**Reset / Unlock your Nintendo 3DS parental code using this online tool**:

### Explanation

When my niece bought a second-hand 3DS, it had a parental code. I was quite surprised to not find any online tool to unlock it (unlike for wii).

So, based on the code of an unlock tool in C, I decided to write my own in JavaScript.

The main problem is that lot of operations are typed and a lot of them need specific size (uint8, uint32, uint64…).

So, here are some tips to know when you need to deal with these kind of operation.

First one is to know the “>>>” operator (Unsigned Right Shift Operator) and its main limitation (unsigned 32 bits).

A trick with this operator is to convert any value to an unsigned variable

var value = 123 >>> 0;

In the C code, there is a variable which is a uint8_t (8 bits), so, after each operation on it, I simply remove the >8 bits using a mask with 0xff.

Based on these 2 first notes, here is an example of the translated code:

y = 0xFFFFFFFF; x = generator[0]; for(i=0; i<4; i++) { x ^= y; y = table[x] ^ (y>>8); x = generator[1+i*2] ^ y; y = table[x] ^ (y>>8); x = generator[2+i*2]; }

Become

y = 0xFFFFFFFF; x = generator.charCodeAt(0); for(i=0; i<4; i++) { x ^= y; x &= 0xff; // uint8 y = table[x] ^ (y>>>8); x = generator.charCodeAt(1+i*2) ^ y; x &= 0xff; // uint8 y = table[x] ^ (y>>>8); x = generator.charCodeAt(2 + i*2); x &= 0xff; // uint8 }

You’ll notice that *generator[0]* became *generator.charCodeAt(0)*, because *generator* is a string of digit (i.e. 01014545) and generator[0] which is the digit “0” (as string) should be used as 0 (numeric) instead of 48 (ascii 48 = “0”)

The last caveat was in the code:

yhi = (yll>>48);

It is a bit rotation from an unsigned long long int, problem is >>> is limited to 32 bits, so, I had to write a small function to execute this rotation:

function ullRShift(ullValue, shift) { while(shift) { shift--; ullValue = ullValue / 2; } return ullValue >>> 0; }

Here is the full code:

function lpad(s, len, chr) { s += ""; while(s.length < len) { s = chr + s; } return s; } function ullRShift(ullValue, shift) { while(shift) { shift--; ullValue = ullValue / 2; } return ullValue >>> 0; } function calculateMasterKey(generator) { var table = []; var data, i, j, y, x, yll, yhi; for(i=0; i<0x100; i++) { data = i; for(j=0; j<4; j++) { if (data & 1) data = 0xEDBA6320 ^ (data>>>1); else data = data>>>1; if (data & 1) data = 0xEDBA6320 ^ (data>>>1); else data = data>>>1; } table[i] = data; } y = 0xFFFFFFFF; x = generator.charCodeAt(0); for(i=0; i<4; i++) { x ^= y; x &= 0xff; // uint8 y = table[x] ^ (y>>>8); x = generator.charCodeAt(1+i*2) ^ y; x &= 0xff; // uint8 y = table[x] ^ (y>>>8); x = generator.charCodeAt(2 + i*2); x &= 0xff; // uint8 } y ^= 0xAAAA; y += 0x1657; yll = y; yll = (yll+1) * 0xA7C5AC47; yhi = ullRShift(yll, 48); yhi *= 0xFFFFF3CB; y += (yhi<<5); return lpad(y, 5, "0"); } function getMasterKey(servicecode, month, day) { servicecode %= 10000; day %= 100; month %= 100; return calculateMasterKey(lpad(month, 2, "0") + lpad(day, 2, "0") + lpad(servicecode, 4, "0")); }