Studio25:
I can confirm it works now on my 32bit Ubuntu VM
It yielded a different code compared with Cybernet's brute force code.
(checks right now....uninstalls already working code from Cybernet
sends ":SYST:OPT:UNINST"+"\n"
yep no options any more ..
sends code generated by your program
"License is unavailable" hmmm
loads code from Cybernet
"option installed")
So there still seems to be problems.
if you like I can PM you my DS2072 serial no. and the two generated codes used.
Ok, I have code running that works on Windows with a GUI. It produces the same key output as cybernet's code. But for some reason on my scope it won't take an official DSAZ code. If I just switch the DSAZ to VSAZ, it resets the trial option time (except the 200M time is different.)
I've compared the output with a copy running on Ubuntu 32-bit, all the outputs match. I've noticed that when I use DSAZ, my lic2-code is one character short. I'll fiddle with it a bit more in the morning.
Ok, I have code running that works on Windows with a GUI. It produces the same key output as cybernet's code. But for some reason on my scope it won't take an official DSAZ code. If I just switch the DSAZ to VSAZ, it resets the trial option time (except the 200M time is different.)
I've compared the output with a copy running on Ubuntu 32-bit, all the outputs match. I've noticed that when I use DSAZ, my lic2-code is one character short. I'll fiddle with it a bit more in the morning.
Try changing the seed, that has worked for me and is why the web generator has the seed field.
I tried changing the seed a couple times, but my scope was in some kind of lockdown from trying bad keys at the time and I didn't notice. I'll have to try it again tomorrow.
Is there any reason that I shouldn't just generate a psuedorandom seed every time in the app?
I tried changing the seed a couple times, but my scope was in some kind of lockdown from trying bad keys at the time and I didn't notice. I'll have to try it again tomorrow.
Is there any reason that I shouldn't just generate a psuedorandom seed every time in the app?
Repeatability. If you don't care about it you can make it random.
okay, can see some code difference between the linux64 and linux32 bit of source that gets copied to mrmuldv.s that would stop it working on the AMD64bit CPU's, so question is how are people getting their codes to work / load on such machines ?
anyway. have built a windows command line version ( aka cygwin ) it doesn't need cygwin installed or setup of course, just a normal cmd window.
generates the same codes as cybernets brute force code. which have worked on my scope.
Darryl
okay, can see some code difference between the linux64 and linux32 bit of source that gets copied to mrmuldv.s that would stop it working on the AMD64bit CPU's, so question is how are people getting their codes to work / load on such machines ?
of course there are diffs, they for different CPUs. The mrmuldv.s used on Rigol should be different as well.
okay, can see some code difference between the linux64 and linux32 bit of source that gets copied to mrmuldv.s that would stop it working on the AMD64bit CPU's, so question is how are people getting their codes to work / load on such machines ?
of course there are diffs, they for different CPUs. The mrmuldv.s used on Rigol should be different as well.
no, i'm meaning,the use of mulq, which produces a 64 bit result, the 32bit when doing mull will not produce an overflow of two unsigned uint32_t types, the 64 bit version however can and will return different values. if the X or Y values are too big.
Darryl
if somebody wants to fix the lic1/lic2 code, it should be left padded with 0 to size 14 when it comes out of ecssign.
e.g. if its to short, 0<code> ...00<code> ... whatever is missing to make it 14 chars - i was just too lazy for that - that should then provide valid serial all the time.
HI
looks like I'm one of the lucky or unlucky , can't decide.
I used the LLLLLLL-RLGLLDS-DSA9LLL-LLLLLLL code and now my 2072 is stuck as a 2012.
tired the USB spi uninstall ,rolled back the firmware generated a new key and they don't install, though this maybe me.
Reading the thread I don't think I'm the only one in this situation ? I'm trying to approach this logically and reading the thread , but there is so much there now, hints appreciated.
PS this is an early scope delivery was about August 2012
your serial is probably DS2A........1 - check in the system info - if so welcome to the club, best serial anyway ;-) - so you need to adapt the serial when generating a key
Good day Sir,
I am a beginner and your thread for me is very tricky. I have a Rigol DS 2102 oscilloscope. Firstly I would like to activate the option and secondly I want to convert this Rigol into a Rigol DS 2202. Can you tell me very clear what should I do to convert it?
My Firmware is 00.00.01.00.02
Hardware is 1.1.0.0
I bought this item from e-bay one month ago.
Cheers
if somebody wants to fix the lic1/lic2 code, it should be left padded with 0 to size 14 when it comes out of ecssign.
e.g. if its to short, 0<code> ...00<code> ... whatever is missing to make it 14 chars - i was just too lazy for that - that should then provide valid serial all the time.
Yes, that was the problem, I didn't get a complete license code for the DSAZ option, and in that calculation my lic2 was only 13 chars long.
I did a strrev/strcat/strrev on it and now I got a working DSAZ and my DS2102 became a DS2202.
My serialno is still intact, if someone wonders.
I had the DSAR option installed already, I tried uninstalling it with :SYSTEM:OPTION:UNINSTALL (both with and without the license code as parameter), but nothing happened.
So I have both DSAR and DSAZ activated, and my "Installed Options"-list shows both of these at the bottom of the list:
BANDWIDTH 100M BandWidth Offcial Version
BANDWIDTH 200M BandWidth Offcial Version
Is this how it's supposed to show up on a DS2202, or should I do something to make the scope only show the 200M option?
Is this how it's supposed to show up on a DS2202, or should I do something to make the scope only show the 200M option?
I've seen both listed when using the LLLLL type keys and I was trying the various combinations. But i only "upgraded" my scope so that it only shows the 200 bandwidth line. My testing last evening shows everything functional. Just the installed options don't show the 100 line now, can still bandwidth limit each channel to the 20 & 100 as well as OFF.
--
Darryl
received yet another mail from "some guy" - thanks when u read this
he pointed out a reason why some lic codes are failing, and that guy knows what he is talking about ;-)
see below:
As prime2 is no prime-number (its prime-factors are [17, 53, 905461,
60291817]) it is possible that the generated s (lic2) is divisible
by one of these factors which will lead to an invalid license key.
This can be detected in ecssign with something like:
int prime2_factors[] = {17, 53, 905461, 60291817};
int i;
big tmp;
tmp = mirvar(0);
for (i = 0; i < (sizeof(prime2_factors) / sizeof(prime2_factors[0])); i++) {
lgconv(prime2_factors[i], tmp);
if (divisible(s, tmp)) {
//increment seed and redo signing
...
}
}
Way to go cybernet's secret source and true!
My issue was a combination of the leading zero *and* the seed (everything that can go wrong, will). I'm going to see what it takes to implement a button that applies the key and finish out a couple things.
Way to go cybernet's secret source and true!
My issue was a combination of the leading zero *and* the seed (everything that can go wrong, will). I'm going to see what it takes to implement a button that applies the key and finish out a couple things.
I would love to see a possibility in your application that leaves the option code open for keys like DSA9....
I would love to see a possibility in your application that leaves the option code open for keys like DSA9....
Looks like I won't have time to put in the key loading button, but I'll put an option code override in since it makes sense.
if somebody wants to fix the lic1/lic2 code, it should be left padded with 0 to size 14 when it comes out of ecssign.
e.g. if its to short, 0<code> ...00<code> ... whatever is missing to make it 14 chars - i was just too lazy for that - that should then provide valid serial all the time.
Yes, that was the problem, I didn't get a complete license code for the DSAZ option, and in that calculation my lic2 was only 13 chars long.
I did a strrev/strcat/strrev on it and now I got a working DSAZ and my DS2102 became a DS2202.
My serialno is still intact, if someone wonders.
I had the DSAR option installed already, I tried uninstalling it with :SYSTEM:OPTION:UNINSTALL (both with and without the license code as parameter), but nothing happened.
So I have both DSAR and DSAZ activated, and my "Installed Options"-list shows both of these at the bottom of the list:
BANDWIDTH 100M BandWidth Offcial Version
BANDWIDTH 200M BandWidth Offcial Version
Is this how it's supposed to show up on a DS2202, or should I do something to make the scope only show the 200M option?
Here you go Linux adepts!
/*
** rigol ds2000 keygen / cybernet & the-eevblog-users
**
** to compile this you need MIRACL from [url]https://github.com/CertiVox/MIRACL[/url]
** download the master.zip into a new folder and run 'unzip -j -aa -L master.zip'
** then run 'bash linux' to build the miracle.a library
**
** BUILD WITH:
**
** gcc rikey.c -I../MIRACL ../MIRACL/miracl.a -o rikey
**
** adapt -I and path to miracl.a to your environment
**
** more info: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/
**
** then fetch private key from EEV Blog and put into "private_key[]=" below, do not prefix with 0x
** supply your serial and wanted options, and enjoy !
**
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "miracl.h"
#define RIGOL_DS2000
// START OF SETTINGS FOR ECC
#ifdef RIGOL_DS2000
unsigned char private_key[]="8EE"; // <- RILOL FILL ME (no 0x prefix !)
unsigned char prime1[]="AEBF94CEE3E707";
unsigned char prime2[]="AEBF94D5C6AA71";
unsigned char curve_a[]="2982";
unsigned char curve_b[]="3408";
unsigned char point1[]="7A3E808599A525";
unsigned char point2[]="28BE7FAFD2A052";
#endif
// END OF SETTINGS FOR ECC
unsigned char codemap_ee00d0[]={ 0x0, 0x0, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2,
0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x8, 0x9, 0xa, 0xb,
0xc, 0x0, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15,0x16, 0x17 };
unsigned char codemap_20688e[]={ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, /* 0-9 = 0x30 */
0x37, 0x37, 0x37, 0x37, 0x37, 0x37 }; /* A-F = 0x37 */
unsigned char vb[]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9'};
void show_help(void)
{
printf("./rikey <DSA2XXXXXXXXX> <OPTS>\n\n");
printf("<DSA2XXXXXXXXX> - serial number of device\n");
printf("<OPTS> - \n");
printf("\t\tDSA? for permanent options\n");
printf("\t\tVSA? for temporary options\n");
printf("\n\n");
}
/*
** take serial and options make sha1 hash out of it
*/
static void hashing(unsigned char *opt_str,big hash)
{ /* compute hash function */
char *p;
char h[20];
int ch;
sha sh;
shs_init(&sh);
p=opt_str;
while(*p)
{
shs_process(&sh,*p);
p++;
}
shs_hash(&sh,h);
bytes_to_big(20,h,hash);
}
/*
** sign the secret message (serial + opts) with the private key
*/
int ecssign(unsigned char *serial, unsigned char *opt, unsigned char *lic1, unsigned char *lic2)
{
FILE *fp;
char ifname[50],ofname[50];
big a,b,p,q,x,y,d,r,s,k,hash;
epoint *g;
long seed;
int bits;
miracl *mip;
unsigned char *serial_options;
/* get public data */
mip=mirsys(0x320, 0x10); /* Use Hex internally */
mip->IOBASE=16;
a=mirvar(0);
b=mirvar(0);
p=mirvar(0);
q=mirvar(0);
x=mirvar(0);
y=mirvar(0);
d=mirvar(0);
r=mirvar(0);
s=mirvar(0);
k=mirvar(0);
hash=mirvar(0);
instr(p,prime1); /* modulus */
instr(a,curve_a); /* curve parameters */
instr(b,curve_b);
instr(q,prime2); /* order of (x,y) */
instr(x,point1); /* (x,y) point on curve of order q */
instr(y,point2);
/* randomise */
seed=1;
irand(seed);
ecurve_init(a,b,p,MR_PROJECTIVE); /* initialise curve */
g=epoint_init();
if (!epoint_set(x,y,0,g)) /* initialise point of order q */
{
printf("1. Problem - point (x,y) is not on the curve\n");
exit(0);
}
/* calculate r - this can be done offline,
and hence amortized to almost nothing */
bigrand(q,k);
ecurve_mult(k,g,g); /* see ebrick.c for method to speed this up */
epoint_get(g,r,r);
divide(r,q,q);
/* get private key of signer */
instr(d, private_key);
/* calculate message digest */
serial_options=calloc(128,1);
strcpy(serial_options, serial);
strcat(serial_options, opt);
hashing(serial_options,hash);
/* calculate s */
xgcd(k,q,k,k,k);
mad(d,r,hash,q,q,s);
mad(s,k,k,q,q,s);
cotstr(r,lic1);
cotstr(s,lic2);
return 0;
}
/*
** convert string to uppercase chars
*/
unsigned char *strtoupper(unsigned char *str)
{
unsigned char *newstr, *p;
p = newstr = (unsigned char*) strdup((char*)str);
while((*p++=toupper(*p)));
return newstr;
}
/*
**
*/
unsigned char code_map_206846(unsigned char i)
{
if ((i >= 'A') && (i <= 'F')) return(i-0x37);
if ((i >= '0') && (i <= '9')) return(i-0x30);
return(0x0);
}
/*
** Encryption Routine 1
*/
unsigned char *lic_code_map(unsigned char *lic_skipped)
{
unsigned char lv1,lv2;
unsigned char b1_mapped, b1_shifted, b1_remapped;
unsigned char b2_mapped, b2_shifted, b2_remapped;
unsigned char b3_mapped, b3_shifted, b3_remapped;
unsigned char b4_mapped, b4_shifted, b4_remapped;
unsigned char b5_shifted, b5_remapped;
unsigned char *lic_mapbytes;
lic_mapbytes=calloc(28, 1);
if (!lic_mapbytes) return(0);
lv1=lv2=0;
while(lv1 < strlen((unsigned char*)lic_skipped))
{
b1_mapped = codemap_ee00d0[ *(lic_skipped+lv1) - 0x30 ];
b1_shifted = (b1_mapped / 2) & 0xf;
b1_remapped = b1_shifted + codemap_20688e[b1_shifted];
lic_mapbytes[lv2++]=b1_remapped;
b1_mapped = b1_mapped & 0x1;
b2_mapped = codemap_ee00d0[ *(lic_skipped+lv1+1) - 0x30 ];
b2_shifted = ((b1_mapped << 0x3) | (b2_mapped / 4)) & 0xF;
b2_remapped = b2_shifted + codemap_20688e[b2_shifted];
lic_mapbytes[lv2++]=b2_remapped;
b3_mapped = codemap_ee00d0[ *(lic_skipped+lv1+2) - 0x30 ];
b3_shifted = ((b3_mapped / 8) | ( (b2_mapped & 0x3) << 2 )) & 0xF;
b3_remapped = b3_shifted + codemap_20688e[b3_shifted];
lic_mapbytes[lv2++]=b3_remapped;
b4_mapped = codemap_ee00d0[ *(lic_skipped+lv1+3) - 0x30 ];
b4_shifted = ((b4_mapped / 16 ) |((b3_mapped & 0x7) << 0x1)) & 0xf;
b4_remapped = b4_shifted + codemap_20688e[b4_shifted];
lic_mapbytes[lv2++]=b4_remapped;
b5_shifted = b4_mapped & 0xF;
b5_remapped = b5_shifted + codemap_20688e[b5_shifted];
lic_mapbytes[lv2++]=b5_remapped;
lv1 = lv1 + 4;
}
return(lic_mapbytes);
}
unsigned char * find_match5(unsigned char *code5)
{
unsigned char c1,c2,c3,c4;
unsigned char *input;
unsigned char *lic_mapbytes;
input=calloc(40,1);
/* lets bruteforce it ;-) */
for (c1=0;c1<sizeof(vb);c1++) {
for (c2=0;c2<sizeof(vb);c2++) {
for (c3=0;c3<sizeof(vb);c3++) {
for (c4=0;c4<sizeof(vb);c4++) {
input[0]=vb[c1];
input[1]=vb[c2];
input[2]=vb[c3];
input[3]=vb[c4];
input[4]='\0';
lic_mapbytes=lic_code_map(input);
if (!strcmp(lic_mapbytes, code5))
{
return(input);
}
}
}
}
}
return(0); // no match
}
char *strrev(char *str)
{
char *p1, *p2;
if (! str || ! *str)
return str;
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return str;
}
int main(int argc, char *argv[0])
{
unsigned char *options,*lic1_code, *lic2_code, *lic_all;
unsigned char *out,*chunk,*temp,*final;
unsigned char *lic1_key, *lic2_key;
unsigned char *serial;
int v,i=0;
if (strlen(private_key)<14)
{
printf("\n\n");
printf("set the private_key variable on top of this file\n");
printf("you can find it here: https://www.eevblog.com/forum/testgear/sniffing-the-rigol's-internal-i2c-bus/msg264690/#msg264690\n");
printf("\n\n");
exit(-1);
}
if (argc != 3)
{
show_help();
exit(-1);
}
serial=strtoupper((unsigned char*)argv[1]);
options=strtoupper((unsigned char*)argv[2]);
if (strlen(serial)<13)
{
printf("\nINVALID SERIAL LENGTH\n");
show_help();
exit(-1);
}
if (strlen(options)!=4)
{
printf("\nINVALID OPTIONS LENGTH\n");
show_help();
exit(-1);
}
printf("serial: %s\n", serial);
printf("options: %s\n", options);
/* sign the message */
lic1_code=calloc(64,1);
lic2_code=calloc(64,1);
ecssign(serial,options,lic1_code, lic2_code);
if (strlen(lic2_code)==13)
{
strrev(lic2_code);
strcat(lic2_code, "0");
strrev(lic2_code);
}
if (strlen(lic1_code)==13)
{
strrev(lic1_code);
strcat(lic1_code, "0");
strrev(lic1_code);
}
printf("lic1-code: %s\n", lic1_code);
printf("lic2-code: %s\n", lic2_code);
lic_all=calloc(128,1);
temp=calloc(128,1);
chunk=calloc(6,1);
final=calloc(128,1);
lic1_key=calloc(20,1);
lic2_key=calloc(20,1);
strcpy(lic_all, lic1_code);
strcat(lic_all, "0");
strcat(lic_all, lic2_code);
printf("target-code: %s\n", lic_all);
// split in 5 byte groups and run bruteforce
// run or lic1_code
strcat(lic1_code,"0");
while(i<=strlen(lic1_code))
{
memcpy(chunk,lic1_code+i,5);
out=find_match5(chunk);
if (out)
{
strcat(temp, out);
}
i=i+5;
}
strcpy(lic1_key, temp);
// run for lic2_code
strcpy(temp,"");
i=0;
while(i<strlen(lic2_code))
{
memcpy(chunk,lic2_code+i,5);
if (strlen(chunk)<5)
{
for(v=0;v<5-strlen(chunk);v++)
strcat(chunk,"0");
}
out=find_match5(chunk);
if (out)
{
strcat(temp, out);
}
i=i+5;
}
strcpy(lic2_key, temp);
strcpy(temp, lic1_key);
strcat(temp, lic2_key);
// now add the options
memcpy(final, temp, 1);
final[1]=options[0];
memcpy(final+2, temp+1,7);
final[9]=options[1];
memcpy(final+10, temp+8,7);
final[17]=options[2];
memcpy(final+18, temp+15,7);
final[25]=options[3];
memcpy(final+26, temp+22,4);
printf("----------------------------------------------------\n");
printf("your-license-key: ");
for(i=0;i<strlen(final);i++)
{
if (i%7==0 && i>0) printf("-");
printf("%c", final[i]);
}
printf("\n");
printf("----------------------------------------------------\n");
}
DONT USE BELOW, as activates 2102 and also 2202:
2 on on == == ==
3 on on == == on
4 on on == on ==
5 on on == on on
6 on on on == ==
7 on on on == on
8 on on on on ==
9 on on on on on
Great work! I used DSA9 as cybernet recommended and it works fine.
Why do you still recommend not to use DSA9?
As you can see from your paste, It installs 100M and 200M options, which isn't necessary. 200M supersedes 100M anyway. It likely won't bring any troubles but there's no need for it. DSAZ is equivalent.
OK, so having the DSA9 already installed (license key generated with original rikey.c ) - everything Official Version - I sent an UNINSTALL and my scope got back to a normal 2072. I had the serial intact all the time. I had the latest FW installed before initially starting installing licenses.
Then on a 32 bit linux box I created a DSAZ license key with rikey.c - my serial is DS2A...2 and is 13 chars long. I sent it to the scope: verification failed
Then I used the "no_brute_force" version of rikey.c - this created a different license key for DSAZ with the same serial but sending it to the scope yielded: verification failed again
Both lic1 and lic2 keys have always been 14 chars long.
So I stopped here.
Any ideas/explanations/suggestions?
Here's the Windows app.
I tried for quite a while to get it to run under .NET 2.0, but Visual Studio 2010 gimped VC++'s ability to roll back the .NET version. This means it'll require .NET 4.0. 4.0 is 3 years old now, and I've included the web installer in the package.
How to use:
- You enter the private key in the first field. If you don't know where to get it, click the "Information" link.
- Enter the serial number from your scope into the second field.
- Select which options you'd like. The option code will be generated on the fly in the Option Code box. For those of you that want to play with the option codes, you can edit it by hand.
- Click Generate. It will take all the information and generate a key into the textbox.
Note: If User Account Control in Windows complains that it needs permissions, it's because the miracl library and cybernet's part of the code was compiled "unmanaged", and the GUI is "managed." This managed/unmanaged mess is what took so long.
Enjoy.
Edit: I was going to put the source project up on my website, but apparently my site is down. Once I get that figured out, I'll put it up.
Thanks very much synapsis, AND to each and every other EEVBee that has made this possible.
Thank You Again
DONT USE BELOW, as activates 2102 and also 2202:
2 on on == == ==
3 on on == == on
4 on on == on ==
5 on on == on on
6 on on on == ==
7 on on on == on
8 on on on on ==
9 on on on on on
Great work! I used DSA9 as cybernet recommended and it works fine.
Why do you still recommend not to use DSA9?
As you can see from your paste, It installs 100M and 200M options, which isn't necessary. 200M supersedes 100M anyway. It likely won't bring any troubles but there's no need for it. DSAZ is equivalent.
OK, so having the DSA9 already installed (license key generated with original rikey.c ) - everything Official Version - I sent an UNINSTALL and my scope got back to a normal 2072. I had the serial intact all the time. I had the latest FW installed before initially starting installing licenses.
Then on a 32 bit linux box I created a DSAZ license key with rikey.c - my serial is DS2A...2 and is 13 chars long. I sent it to the scope: verification failed
Then I used the "no_brute_force" version of rikey.c - this created a different license key for DSAZ with the same serial but sending it to the scope yielded: verification failed again
Both lic1 and lic2 keys have always been 14 chars long.
So I stopped here.
Any ideas/explanations/suggestions?
OK, so I used cybernet's verification routine on all keys generated. And yes, the result is the same. The DSA9 key generated is VALID, while DSAZ key generated is INVALID against my serial.
Edit:
I changed the seed and now it works. Thanks again.
Sorry for talking to myself in the open
Try changing the seed; the key generated probably starts with 0, there is a 1 in 16 chance of this. I'll post a version that fixes this (Orange's only looks for len 13, but it could start with 00, it's pretty hackish) and is a little more readable later.
Would still love to use an engineering / service menu...