예제 #1
0
    def verify(self):
        ncaHeader = NcaHeader()
        ncaHeader.open(
            MemoryFile(self.ncaHeader, Type.Crypto.XTS,
                       uhx(Keys.get('header_key'))))

        id = ncaHeader.rightsId[0:16].decode().upper()
        if str(self.titleId) != id:
            raise IndexError('Title IDs do not match!  ' + str(self.titleId) +
                             ' != ' + id)

        decKey = Keys.decryptTitleKey(uhx(self.titleKey), ncaHeader.masterKey)

        pfs0 = Fs.Pfs0(self.sectionHeaderBlock)
        '''
		print('encKey = ' + str(self.titleKey))
		print('decKey = ' + str(hx(decKey)))
		print('master key = ' + str(ncaHeader.masterKey))
		print('ctr = ' + str(hx(pfs0.cryptoCounter)))
		print('offset = ' + str(self.pfs0Offset))
		'''

        if self.sectionHeaderBlock[8:12] == b'IVFC':
            #Hex.dump(self.sectionHeaderBlock)
            #Print.info(hx(self.sectionHeaderBlock[0xc8:0xc8+0x20]).decode('utf-8'))
            mem = MemoryFile(self.pfs0Header,
                             Type.Crypto.CTR,
                             decKey,
                             pfs0.cryptoCounter,
                             offset=self.pfs0Offset)
            data = mem.read()
            #Hex.dump(data)
            #print('hash = %s' % str(_sha256(data)))
            if hx(self.sectionHeaderBlock[0xc8:0xc8 +
                                          0x20]).decode('utf-8') == str(
                                              _sha256(data)):
                return True
            else:
                return False
        else:
            mem = MemoryFile(self.pfs0Header,
                             Type.Crypto.CTR,
                             decKey,
                             pfs0.cryptoCounter,
                             offset=self.pfs0Offset)
            magic = mem.read()[0:4]
            if magic != b'PFS0':
                raise LookupError('Title Key is incorrect!')

        return True
예제 #2
0
파일: Nca.py 프로젝트: yukun451/nut
    def restore(self):
        header = self.getVerifiedHeader()

        if not header:
            raise IOError('could not restore nca header for %s - %s' %
                          (self.titleId, str(self.f._path)))

        if not self.hasTitleRights():
            if header[0x30:0x40] != b'\x00' * 0x10:
                self.rightsId = hx(header[0x30:0x40])
                key = hx(
                    Keys.encryptTitleKey(
                        self.key(), max(max(header[0x6], header[0x20]) - 1,
                                        0))).decode().upper()
                #key = hx(self.key()).decode().upper()
                title = Titles.get(self.titleId)

                if title.key and title.key != key:
                    raise IOError(
                        'nca title key does not match database: %s vs %s' %
                        (title.key, key))
                elif not title.key:
                    title.key = key
            else:
                self.rightsId = b'0' * 32

        self.seek(0x200)
        self.write(header)
        return True
예제 #3
0
    def printInfo(self, maxDepth=3, indent=0):
        tabs = '\t' * indent

        try:
            rightsId = format(self.getRightsId(), 'X').zfill(32)
        except:
            Print.info('\n%sInvalid Ticket\n' % (tabs))
            return
        titleId = rightsId[0:16]
        titleKey = format(self.getTitleKeyBlock(), 'X').zfill(32)

        Print.info('\n%sTicket\n' % (tabs))
        super(Ticket, self).printInfo(maxDepth, indent)
        Print.info(tabs + 'signatureType = ' + str(self.signatureType))
        Print.info(tabs + 'keyType = ' + str(self.keyType))
        Print.info(tabs + 'masterKeyRev = ' + str(self.masterKeyRevision))
        Print.info(tabs + 'ticketId = ' + str(self.ticketId))
        Print.info(tabs + 'deviceId = ' + str(self.deviceId))
        Print.info(tabs + 'rightsId = ' + rightsId)
        Print.info(tabs + 'accountId = ' + str(self.accountId))
        Print.info(tabs + 'titleId = ' + titleId)
        Print.info(tabs + 'titleKey = ' + titleKey)
        try:
            Print.info(tabs + 'titleKeyDec = ' + str(
                hx(
                    Keys.decryptTitleKey(
                        (self.getTitleKey()), self.masterKeyRevision))))
        except BaseException as e:
            Print.info(tabs + 'titleKeyDec = ' + str(e))
        '''
예제 #4
0
 def readFile(self, filePath):
     try:
         cal0File = open(filePath, 'rb')
         cal0 = cal0File.read()
         if int.from_bytes(cal0[0x0:0x4], byteorder='little',
                           signed=False) == 810303811:
             self.serialNumber = cal0[0x250:0x25E].decode('utf-8')
             sslCertificateSize = int.from_bytes(cal0[0xAD0:0xAD4],
                                                 byteorder='little',
                                                 signed=False)
             self.sslCertificate = cal0[0xAE0:0xAE0 + sslCertificateSize]
             self.rsa2048ETicketCertificate = cal0[0x2A90:0x2CD0]
             self.deviceId = hexlify(cal0[0x35E0:0x35E8]).decode('utf-8')
             self.extendedRsa2048ETicketKey = cal0[0x3890:0x3AD0]
             ctr = Counter.new(128,
                               initial_value=int(
                                   hexlify(cal0[0x3AE0:0x3AF0]), 16))
             dec = AES.new(Keys.getKey('ssl_rsa_kek'),
                           AES.MODE_CTR,
                           counter=ctr).decrypt(cal0[0x3AF0:0x3C10])
             self.extendedSslKey = get_priv_key_der(self.sslCertificate,
                                                    dec[:0x100])
             return True
         else:
             print('File specified is not a valid CAL0 file')
         cal0File.close()
     except FileNotFoundError:
         print('CAL0 specified not found! Unable to read information')
     return False
예제 #5
0
    def printInfo(self, maxDepth=3, indent=0):
        tabs = '\t' * indent

        rightsId = format(self.getRightsId(), 'X').zfill(32)
        titleId = rightsId[0:16]
        titleKey = format(self.getTitleKeyBlock(), 'X').zfill(32)

        Print.info('\n%sTicket\n' % (tabs))
        super(Ticket, self).printInfo(maxDepth, indent)
        Print.info(tabs + 'signatureType = ' + str(self.signatureType))
        Print.info(tabs + 'keyType = ' + str(self.keyType))
        Print.info(tabs + 'masterKeyRev = ' + str(self.masterKeyRevision))
        Print.info(tabs + 'ticketId = ' + str(self.ticketId))
        Print.info(tabs + 'deviceId = ' + str(self.deviceId))
        Print.info(tabs + 'rightsId = ' + rightsId)
        Print.info(tabs + 'accountId = ' + str(self.accountId))
        Print.info(tabs + 'titleId = ' + titleId)
        Print.info(tabs + 'titleKey = ' + titleKey)
        Print.info(tabs + 'titleKeyDec = ' + str(
            hx(
                Keys.decryptTitleKey(
                    (self.getTitleKey()), self.masterKeyRevision))))

        try:
            if blockchain.verifyKey(titleId, titleKey):
                tkeyStatus = 'VERIFIED'
            else:
                tkeyStatus = 'BAD KEY'
        except BaseException as e:
            tkeyStatus = 'UNKNOWN - ' + str(e)
            raise

        Print.info(tabs + 'titleKeyStatus = ' + tkeyStatus)
예제 #6
0
파일: Nca.py 프로젝트: yukun451/nut
    def getVerifiedHeader(self):
        self.seek(0x200)
        buffer = bytearray(self.read(0x200))

        if self.verifyBuffer(buffer):
            return buffer

        for gameCardValue in [0, 1]:
            buffer[0x04] = gameCardValue

            if self.verifyBuffer(buffer):
                Print.info('isGameCard = %d' % gameCardValue)
                return buffer

        if self.hasTitleRights():
            return None

        title = Titles.get(self.titleId)
        '''
		if title.rightsId:
			for gameCardValue in [0, 1]:
				buffer[0x04] = gameCardValue
			#return False
		'''

        for gameCardValue in [0, 1]:
            buffer[0x04] = gameCardValue
            for keyGen in Keys.getKeyGens():
                buffer = self.setRightsIdBuffer(buffer, keyGen)
                if self.verifyBuffer(buffer):
                    Print.info('Title Rights: isGameCard = %d, keyGen = %d' %
                               (gameCardValue, keyGen))
                    return buffer

        for gameCardValue in [0, 1]:
            buffer[0x04] = gameCardValue
            for keyGen in Keys.getKeyGens():
                buffer = self.setStandardCryptoBuffer(buffer, keyGen)
                if self.verifyBuffer(buffer):
                    Print.info(
                        'Standard Crypto: isGameCard = %d, keyGen = %d' %
                        (gameCardValue, keyGen))
                    return buffer

        return None
예제 #7
0
    def open(self,
             file=None,
             mode='rb',
             cryptoType=-1,
             cryptoKey=-1,
             cryptoCounter=-1):
        super(Nca, self).open(file, mode, cryptoType, cryptoKey, cryptoCounter)

        self.header = NcaHeader()
        self.partition(0x0, 0xC00, self.header, Fs.Type.Crypto.XTS,
                       uhx(Keys.get('header_key')))
        #Print.info('partition complete, seeking')
        self.header.seek(0x400)
        # Print.info('reading')
        # Hex.dump(self.header.read(0x200))
        # exit()

        if self._path is not None and self._path.endswith('.ncz'):
            return

        for i in range(4):
            hdr = self.header.read(0x200)
            section = BaseFs(hdr, cryptoKey=self.header.titleKeyDec)
            fs = GetSectionFilesystem(hdr, cryptoKey=-1)
            #Print.info('fs type = ' + hex(fs.fsType))
            #Print.info('fs crypto = ' + hex(fs.cryptoType))
            #Print.info('st end offset = ' + str(self.header.sectionTables[i].endOffset - self.header.sectionTables[i].offset))
            #Print.info('fs offset = ' + hex(self.header.sectionTables[i].offset))
            #Print.info('fs section start = ' + hex(fs.sectionStart))
            #Print.info('titleKey = ' + hex(self.header.titleKeyDec))

            self.partition(self.header.sectionTables[i].offset,
                           self.header.sectionTables[i].endOffset -
                           self.header.sectionTables[i].offset,
                           section,
                           cryptoKey=self.header.titleKeyDec)

            try:
                section.partition(fs.sectionStart,
                                  section.size - fs.sectionStart, fs)
            except BaseException as e:
                pass
                # Print.info(e)
                # raise

            if fs.fsType:
                self.sectionFilesystems.append(fs)
                self.sections.append(section)

            try:
                fs.open(None, 'rb')
            except BaseException as e:
                Print.error(str(e))
                traceback.print_exc(file=sys.stdout)

        self.titleKeyDec = None
예제 #8
0
파일: Nca.py 프로젝트: yukun451/nut
    def setStandardCryptoBuffer(self, buffer, keyGen):
        buffer[0x30:0x40] = b'\x00' * 0x10

        emptyKey = b'\x00' * 0x10

        kek = Keys.keyAreaKey(Keys.getMasterKeyIndex(keyGen), self.keyIndex)
        crypto = aes128.AESECB(kek)

        encKeyBlock = crypto.encrypt(emptyKey + emptyKey + self.titleKeyDec +
                                     emptyKey)

        buffer[0x100:0x140] = encKeyBlock

        if keyGen <= 2:
            buffer[0x6] = keyGen
            buffer[0x20] = 0
        else:
            buffer[0x6] = 2
            buffer[0x20] = keyGen

        return buffer
예제 #9
0
    def removeTitleRights(self):
        if not Titles.contains(self.titleId):
            raise IOError('No title key found in database! ' + self.titleId)

        ticket = self.ticket()
        masterKeyRev = ticket.getMasterKeyRevision()
        titleKeyDec = Keys.decryptTitleKey(
            ticket.getTitleKeyBlock().to_bytes(16, byteorder='big'),
            Keys.getMasterKeyIndex(masterKeyRev))
        rightsId = ticket.getRightsId()

        Print.info('rightsId =\t' + hex(rightsId))
        Print.info('titleKeyDec =\t' + str(hx(titleKeyDec)))
        Print.info('masterKeyRev =\t' + hex(masterKeyRev))

        for nca in self:
            if type(nca) == Nca:
                if nca.header.getCryptoType2() != masterKeyRev:
                    pass
                    raise IOError('Mismatched masterKeyRevs!')

        ticket.setRightsId(0)

        for nca in self:
            if type(nca) == Nca:
                if nca.header.getRightsId() == 0:
                    continue

                kek = Keys.keyAreaKey(Keys.getMasterKeyIndex(masterKeyRev),
                                      nca.header.keyIndex)
                Print.info('writing masterKeyRev for %s, %d' %
                           (str(nca._path), masterKeyRev))
                Print.info('kek =\t' + hx(kek).decode())
                crypto = aes128.AESECB(kek)

                encKeyBlock = crypto.encrypt(titleKeyDec * 4)
                nca.header.setRightsId(0)
                nca.header.setKeyBlock(encKeyBlock)
                Hex.dump(encKeyBlock)
예제 #10
0
파일: Nca.py 프로젝트: zhentan/nut
    def open(self,
             file=None,
             mode='rb',
             cryptoType=-1,
             cryptoKey=-1,
             cryptoCounter=-1):

        super(Nca, self).open(file, mode, cryptoType, cryptoKey, cryptoCounter)

        self.header = NcaHeader()
        self.partition(0x0, 0xC00, self.header, Fs.Type.Crypto.XTS,
                       uhx(Keys.get('header_key')))
        #Print.info('partition complete, seeking')
        self.header.seek(0x400)
        #Print.info('reading')
        #Hex.dump(self.header.read(0x200))
        #exit()

        for i in range(4):
            fs = GetSectionFilesystem(self.header.read(0x200),
                                      cryptoKey=self.header.titleKeyDec)
            #Print.info('fs type = ' + hex(fs.fsType))
            #Print.info('fs crypto = ' + hex(fs.cryptoType))
            #Print.info('st end offset = ' + str(self.header.sectionTables[i].endOffset - self.header.sectionTables[i].offset))
            #Print.info('fs offset = ' + hex(self.header.sectionTables[i].offset))
            #Print.info('fs section start = ' + hex(fs.sectionStart))
            #Print.info('titleKey = ' + hex(self.header.titleKeyDec))
            try:
                self.partition(self.header.sectionTables[i].offset +
                               fs.sectionStart,
                               self.header.sectionTables[i].endOffset -
                               self.header.sectionTables[i].offset,
                               fs,
                               cryptoKey=self.header.titleKeyDec)
            except BaseException as e:
                pass
                #Print.info(e)
                #raise

            if fs.fsType:
                self.sectionFilesystems.append(fs)

        self.titleKeyDec = None
        self.masterKey = None
예제 #11
0
파일: Nca.py 프로젝트: narimantos/nsz
    def open(self,
             file=None,
             mode='rb',
             cryptoType=-1,
             cryptoKey=-1,
             cryptoCounter=-1):
        super(NcaHeader, self).open(file, mode, cryptoType, cryptoKey,
                                    cryptoCounter)
        self.rewind()
        self.signature1 = self.read(0x100)
        self.signature2 = self.read(0x100)
        self.magic = self.read(0x4)
        self.isGameCard = self.readInt8()
        self.contentType = self.readInt8()

        try:
            self.contentType = Fs.Type.Content(self.contentType)
        except:
            pass

        self.cryptoType = self.readInt8()
        self.keyIndex = self.readInt8()
        self.size = self.readInt64()
        self.titleId = hx(self.read(8)[::-1]).decode('utf-8').upper()
        self.contentIndex = self.readInt32()
        self.sdkVersion = self.readInt32()
        self.cryptoType2 = self.readInt8()

        self.read(0xF)  # padding

        self.rightsId = hx(self.read(0x10))

        if self.magic not in [b'NCA3', b'NCA2']:
            raise Exception('Failed to decrypt NCA header: ' + str(self.magic))

        self.sectionHashes = []

        for i in range(4):
            self.sectionTables.append(SectionTableEntry(self.read(0x10)))

        for i in range(4):
            self.sectionHashes.append(self.sectionTables[i])

        self.masterKey = (self.cryptoType if self.cryptoType > self.cryptoType2
                          else self.cryptoType2) - 1

        if self.masterKey < 0:
            self.masterKey = 0

        self.encKeyBlock = self.getKeyBlock()
        #for i in range(4):
        #	offset = i * 0x10
        #	key = encKeyBlock[offset:offset+0x10]
        #	Print.info('enc %d: %s' % (i, hx(key)))

        #crypto = aes128.AESECB(Keys.keyAreaKey(self.masterKey, 0))
        self.keyBlock = Keys.unwrapAesWrappedTitlekey(self.encKeyBlock,
                                                      self.masterKey)
        self.keys = []
        for i in range(4):
            offset = i * 0x10
            key = self.keyBlock[offset:offset + 0x10]
            #Print.info('dec %d: %s' % (i, hx(key)))
            self.keys.append(key)

        if self.hasTitleRights():
            titleRightsTitleId = self.rightsId.decode()[0:16].upper()

            if titleRightsTitleId in Titles.keys() and Titles.get(
                    titleRightsTitleId).key:
                self.titleKeyDec = Keys.decryptTitleKey(
                    uhx(Titles.get(titleRightsTitleId).key), self.masterKey)
            else:
                Print.info('could not find title key!')
        else:
            self.titleKeyDec = self.key()

        return True
예제 #12
0
파일: Nca.py 프로젝트: yukun451/nut
    def verifyKey(self, userkey):
        if not self.header.hasTitleRights():
            titleKeyDec = Keys.decryptTitleKey(
                file.getTitleKeyBlock().to_bytes(16, byteorder='big'),
                Keys.getMasterKeyIndex(self.masterKey()))
        else:
            encKey = userkey

            titleKeyDec = Keys.decryptTitleKey(
                encKey, Keys.getMasterKeyIndex(self.masterKey()))
            '''
			print('\nTesting {} with:'.format(self))
			print('- Keygeneration {}'.format(self.masterKey()))
			print('- Encrypted key {}'.format(str(hx(encKey))[2:-1]))
			print('- Decrypted key {}'.format(str(hx(titleKeyDec))[2:-1]))
			'''

        decKey = titleKeyDec
        f = self

        if self.header.getRightsId() != 0:
            for fs in self:
                # print(fs.fsType)
                # print(fs.cryptoType)
                if fs.fsType == Type.Fs.PFS0 and fs.cryptoType == Type.Crypto.CTR:
                    f.seek(0)
                    ncaHeader = NcaHeader()
                    ncaHeader.open(
                        MemoryFile(f.read(0x400), Type.Crypto.XTS,
                                   uhx(Keys.get('header_key'))))
                    pfs0 = fs
                    sectionHeaderBlock = fs.buffer

                    #fs.f.setKey(b'\x00' * 16)
                    #print('- Current key {}'.format(str(hx(fs.f.cryptoKey))[2:-1]))

                    fs.seek(0)
                    pfs0Offset = 0  # int.from_bytes(sectionHeaderBlock[0x38:0x40], byteorder='little', signed=False)
                    pfs0Header = fs.read(0x10)

                    # Hex.dump(sectionHeaderBlock)
                    #mem = MemoryFile(pfs0Header, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset = pfs0Offset)
                    data = pfs0Header  # mem.read();
                    # Hex.dump(pfs0Header)
                    magic = data[0:4]
                    # print(magic)
                    if magic != b'PFS0':
                        return False
                    else:
                        return True

                if fs.fsType == Type.Fs.ROMFS and fs.cryptoType == Type.Crypto.CTR:
                    f.seek(0)
                    ncaHeader = NcaHeader()
                    ncaHeader.open(
                        MemoryFile(f.read(0x400), Type.Crypto.XTS,
                                   uhx(Keys.get('header_key'))))
                    ncaHeader = f.read(0x400)
                    pfs0 = fs
                    sectionHeaderBlock = fs.buffer

                    levelOffset = int.from_bytes(sectionHeaderBlock[0x18:0x20],
                                                 byteorder='little',
                                                 signed=False)
                    levelSize = int.from_bytes(sectionHeaderBlock[0x20:0x28],
                                               byteorder='little',
                                               signed=False)

                    pfs0Offset = levelOffset
                    f.seek(pfs0Offset + fs.f.offset)
                    pfs0Header = f.read(levelSize)

                    # fs.seek(pfs0Offset)
                    #pfs0Header = fs.read(levelSize)

                    #print(sectionHeaderBlock[8:12] == b'IVFC')
                    if sectionHeaderBlock[8:12] == b'IVFC':
                        # Hex.dump(sectionHeaderBlock)
                        # Print.info(hx(sectionHeaderBlock[0xc8:0xc8+0x20]).decode('utf-8'))
                        mem = MemoryFile(pfs0Header,
                                         Type.Crypto.CTR,
                                         decKey,
                                         pfs0.cryptoCounter,
                                         offset=fs.f.offset)

                        data = mem.read()

                        #Hex.dump(data, 48)
                        #print('hash = %s' % str(sha256(data).hexdigest()))
                        if hx(sectionHeaderBlock[0xc8:0xc8 +
                                                 0x20]).decode('utf-8') == str(
                                                     sha256(data).hexdigest()):
                            return True
                        else:
                            return False
                    else:
                        mem = MemoryFile(pfs0Header,
                                         Type.Crypto.CTR,
                                         decKey,
                                         pfs0.cryptoCounter,
                                         offset=pfs0Offset)
                        data = mem.read()
                        # Hex.dump(data)
                        magic = mem.read()[0:4]
                        # print(magic)
                        if magic != b'PFS0':
                            pass
                        else:
                            return True

                if fs.fsType == Type.Fs.ROMFS and fs.cryptoType == Type.Crypto.BKTR and str(
                        f.header.contentType) == 'Content.PROGRAM':
                    f.seek(0)
                    ncaHeader = NcaHeader()
                    ncaHeader.open(
                        MemoryFile(f.read(0x400), Type.Crypto.XTS,
                                   uhx(Keys.get('header_key'))))
                    ncaHeader = f.read(0x400)
                    pfs0 = fs
                    sectionHeaderBlock = fs.buffer

                    levelOffset = int.from_bytes(sectionHeaderBlock[0x18:0x20],
                                                 byteorder='little',
                                                 signed=False)
                    levelSize = int.from_bytes(sectionHeaderBlock[0x20:0x28],
                                               byteorder='little',
                                               signed=False)

                    pfs0Offset = fs.offset + levelOffset
                    f.seek(pfs0Offset)
                    pfs0Header = f.read(levelSize)

                    if sectionHeaderBlock[8:12] == b'IVFC':
                        for i in range(10):
                            ini = 0x100 + (i * 0x10)
                            fin = 0x110 + (i * 4)
                            test = sectionHeaderBlock[ini:fin]
                            if test == b'BKTR':
                                return True
        return False
예제 #13
0
파일: Nca.py 프로젝트: yukun451/nut
 def verifyBuffer(self, buffer):
     if Keys.pssVerify(buffer, self.signature1, Keys.ncaHdrFixedKeyModulus):
         return True
     return False
예제 #14
0
    def setMasterKeyRev(self, newMasterKeyRev):
        if not Titles.contains(self.titleId):
            raise IOError('No title key found in database! ' + self.titleId)

        ticket = self.ticket()
        masterKeyRev = ticket.getMasterKeyRevision()
        titleKey = ticket.getTitleKeyBlock()
        newTitleKey = Keys.changeTitleKeyMasterKey(
            titleKey.to_bytes(16, byteorder='big'),
            Keys.getMasterKeyIndex(masterKeyRev),
            Keys.getMasterKeyIndex(newMasterKeyRev))
        rightsId = ticket.getRightsId()

        if rightsId != 0:
            raise IOError('please remove titlerights first')

        if (newMasterKeyRev == None
                and rightsId == 0) or masterKeyRev == newMasterKeyRev:
            Print.info('Nothing to do')
            return

        Print.info('rightsId =\t' + hex(rightsId))
        Print.info('titleKey =\t' +
                   str(hx(titleKey.to_bytes(16, byteorder='big'))))
        Print.info('newTitleKey =\t' + str(hx(newTitleKey)))
        Print.info('masterKeyRev =\t' + hex(masterKeyRev))

        for nca in self:
            if type(nca) == Nca:
                if nca.header.getCryptoType2() != masterKeyRev:
                    pass
                    raise IOError('Mismatched masterKeyRevs!')

        ticket.setMasterKeyRevision(newMasterKeyRev)
        ticket.setRightsId((ticket.getRightsId()
                            & 0xFFFFFFFFFFFFFFFF0000000000000000) +
                           newMasterKeyRev)
        ticket.setTitleKeyBlock(int.from_bytes(newTitleKey, 'big'))

        for nca in self:
            if type(nca) == Nca:
                if nca.header.getCryptoType2() != newMasterKeyRev:
                    Print.info('writing masterKeyRev for %s, %d -> %s' %
                               (str(nca._path), nca.header.getCryptoType2(),
                                str(newMasterKeyRev)))

                    encKeyBlock = nca.header.getKeyBlock()

                    if sum(encKeyBlock) != 0:
                        key = Keys.keyAreaKey(
                            Keys.getMasterKeyIndex(masterKeyRev),
                            nca.header.keyIndex)
                        Print.info('decrypting with %s (%d, %d)' %
                                   (str(hx(key)),
                                    Keys.getMasterKeyIndex(masterKeyRev),
                                    nca.header.keyIndex))
                        crypto = aes128.AESECB(key)
                        decKeyBlock = crypto.decrypt(encKeyBlock)

                        key = Keys.keyAreaKey(
                            Keys.getMasterKeyIndex(newMasterKeyRev),
                            nca.header.keyIndex)
                        Print.info('encrypting with %s (%d, %d)' %
                                   (str(hx(key)),
                                    Keys.getMasterKeyIndex(newMasterKeyRev),
                                    nca.header.keyIndex))
                        crypto = aes128.AESECB(key)

                        reEncKeyBlock = crypto.encrypt(decKeyBlock)
                        nca.header.setKeyBlock(reEncKeyBlock)

                    if newMasterKeyRev >= 3:
                        nca.header.setCryptoType(2)
                        nca.header.setCryptoType2(newMasterKeyRev)
                    else:
                        nca.header.setCryptoType(newMasterKeyRev)
                        nca.header.setCryptoType2(0)