Optional
even?: numberThe even bits of lfsr.
Optional
odd?: numberThe odd bits of lfsr.
Get the value of lfsr.
lfsr.
const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
const { default: Crypto1 } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/Crypto1.mjs/+esm')
const state1 = new Crypto1()
console.log(state1.setLfsr(new Buffer('FFFFFFFFFFFF')).getLfsr().toString(16)) // 'FFFFFFFFFFFF'
Get the lfsr output bit and update lfsr by input bit.
The input bit.
Indicates whether the input bit is encrypted or not.
The lfsr output bit.
Get the lfsr output byte and update lfsr by input byte.
The input byte.
Indicates whether the input byte is encrypted or not.
The lfsr output byte.
Rollback the lfsr in order to get previous states
The input bit.
Indicates whether the input bit is encrypted or not.
The lfsr output bit.
Rollback the lfsr in order to get previous states
The input byte.
Indicates whether the input byte is encrypted or not.
The lfsr output byte.
Rollback the lfsr in order to get previous states
The 32-bit input word.
Indicates whether the 32-bit input word is encrypted or not.
The lfsr 32-bit output word.
Get the lfsr 32-bit output word and update lfsr by 32-bit input word.
The 32-bit input word.
Indicates whether the 32-bit input word is encrypted or not.
The lfsr 32-bit output word.
Set the internal lfsr with the key.
The key to set the internal lfsr.
Static
darksideRecover the key from the tag with the darkside attack.
An async function to acquire the darkside attack data.
An async function to check the key.
The maximum number of attempts to try.
The recovered key.
// you can run in DevTools of https://taichunmin.idv.tw/chameleon-ultra.js/test.html
await (async ultra => {
const { Buffer, DarksideStatus, DeviceMode, Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
const { default: Crypto1 } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/Crypto1.mjs/+esm')
await ultra.cmdChangeDeviceMode(DeviceMode.READER)
const block = 0
const keyType = Mf1KeyType.KEY_A
const key = await Crypto1.darkside(
async attempt => {
const accquired = await ultra.cmdMf1AcquireDarkside(block, keyType, attempt === 0)
console.log(_.mapValues(accquired, buf => Buffer.isBuffer(buf) ? buf.toString('hex') : buf))
if (acquired.status === DarksideStatus.LUCKY_AUTH_OK) throw new Error('LUCKY_AUTH_OK')
if (acquired.status !== DarksideStatus.OK) throw new Error('card is not vulnerable to Darkside attack')
return accquired
},
async key => {
return await ultra.cmdMf1CheckBlockKey({ block, keyType, key })
},
)
console.log(`key founded: ${key.toString('hex')}`)
})(vm.ultra)
Static
decryptDecrypt the data.
The encrypted data.
The 6-bytes key to decrypt the data.
The calculated response of args.nt
from reader in the authentication.
The nonce from tag in the authentication.
The 4-bytes uid in the authentication.
The decrypted data.
Static
mfkey32A method for Tag to validate Reader has the correct key.
The encrypted prng successor of opts.nt
.
The 6-bytes key to be test.
The encrypted nonce from reader.
The nonce from tag.
The 4-bytes uid of tag.
const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
const { default: Crypto1 } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/Crypto1.mjs/+esm')
console.log(Crypto1.mfkey32IsReaderHasKey({
ar: 'CF0A3C7E',
key: 'A9AC67832330',
nr: 'FEDAC6D2',
nt: '2C198BE4',
uid: '65535D33',
}).toString('hex')) // true
Static
mfkey32v2Recover the key with the two authentication attempts from reader.
The random challenge from reader in the first authentication attempt.
The random challenge from reader in the second authentication attempt.
The calculated nonce response from reader in the first authentication attempt.
The calculated nonce response from reader in the second authentication attempt.
The nonce from tag in the first authentication attempt.
The nonce from tag in the second authentication attempt.
The 4-bytes uid in the authentication attempt.
The recovered key.
const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
const { default: Crypto1 } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/Crypto1.mjs/+esm')
console.log(Crypto1.mfkey32v2({
uid: 0x65535D33,
nt0: 0xCB7B9ED9,
nr0: 0x5A8FFEC6,
ar0: 0x5C7C6F89,
nt1: 0x1E6D9228,
nr1: 0x6FB8B4A8,
ar1: 0xEF4039FB,
}).toString('hex')) // A9AC67832330
console.log(Crypto1.mfkey32v2({
uid: Buffer.fromHex('65535D33'),
nt0: Buffer.fromHex('CB7B9ED9'),
nr0: Buffer.fromHex('5A8FFEC6'),
ar0: Buffer.fromHex('5C7C6F89'),
nt1: Buffer.fromHex('1E6D9228'),
nr1: Buffer.fromHex('6FB8B4A8'),
ar1: Buffer.fromHex('EF4039FB'),
}).toString('hex')) // A9AC67832330
console.log(Crypto1.mfkey32v2({
uid: '65535D33',
nt0: 'CB7B9ED9',
nr0: '5A8FFEC6',
ar0: '5C7C6F89',
nt1: '1E6D9228',
nr1: '6FB8B4A8',
ar1: 'EF4039FB',
}).toString('hex')) // A9AC67832330
Static
mfkey64Recover the key with the successfully authentication between the reader and the tag.
The random challenge from reader in the authentication.
The calculated response of args.ar
from tag in the authentication.
The calculated response of args.nt
from reader in the authentication.
The nonce from tag in the authentication.
The 4-bytes uid in the authentication.
The recovered key.
const { Buffer } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
const { default: Crypto1 } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/Crypto1.mjs/+esm')
console.log(Crypto1.mfkey32v2({
uid: 0x65535D33,
nt: 0x2C198BE4,
nr: 0xFEDAC6D2,
ar: 0xCF0A3C7E,
at: 0xF4A81AF8,
}).toString('hex')) // A9AC67832330
console.log(Crypto1.mfkey32v2({
uid: Buffer.fromHex('65535D33'),
nt: Buffer.fromHex('2C198BE4'),
nr: Buffer.fromHex('FEDAC6D2'),
ar: Buffer.fromHex('CF0A3C7E'),
at: Buffer.fromHex('F4A81AF8'),
}).toString('hex')) // A9AC67832330
console.log(Crypto1.mfkey32v2({
uid: '65535D33',
nt: '2C198BE4',
nr: 'FEDAC6D2',
ar: 'CF0A3C7E',
at: 'F4A81AF8',
}).toString('hex')) // A9AC67832330
Static
nestedRecover key from mifare tags with weak prng
The logs of the nested attack.
The nonce distance between two authentication.
The 4-bytes uid in the authentication.
candidates keys
const { default: Crypto1 } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/Crypto1.mjs/+esm')
const args = {
uid: '877209e1',
dist: '00000080',
atks: [
{ nt1: 'b4a08a09', nt2: '8a15bbf2', par: 5 },
{ nt1: '1613293d', nt2: '912e6760', par: 7 }
]
}
const keys = Crypto1.nested(args)
console.log(`keys = ${JSON.stringify(_.map(keys, key => key.toString('hex')))}`)
Static
prngGenerate the new prng state from the current prng state x
by n
times.
The current prng state.
The number of times to generate the new prng state.
The new prng state.
Static
staticnestedRecover key from mifare tags with static nonce
The nonce logs of the authentication.
The key type of target block.
The 4-bytes uid in the authentication.
candidates keys
const { default: Crypto1 } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/dist/Crypto1.mjs/+esm')
const { Mf1KeyType } = await import('https://cdn.jsdelivr.net/npm/chameleon-ultra.js@0/+esm')
const args = {
uid: 'b908a16d',
keyType: Mf1KeyType.KEY_A,
atks: [
{ nt1: '01200145', nt2: '81901975' },
{ nt1: '01200145', nt2: 'cdd400f3' },
],
}
const keys = Crypto1.staticnested(args)
console.log(`keys = ${JSON.stringify(_.map(keys, key => key.toString('hex')))}`)
Internal
evenInternal
oddStatic
Internal
evenStatic
Internal
lfsrStatic
beInternal
Get bit of the unsigned reversed endian 32-bit integer x
at position n
.
The reversed endian unsigned 32-bit integer.
The bit position.
The bit at position n
.
Static
bitInternal
Get bit of the unsigned 32-bit integer x
at position n
.
The unsigned 32-bit integer.
The bit position.
The bit at position n
.
Static
castInternal
Cast Buffer, hex string or number to UInt32
Buffer, string or number
UInt32
Static
checkInternal
helper function which eliminates possible secret states using parity bits
Static
evenInternal
Return the even parity of the unsigned 32-bit integer x
.
The unsigned 32-bit integer.
The even parity of x
.
Static
evenInternal
Return the even parity of the unsigned 8-bit integer x
.
The unsigned 8-bit integer.
The even parity of x
.
Static
extendInternal
Using a bit of the keystream extend the table of possible lfsr states. (complex version)
An array of the even/odd bits of lfsr.
Size of array.
The bit of the keystream.
mask1
mask2
The value that was fed into the lfsr at the time the keystream was generated.
The new size of array.
Static
extendInternal
Using a bit of the keystream extend the table of possible lfsr states. (simple version)
An array of the even/odd bits of lfsr.
Size of array.
The bit of the keystream.
The new size of array.
Static
filterInternal
The filter function of Crypto1.
The unsigned 32-bit integer.
The filtered bit.
Static
lfsrStatic
lfsrInternal
Static
lfsrInternal
Recover the state of the lfsr given 32 bits of the keystream. Additionally you can use the in parameter to specify the value that was fed into the lfsr at the time the keystream was generated
The array of recovered lfsr states.
Static
lfsrInternal
Reverse 64 bits of keystream into possible lfsr states. Variation mentioned in the paper. Somewhat optimized version
keystream 2
keystream 3
The recovered lfsr state.
Static
mfkeyInternal
Recursively narrow down the search space, 4 bits of keystream at a time.
The array of even bits of possible lfsr states.
The array of odd bits of possible lfsr states.
The array of recovered lfsr states.
Static
nestedInternal
Static
nestedInternal
Static
oddInternal
Return the odd parity of the unsigned 8-bit integer x
.
The unsigned 8-bit integer.
The odd parity of x
.
Static
swapInternal
Swap endian of the unsigned 32-bit integer x
.
The unsigned 32-bit integer.
The unsigned 32-bit integer after swap endian.
Static
toStatic
toInternal
Indicates whether the number is truly or not.
The number.
Return 1
if the number is not falsey, otherwise return 0
.
Static
toInternal
Cast the number x
to unsigned 24-bit integer.
The number.
The casted unsigned 24-bit integer.
Static
toInternal
Cast the number x
to unsigned 32-bit integer.
The number.
The casted unsigned 32-bit integer.
Static
toInternal
Cast the number x
to unsigned 8-bit integer.
The number.
The casted unsigned 8-bit integer.
Static
updateInternal
A helper function to calculates the partial linear feedback contributions and puts in MSB (Most Significant Bit).
The input number.
JavaScript implementation of the Crypto1 cipher.
See
crypto1.c | RfidResearchGroup/proxmark3