def encrypt_bcd(data: bytes, *args, **kwargs) -> bytes: assert (isinstance(data, bytes)) assert (len(data) == 0x5bfc0) stream: io.BytesIO = io.BytesIO(data) header: io.BytesIO = io.BytesIO() decrypted: bytes = stream.read(0x5bfc0) header.write( struct.pack('<I', 0x1) + struct.pack('<H', 0x10) + struct.pack('<H', 0x0) + struct.pack('<I', zlib.crc32(decrypted)) + 'SCDL'.encode('utf-8')) seed: bytes = get_random_bytes(0x10) context: tuple = struct.unpack_from('<IIII', seed) random: Random = Random(*context) key: bytes = crypto.create_key(random, keytables.bcd, 0x10) aes: _mode_cbc.CbcMode = AES.new(key, AES.MODE_CBC, get_random_bytes(0x10)) encrypted: bytes = aes.encrypt(decrypted) key: bytes = crypto.create_key(random, keytables.bcd, 0x10) mac: CMAC.CMAC = CMAC.new(key, ciphermod=AES) mac.update(decrypted) return header.getvalue() + encrypted + aes.iv + seed + mac.digest()
def decrypt_btl(data: bytes, *args, **kwargs) -> bytes: assert (isinstance(data, bytes)) assert (len(data) == 0x1c000) stream: io.BytesIO = io.BytesIO(data) encrypted: bytes = stream.read(0x1bfd0) footer: io.BytesIO = io.BytesIO(stream.read(0x30)) iv: bytes = footer.read(0x10) seed: bytes = footer.read(0x10) cmac: bytes = footer.read(0x10) context: tuple = struct.unpack_from('<IIII', footer.getvalue(), 0x10) random: Random = Random(*context) key: bytes = crypto.create_key(random, keytables.btl, 0x10) aes: _mode_cbc.CbcMode = AES.new(key, AES.MODE_CBC, iv) decrypted: bytes = aes.decrypt(encrypted) key: bytes = crypto.create_key(random, keytables.btl, 0x10) mac: CMAC.CMAC = CMAC.new(key, ciphermod=AES) mac.update(decrypted) mac.verify(cmac) return decrypted
def encrypt(self): self.stream = streams.StreamIn(self.data) self.header = streams.StreamOut() self.decrypted = self.stream.read(0x5BFC0) self.header.write(struct.pack("<I", 0x1)) self.header.write(struct.pack("<H", 0x10)) self.header.write(struct.pack("<H", 0x0)) self.header.write(struct.pack("<I", zlib.crc32(self.decrypted))) self.header.write("SCDL".encode("utf-8")) self.randomState = Random.get_random_bytes(0x10) self.context = struct.unpack("<IIII", self.randomState) self.rand = random.Random(*self.context) self.key = crypto.create_key(self.rand, keytables.course, 0x10) self.aes = AES.new(self.key, AES.MODE_CBC, Random.get_random_bytes(0x10)) self.encrypted = self.aes.encrypt(self.decrypted) self.key = crypto.create_key(self.rand, keytables.course, 0x10) self.mac = CMAC.new(self.key, ciphermod=AES) self.mac.update(self.decrypted) self.mac.digest() self.data = self.header.data( ) + self.encrypted + self.aes.iv + self.randomState + self.mac.digest( ) return None
def decrypt(self): self.stream = streams.StreamIn(self.data) self.header = self.stream.substream(0x10) self.encrypted = self.stream.read(0x5BFC0) self.cryptoConfig = self.stream.substream(0x30) self.header.skip(0x4) self.filetype = self.header.read(0x2) self.header.skip(0x2) self.crc32 = self.header.read(0x4) self.magic = self.header.read(0x4) self.iv = self.cryptoConfig.read(0x10) self.randomState = self.cryptoConfig.read(0x10) self.cmac = self.cryptoConfig.read(0x10) self.context = struct.unpack_from("<IIII", self.cryptoConfig.data, 0x10) self.rand = random.Random(*self.context) self.key = crypto.create_key(self.rand, keytables.course, 0x10) self.aes = AES.new(self.key, AES.MODE_CBC, self.iv) self.decrypted = self.aes.decrypt(self.encrypted) self.key = crypto.create_key(self.rand, keytables.course, 0x10) self.mac = CMAC.new(self.key, ciphermod=AES) self.mac.update(self.decrypted) self.mac.verify(self.cmac) self.data = self.decrypted return None
def encrypt_btl(data: bytes, *args, **kwargs) -> bytes: assert (isinstance(data, bytes)) assert (len(data) == 0x1bfd0) stream: io.BytesIO = io.BytesIO(data) decrypted: bytes = stream.read(0x1bfd0) seed: bytes = get_random_bytes(0x10) context: tuple = struct.unpack_from('<IIII', seed) random: Random = Random(*context) key: bytes = crypto.create_key(random, keytables.btl, 0x10) aes: _mode_cbc.CbcMode = AES.new(key, AES.MODE_CBC, get_random_bytes(0x10)) encrypted: bytes = aes.encrypt(decrypted) key: bytes = crypto.create_key(random, keytables.btl, 0x10) mac: CMAC.CMAC = CMAC.new(key, ciphermod=AES) mac.update(decrypted) return encrypted + aes.iv + seed + mac.digest()
def decrypt_bcd(data: bytes, *args, **kwargs) -> bytes: assert (isinstance(data, bytes)) assert (len(data) == 0x5c000) stream: io.BytesIO = io.BytesIO(data) header: io.BytesIO = io.BytesIO(stream.read(0x10)) encrypted: bytes = stream.read(0x5bfc0) footer: io.BytesIO = io.BytesIO(stream.read(0x30)) header.seek(header.tell() + 0x4) filetype: int = struct.unpack('<H', header.read(0x2))[0] header.seek(header.tell() + 0x2) crc32: int = struct.unpack('<I', header.read(0x4))[0] magic: str = header.read(0x4).decode('utf-8') assert (filetype == 0x10 and magic == 'SCDL') iv: bytes = footer.read(0x10) seed: bytes = footer.read(0x10) cmac: bytes = footer.read(0x10) context: tuple = struct.unpack_from('<IIII', footer.getvalue(), 0x10) random: Random = Random(*context) key: bytes = crypto.create_key(random, keytables.bcd, 0x10) aes: _mode_cbc.CbcMode = AES.new(key, AES.MODE_CBC, iv) decrypted: bytes = aes.decrypt(encrypted) assert (zlib.crc32(decrypted) == crc32) key: bytes = crypto.create_key(random, keytables.bcd, 0x10) mac: CMAC.CMAC = CMAC.new(key, ciphermod=AES) mac.update(decrypted) mac.verify(cmac) return decrypted
def test_create_key(): rand = sead.Random(0xCEB9D8D9) table = [ 0x56CB956F, 0x7B50EEC6, 0x234D1A63, 0x1C691A6B, 0xD2D9C482, 0xCFE21965, 0x0B32DF99, 0xB32AFE44, 0xB15DA3D7, 0x86588505, 0x4FC8CD8B, 0xC30F864B, 0x08D4D3BE, 0xEFDEC6CA, 0x63A1D53F, 0xC545538D, 0x715E27A2, 0x4818A005, 0x8C28D9F8, 0xC303EABF, 0xF1D847ED, 0xE837F303, 0xE68981E8, 0x63E2F9BC, 0xC320F7E1, 0x5E0B4084, 0x502B2A2D, 0x65D36579, 0x0D169E46, 0x65AB445D, 0xFDF0678B, 0x26167D3E, 0xFE5025A0, 0x04EB0EA8, 0xC048B044, 0xF858002E, 0x6725F7D6, 0xD4086AA8, 0xF216DE10, 0x0F1807E6, 0xD3614878, 0x34A2FEE6, 0xA69AE3DE, 0xED8518EF, 0x6FCCB7A5, 0x7F8D0E40, 0x9B72BFA8, 0x87C669D4, 0x5BF80652, 0x9A71383F, 0xBA3E7A7A, 0x1ABA65A3, 0xA9A16DFF, 0xD07B9E3C, 0x11C9BD45, 0xF14A6D81, 0x78516ECD, 0x53445C15, 0xC86E9942, 0x5501D2C9, 0xD0D4ECB3, 0x38F5C341, 0xC4A16155, 0x42F1F406 ] key = crypto.create_key(rand, table, 16) assert key == bytes.fromhex("ee182a63e216cdb1f51ad4bed8cf6508")
print("\tSession param: %s" % info.session_param.hex()) print("\tHost: %s" % info.host_location.get_station_url()) seed = 0xCEB9D8D9 table = [ 0x56CB956F, 0x7B50EEC6, 0x234D1A63, 0x1C691A6B, 0xD2D9C482, 0xCFE21965, 0x0B32DF99, 0xB32AFE44, 0xB15DA3D7, 0x86588505, 0x4FC8CD8B, 0xC30F864B, 0x08D4D3BE, 0xEFDEC6CA, 0x63A1D53F, 0xC545538D, 0x715E27A2, 0x4818A005, 0x8C28D9F8, 0xC303EABF, 0xF1D847ED, 0xE837F303, 0xE68981E8, 0x63E2F9BC, 0xC320F7E1, 0x5E0B4084, 0x502B2A2D, 0x65D36579, 0x0D169E46, 0x65AB445D, 0xFDF0678B, 0x26167D3E, 0xFE5025A0, 0x04EB0EA8, 0xC048B044, 0xF858002E, 0x6725F7D6, 0xD4086AA8, 0xF216DE10, 0x0F1807E6, 0xD3614878, 0x34A2FEE6, 0xA69AE3DE, 0xED8518EF, 0x6FCCB7A5, 0x7F8D0E40, 0x9B72BFA8, 0x87C669D4, 0x5BF80652, 0x9A71383F, 0xBA3E7A7A, 0x1ABA65A3, 0xA9A16DFF, 0xD07B9E3C, 0x11C9BD45, 0xF14A6D81, 0x78516ECD, 0x53445C15, 0xC86E9942, 0x5501D2C9, 0xD0D4ECB3, 0x38F5C341, 0xC4A16155, 0x42F1F406 ] key = crypto.create_key(seed, table, 16) settings = settings.Settings("switch.cfg") browser = lan.LanBrowser(settings, key) search_criteria = lan.LanSessionSearchCriteria() result = browser.browse(search_criteria) if result: print_session_info(result) else: print("No LAN session found")
print("\tSession param: %s" % info.session_param.hex()) print("\tHost: %s" % info.host_location.get_station_url()) rand = random.Random(0xCEB9D8D9) table = [ 0x56CB956F, 0x7B50EEC6, 0x234D1A63, 0x1C691A6B, 0xD2D9C482, 0xCFE21965, 0x0B32DF99, 0xB32AFE44, 0xB15DA3D7, 0x86588505, 0x4FC8CD8B, 0xC30F864B, 0x08D4D3BE, 0xEFDEC6CA, 0x63A1D53F, 0xC545538D, 0x715E27A2, 0x4818A005, 0x8C28D9F8, 0xC303EABF, 0xF1D847ED, 0xE837F303, 0xE68981E8, 0x63E2F9BC, 0xC320F7E1, 0x5E0B4084, 0x502B2A2D, 0x65D36579, 0x0D169E46, 0x65AB445D, 0xFDF0678B, 0x26167D3E, 0xFE5025A0, 0x04EB0EA8, 0xC048B044, 0xF858002E, 0x6725F7D6, 0xD4086AA8, 0xF216DE10, 0x0F1807E6, 0xD3614878, 0x34A2FEE6, 0xA69AE3DE, 0xED8518EF, 0x6FCCB7A5, 0x7F8D0E40, 0x9B72BFA8, 0x87C669D4, 0x5BF80652, 0x9A71383F, 0xBA3E7A7A, 0x1ABA65A3, 0xA9A16DFF, 0xD07B9E3C, 0x11C9BD45, 0xF14A6D81, 0x78516ECD, 0x53445C15, 0xC86E9942, 0x5501D2C9, 0xD0D4ECB3, 0x38F5C341, 0xC4A16155, 0x42F1F406 ] key = crypto.create_key(rand, table, 16) settings = settings.Settings("switch.cfg") browser = lan.LanBrowser(settings, key) search_criteria = lan.LanSessionSearchCriteria() result = browser.browse(search_criteria) if result: print_session_info(result) else: print("No LAN session found")