miijs 2.5.0 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/amiiboHandler.js CHANGED
@@ -1,56 +1,16 @@
1
- const crypto = require('crypto');
2
1
 
3
- /*This constant is provided SOLELY because I cannot find a guide online to retrieve this file from a console or Amiibo on your own that doesn't just tell you to download it from somewhere anyway.
4
- If someone can find, or make, a guide for this, I will wipe all commits of this key from the repo and instead point to how to get this key for yourself.*/
5
- const MASTER_KEY_BUFFER = Buffer.from('1D164B375B72A55728B91D64B6A3C205756E666978656420696E666F7300000EDB4B9E3F45278F397EFF9B4FB9930000044917DC76B49640D6F83939960FAED4EF392FAAB21428AA21FB54E5450547667F752D2873A20017FEF85C0575904B6D6C6F636B656420736563726574000010FDC8A07694B89E4C47D37DE8CE5C74C1044917DC76B49640D6F83939960FAED4EF392FAAB21428AA21FB54E545054766', 'hex');
2
+ // Takes Amiibo dumps that are either 532 bytes or 540 bytes, and manipulates a 96 byte (C/F)FSD Mii in/out of the dump from offset 0x4C.
6
3
 
7
- const DATA_HMAC_KEY = MASTER_KEY_BUFFER.slice(0, 16);
8
- const DATA_TYPE_STRING = MASTER_KEY_BUFFER.slice(16, 30);
9
- const DATA_MAGIC_BYTES_SIZE = MASTER_KEY_BUFFER[31];
10
- const DATA_MAGIC_BYTES = MASTER_KEY_BUFFER.slice(32, 48);
11
- const DATA_XOR_PAD = MASTER_KEY_BUFFER.slice(48, 80);
12
-
13
- const TAG_HMAC_KEY = MASTER_KEY_BUFFER.slice(80, 96);
14
- const TAG_TYPE_STRING = MASTER_KEY_BUFFER.slice(96, 110);
15
- const TAG_MAGIC_BYTES_SIZE = MASTER_KEY_BUFFER[111];
16
- const TAG_MAGIC_BYTES = MASTER_KEY_BUFFER.slice(112, 128);
17
- const TAG_XOR_PAD = MASTER_KEY_BUFFER.slice(128, 160);
4
+ const { Buffer } = require('buffer');
5
+ const isBrowser = typeof window !== 'undefined' && typeof window.crypto !== 'undefined';
6
+ const isNode = typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
7
+ const nodeCrypto = isNode ? require('crypto') : null;
8
+ const subtleCrypto = (typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.subtle)
9
+ ? globalThis.crypto.subtle
10
+ : (nodeCrypto && nodeCrypto.webcrypto ? nodeCrypto.webcrypto.subtle : null);
18
11
 
19
12
  const NFC3D_AMIIBO_SIZE = 520;
20
- const NTAG215_SIZE = 540;
21
- const NTAG215_SIZE_ALT = 532;
22
-
23
- const MII_OFFSET_DECRYPTED = 0x4C;
24
- const MII_SIZE = 96;
25
-
26
- //Calculate CRC16 checksum for Mii data (for Amiibo format)
27
- function calculateMiiChecksum(data) {
28
- const checksumData = data.slice(0, 94);
29
- let crc = 0;
30
- for (let byteIndex = 0; byteIndex < checksumData.length; byteIndex++) {
31
- for (let bitIndex = 7; bitIndex >= 0; bitIndex--) {
32
- crc = (((crc << 1) | ((checksumData[byteIndex] >> bitIndex) & 0x1)) ^
33
- (((crc & 0x8000) !== 0) ? 0x1021 : 0)) & 0xFFFF;
34
- }
35
- }
36
- for (let counter = 16; counter > 0; counter--) {
37
- crc = ((crc << 1) ^ (((crc & 0x8000) !== 0) ? 0x1021 : 0)) & 0xFFFF;
38
- }
39
- return crc & 0xFFFF;
40
- }
41
13
 
42
- //Validate and fix Mii checksum - for 96-byte Amiibo format
43
- function validateAndFixMiiChecksum(miiData) {
44
- if (miiData.length !== 92 && miiData.length !== MII_SIZE) {
45
- throw new Error(`Invalid Mii data size: expected 92 or ${MII_SIZE} bytes, got ${miiData.length}`);
46
- }
47
- const fullMii = Buffer.alloc(MII_SIZE);
48
- miiData.slice(0, Math.min(94, miiData.length)).copy(fullMii, 0);
49
- const newChecksum = calculateMiiChecksum(fullMii);
50
- fullMii[94] = (newChecksum >> 8) & 0xFF;
51
- fullMii[95] = newChecksum & 0xFF;
52
- return fullMii;
53
- }
54
14
  function calcSeed(dump) {
55
15
  const seed = Buffer.alloc(64);
56
16
  dump.slice(0x029, 0x02B).copy(seed, 0x00);
@@ -89,7 +49,7 @@ function drbgGenerateBytes(hmacKey, seed, outputSize) {
89
49
  iterBuffer[0] = (iteration >> 8) & 0xFF;
90
50
  iterBuffer[1] = iteration & 0xFF;
91
51
  seed.copy(iterBuffer, 2);
92
- const hmac = crypto.createHmac('sha256', hmacKey);
52
+ const hmac = nodeCrypto.createHmac('sha256', hmacKey);
93
53
  hmac.update(iterBuffer);
94
54
  const output = hmac.digest();
95
55
  const toCopy = Math.min(32, outputSize - offset);
@@ -99,7 +59,6 @@ function drbgGenerateBytes(hmacKey, seed, outputSize) {
99
59
  }
100
60
  return result;
101
61
  }
102
-
103
62
  function deriveKeys(typeString, magicBytes, magicBytesSize, xorPad, hmacKey, baseSeed) {
104
63
  const preparedSeed = prepareSeed(typeString, magicBytes, magicBytesSize, xorPad, baseSeed);
105
64
  const derived = drbgGenerateBytes(hmacKey, preparedSeed, 48);
@@ -121,7 +80,6 @@ function tagToInternal(tag) {
121
80
  tag.slice(0x054, 0x080).copy(internal, 0x1DC);
122
81
  return internal;
123
82
  }
124
-
125
83
  function internalToTag(internal) {
126
84
  const tag = Buffer.alloc(NFC3D_AMIIBO_SIZE);
127
85
  internal.slice(0x000, 0x008).copy(tag, 0x008);
@@ -137,41 +95,40 @@ function internalToTag(internal) {
137
95
  function decryptAmiibo(tag) {
138
96
  const internal = tagToInternal(tag);
139
97
  const seed = calcSeed(internal);
140
- const dataKeys = deriveKeys(DATA_TYPE_STRING, DATA_MAGIC_BYTES, DATA_MAGIC_BYTES_SIZE, DATA_XOR_PAD, DATA_HMAC_KEY, seed);
141
- const tagKeys = deriveKeys(TAG_TYPE_STRING, TAG_MAGIC_BYTES, TAG_MAGIC_BYTES_SIZE, TAG_XOR_PAD, TAG_HMAC_KEY, seed);
98
+ const dataKeys = deriveKeys(Buffer.from("756E666978656420696E666F7300",'hex'), Buffer.from("DB4B9E3F45278F397EFF9B4FB9930000",'hex'), 14, Buffer.from("044917DC76B49640D6F83939960FAED4EF392FAAB21428AA21FB54E545054766",'hex'), Buffer.from("1D164B375B72A55728B91D64B6A3C205",'hex'), seed);
99
+ const tagKeys = deriveKeys(Buffer.from("6C6F636B65642073656372657400",'hex'), Buffer.from("FDC8A07694B89E4C47D37DE8CE5C74C1",'hex'), 16, Buffer.from("044917DC76B49640D6F83939960FAED4EF392FAAB21428AA21FB54E545054766",'hex'), Buffer.from("7F752D2873A20017FEF85C0575904B6D",'hex'), seed);
142
100
  const plain = Buffer.alloc(NFC3D_AMIIBO_SIZE);
143
- const cipher = crypto.createDecipheriv('aes-128-ctr', dataKeys.aesKey, dataKeys.aesIV);
101
+ const cipher = nodeCrypto.createDecipheriv('aes-128-ctr', dataKeys.aesKey, dataKeys.aesIV);
144
102
  cipher.setAutoPadding(false);
145
103
  const decrypted = cipher.update(internal.slice(0x02C, 0x1B4));
146
104
  decrypted.copy(plain, 0x02C);
147
105
  internal.slice(0x000, 0x008).copy(plain, 0x000);
148
106
  internal.slice(0x028, 0x02C).copy(plain, 0x028);
149
107
  internal.slice(0x1D4, 0x208).copy(plain, 0x1D4);
150
- const tagHmac = crypto.createHmac('sha256', tagKeys.hmacKey);
108
+ const tagHmac = nodeCrypto.createHmac('sha256', tagKeys.hmacKey);
151
109
  tagHmac.update(plain.slice(0x1D4, 0x208));
152
110
  const computedTagHmac = tagHmac.digest();
153
111
  computedTagHmac.copy(plain, 0x1B4);
154
- const dataHmac = crypto.createHmac('sha256', dataKeys.hmacKey);
112
+ const dataHmac = nodeCrypto.createHmac('sha256', dataKeys.hmacKey);
155
113
  dataHmac.update(plain.slice(0x029, 0x208));
156
114
  const computedDataHmac = dataHmac.digest();
157
115
  computedDataHmac.copy(plain, 0x008);
158
116
  return plain;
159
117
  }
160
-
161
118
  function encryptAmiibo(plain) {
162
119
  const seed = calcSeed(plain);
163
- const dataKeys = deriveKeys(DATA_TYPE_STRING, DATA_MAGIC_BYTES, DATA_MAGIC_BYTES_SIZE, DATA_XOR_PAD, DATA_HMAC_KEY, seed);
164
- const tagKeys = deriveKeys(TAG_TYPE_STRING, TAG_MAGIC_BYTES, TAG_MAGIC_BYTES_SIZE, TAG_XOR_PAD, TAG_HMAC_KEY, seed);
120
+ const dataKeys = deriveKeys(Buffer.from("756E666978656420696E666F7300",'hex'), Buffer.from("DB4B9E3F45278F397EFF9B4FB9930000",'hex'), 14, Buffer.from("044917DC76B49640D6F83939960FAED4EF392FAAB21428AA21FB54E545054766",'hex'), Buffer.from("1D164B375B72A55728B91D64B6A3C205",'hex'), seed);
121
+ const tagKeys = deriveKeys(Buffer.from("6C6F636B65642073656372657400",'hex'), Buffer.from("FDC8A07694B89E4C47D37DE8CE5C74C1",'hex'), 16, Buffer.from("044917DC76B49640D6F83939960FAED4EF392FAAB21428AA21FB54E545054766",'hex'), Buffer.from("7F752D2873A20017FEF85C0575904B6D",'hex'), seed);
165
122
  const cipher_internal = Buffer.alloc(NFC3D_AMIIBO_SIZE);
166
- const tagHmac = crypto.createHmac('sha256', tagKeys.hmacKey);
123
+ const tagHmac = nodeCrypto.createHmac('sha256', tagKeys.hmacKey);
167
124
  tagHmac.update(plain.slice(0x1D4, 0x208));
168
125
  tagHmac.digest().copy(cipher_internal, 0x1B4);
169
- const dataHmac = crypto.createHmac('sha256', dataKeys.hmacKey);
126
+ const dataHmac = nodeCrypto.createHmac('sha256', dataKeys.hmacKey);
170
127
  dataHmac.update(plain.slice(0x029, 0x1B4));
171
128
  dataHmac.update(cipher_internal.slice(0x1B4, 0x1D4));
172
129
  dataHmac.update(plain.slice(0x1D4, 0x208));
173
130
  dataHmac.digest().copy(cipher_internal, 0x008);
174
- const aesCipher = crypto.createCipheriv('aes-128-ctr', dataKeys.aesKey, dataKeys.aesIV);
131
+ const aesCipher = nodeCrypto.createCipheriv('aes-128-ctr', dataKeys.aesKey, dataKeys.aesIV);
175
132
  aesCipher.setAutoPadding(false);
176
133
  const encrypted = aesCipher.update(plain.slice(0x02C, 0x1B4));
177
134
  encrypted.copy(cipher_internal, 0x02C);
@@ -182,54 +139,23 @@ function encryptAmiibo(plain) {
182
139
  }
183
140
 
184
141
  //Extract Mii data from an Amiibo dump
185
- function extractMiiFromAmiibo(amiiboDump) {
186
- if (!Buffer.isBuffer(amiiboDump)) {
187
- throw new Error('Amiibo dump must be a Buffer');
188
- }
189
- const size = amiiboDump.length;
190
- if (size !== NFC3D_AMIIBO_SIZE && size !== NTAG215_SIZE && size !== NTAG215_SIZE_ALT) {
191
- throw new Error(`Invalid Amiibo dump size: ${size} (expected ${NFC3D_AMIIBO_SIZE}, ${NTAG215_SIZE_ALT}, or ${NTAG215_SIZE})`);
192
- }
193
- const tag = amiiboDump.slice(0, NFC3D_AMIIBO_SIZE);
142
+ function extractMiiFromAmiibo(dump) {
143
+ const tag = dump.slice(0, NFC3D_AMIIBO_SIZE);
194
144
  const decrypted = decryptAmiibo(tag);
195
-
196
- // Extract only the first 92 bytes (the actual Mii data, without checksum)
197
- const miiData = decrypted.slice(MII_OFFSET_DECRYPTED, MII_OFFSET_DECRYPTED + 92);
198
-
145
+ const miiData = decrypted.slice(76, 172);// Extract the 96 Bytes (C/F)FSD Mii
199
146
  return Buffer.from(miiData);
200
147
  }
201
148
 
202
149
  //Insert Mii data into an Amiibo dump
203
- function insertMiiIntoAmiibo(amiiboDump, miiData) {
204
- if (!Buffer.isBuffer(amiiboDump)) {
205
- throw new Error('Amiibo dump must be a Buffer');
206
- }
207
- if (!Buffer.isBuffer(miiData)) {
208
- throw new Error('Mii data must be a Buffer');
209
- }
210
- const size = amiiboDump.length;
211
- if (size !== NFC3D_AMIIBO_SIZE && size !== NTAG215_SIZE && size !== NTAG215_SIZE_ALT) {
212
- throw new Error(`Invalid Amiibo dump size: ${size}`);
213
- }
214
- if (miiData.length !== 92 && miiData.length !== MII_SIZE) {
215
- throw new Error(`Mii data must be 92 or ${MII_SIZE} bytes, got ${miiData.length}`);
216
- }
217
- const tag = amiiboDump.slice(0, NFC3D_AMIIBO_SIZE);
218
- const decrypted = decryptAmiibo(tag);
219
-
220
- // Validate and fix Mii checksum, ensuring it's 96 bytes with correct checksum
221
- const miiWithChecksum = validateAndFixMiiChecksum(miiData);
222
-
223
- // Insert Mii data (96 bytes)
224
- miiWithChecksum.copy(decrypted, MII_OFFSET_DECRYPTED);
225
-
226
- const encrypted = encryptAmiibo(decrypted);
227
- const result = Buffer.alloc(size);
150
+ function insertMiiIntoAmiibo(dump, miiWithChecksum) {
151
+ const decrypted = decryptAmiibo(dump.slice(0, NFC3D_AMIIBO_SIZE));//Decrypt the Amiibo
152
+ miiWithChecksum.copy(decrypted, 76);//Insert the Mii into Amiibo
153
+ const encrypted = encryptAmiibo(decrypted);//Reencrypt the Amiibo
154
+ const result = Buffer.alloc(dump.length);
228
155
  encrypted.copy(result, 0);
229
- if (size > NFC3D_AMIIBO_SIZE) {
230
- amiiboDump.slice(NFC3D_AMIIBO_SIZE).copy(result, NFC3D_AMIIBO_SIZE);
156
+ if (dump.length > NFC3D_AMIIBO_SIZE) {
157
+ dump.slice(NFC3D_AMIIBO_SIZE).copy(result, NFC3D_AMIIBO_SIZE);
231
158
  }
232
-
233
159
  return result;
234
160
  }
235
161
 
package/asmCrypto.js CHANGED
@@ -3598,22 +3598,30 @@ function BigNumber_extGCD(a, b) {
3598
3598
  }
3599
3599
 
3600
3600
  function getRandomValues(buf) {
3601
- if (typeof process !== 'undefined') {
3602
- var nodeCrypto = require('crypto');
3603
- var bytes = nodeCrypto.randomBytes(buf.length);
3604
- buf.set(bytes);
3605
- return;
3601
+ if (typeof process !== 'undefined' && typeof require === 'function') {
3602
+ try {
3603
+ var nodeCrypto = eval('require')('crypto');
3604
+ var bytes = nodeCrypto.randomBytes(buf.length);
3605
+ buf.set(bytes);
3606
+ return;
3607
+ } catch (e) {
3608
+ // Fall through to browser methods
3609
+ }
3606
3610
  }
3607
- if (window.crypto && window.crypto.getRandomValues) {
3611
+ if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
3608
3612
  window.crypto.getRandomValues(buf);
3609
3613
  return;
3610
3614
  }
3611
- if (self.crypto && self.crypto.getRandomValues) {
3615
+ if (typeof self !== 'undefined' && self.crypto && self.crypto.getRandomValues) {
3612
3616
  self.crypto.getRandomValues(buf);
3613
3617
  return;
3614
3618
  }
3619
+ if (typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.getRandomValues) {
3620
+ globalThis.crypto.getRandomValues(buf);
3621
+ return;
3622
+ }
3615
3623
  // @ts-ignore
3616
- if (window.msCrypto && window.msCrypto.getRandomValues) {
3624
+ if (typeof window !== 'undefined' && window.msCrypto && window.msCrypto.getRandomValues) {
3617
3625
  // @ts-ignore
3618
3626
  window.msCrypto.getRandomValues(buf);
3619
3627
  return;