Great work!
And here's a version without brute force.
/*
** 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[]="8..."; // <- 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 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 * find_match5(unsigned char *code5)
{
unsigned long long b=0;
unsigned char *out;
int i=0;
out=calloc(5,1);
// hex2dez
while (code5[i] != '\0') {
if (code5[i]>='1' && code5[i]<='9')
b=b*16+code5[i]-'0';
else if (code5[i]>='A' && code5[i]<='F')
b=b*16+code5[i]-'A'+10;
else if (code5[i]>='a' && code5[i]<='f')
b=b*16+code5[i]-'a'+10;
i++;
}
for (i=3;;i--) {
out[i]=vb[b & 0x1F];
if (i==0) break;
b>>=5;
}
out[4]='\0';
return(out);
}
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);
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
// run for 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");
}