Last active
December 30, 2024 07:09
-
-
Save TooTallNate/4fa19e9c8aa567d6a6b82e87751d3065 to your computer and use it in GitHub Desktop.
Get the NCA header decryption key in nx.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// These source values are seen in other open source repos: | |
// - https://github.com/blawar/tinleaf/blob/3363538600e47e1862d64d265dab1a031b32d037/include/util/crypto.hpp#L41-L42 | |
// - https://github.com/ITotalJustice/sphaira/blob/0370e47f7fac0e426675624f363fe50f3b442048/sphaira/source/owo.cpp#L339-L346 | |
const headerKekSource = new Uint8Array([ | |
0x1f, 0x12, 0x91, 0x3a, 0x4a, 0xcb, 0xf0, 0x0d, 0x4c, 0xde, 0x3a, 0xf6, | |
0xd5, 0x23, 0x88, 0x2a, | |
]); | |
const headerKeySource = new Uint8Array([ | |
0x5a, 0x3e, 0xd8, 0x4f, 0xde, 0xc0, 0xd8, 0x26, 0x31, 0xf7, 0xe2, 0x5d, | |
0x19, 0x7b, 0xf5, 0xd0, 0x1c, 0x9b, 0x7b, 0xfa, 0xf6, 0x28, 0x18, 0x3d, | |
0x71, 0xf6, 0x4d, 0x73, 0xf1, 0x50, 0xb9, 0xd2, | |
]); | |
const kek = splCryptoGenerateAesKek(headerKekSource.buffer, 0, 0); | |
const key0 = splCryptoGenerateAesKey( | |
kek, | |
headerKeySource.buffer.slice(0, 0x10), | |
); | |
const key1 = splCryptoGenerateAesKey(kek, headerKeySource.buffer.slice(0x10)); | |
const key = new Uint8Array([ | |
...new Uint8Array(key0), | |
...new Uint8Array(key1), | |
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const splMig = new Switch.Service('spl:mig'); | |
export function splCryptoGenerateAesKek( | |
wrappedKek: ArrayBuffer, | |
keyGeneration: number, | |
option: number, | |
): ArrayBuffer { | |
//Result splCryptoGenerateAesKek(const void *wrapped_kek, u32 key_generation, u32 option, void *out_sealed_kek) { | |
// const struct { | |
// SplKey wrapped_kek; | |
// u32 key_generation; | |
// u32 option; | |
// } in = { *((const SplKey *)wrapped_kek), key_generation, option }; | |
// return serviceDispatchInOut(_splGetCryptoSrv(), 2, in, *((SplKey *)out_sealed_kek)); | |
//} | |
const inData = new Uint8Array(0x18); | |
inData.set(new Uint8Array(wrappedKek, 0, 0x10), 0); | |
const inDataArr = new Uint32Array(inData.buffer, 0x10, 2); | |
inDataArr[0] = keyGeneration; | |
inDataArr[1] = option; | |
const out = new Uint8Array(0x10); | |
splMig.dispatchInOut(2, inData.buffer, out.buffer); | |
return out; | |
} | |
export function splCryptoGenerateAesKey( | |
sealedKek: ArrayBuffer, | |
wrappedKey: ArrayBuffer, | |
): ArrayBuffer { | |
//Result splCryptoGenerateAesKey(const void *sealed_kek, const void *wrapped_key, void *out_sealed_key) { | |
// const struct { | |
// SplKey sealed_kek; | |
// SplKey wrapped_key; | |
// } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key) }; | |
// return serviceDispatchInOut(_splGetCryptoSrv(), 4, in, *((SplKey *)out_sealed_key)); | |
//} | |
const inData = new Uint8Array(0x20); | |
inData.set(new Uint8Array(sealedKek, 0, 0x10), 0); | |
inData.set(new Uint8Array(wrappedKey, 0, 0x10), 0x10); | |
const out = new Uint8Array(0x10); | |
splMig.dispatchInOut(4, inData.buffer, out.buffer); | |
return out; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment