@@ -810,6 +810,101 @@ def pkcs7unpad(msg, blocklen):
810810 "V5683" : (0x05 , b'z3\n \x03 9\x12 \x13 `\x06 =v,\x02 MTK\x1e %}L\x1c \x1f \x15 \x0c \x11 \x02 \x0c \n 8\x17 p' ),
811811}
812812
813+ def scramble3 (st ,magic ):
814+ ret = bytearray (len (st ))
815+ padlen = len (st )
816+ divs = padlen // magic
817+ cntr = 0
818+ iVar6 = 0
819+ offset = 0
820+ if (0 < ((magic - 1 ) + divs )):
821+ while True :
822+ if (offset & 1 ) == 0 :
823+ uVar4 = divs - 1
824+ if offset < divs :
825+ iVar3 = 0
826+ uVar4 = offset
827+ else :
828+ iVar3 = (offset - divs ) + 1
829+ if uVar4 >= 0 :
830+ iVar5 = uVar4 * magic
831+ index = ((padlen - 1 ) - cntr )
832+ while True :
833+ if (magic <= iVar3 ): break
834+ ret [index ] = st [iVar3 + iVar5 ]
835+ iVar3 = iVar3 + 1
836+ cntr = cntr + 1
837+ uVar4 = uVar4 - 1
838+ iVar5 = iVar5 - magic
839+ index -= 1
840+ if uVar4 <= - 1 : break
841+ else :
842+ if (offset < magic ):
843+ iVar3 = 0
844+ else :
845+ iVar3 = (offset - magic ) + 1
846+ if (iVar3 < divs ):
847+ uVar4 = offset
848+ if (magic <= offset ):
849+ uVar4 = magic - 1
850+
851+ index = ((padlen - 1 ) - cntr )
852+ iVar5 = iVar3 * magic
853+ while True :
854+ if (uVar4 < 0 ) : break
855+ iVar3 += 1
856+ ret [index ] = st [uVar4 + iVar5 ]
857+ uVar4 -= 1
858+ index = index - 1
859+ iVar5 = iVar5 + magic ;
860+ cntr += 1 ;
861+ if iVar3 >= divs : break
862+ offset = offset + 1
863+ if offset >= ((magic - 1 ) + divs ) :break
864+ return ret
865+
866+ #not sure if the third variant is used anywhere, but it is in Kindle, so I tried to add it
867+ def obfuscate3 (secret , version ):
868+ if version == 1 : # v1 does not use obfuscation
869+ return secret
870+ magic , word = OBFUSCATION_TABLE ["V%d" % version ]
871+ # extend secret so that its length is divisible by the magic number
872+ if len (secret ) % magic != 0 :
873+ secret = secret + b'\x00 ' * (magic - len (secret ) % magic )
874+ #secret = bytearray(secret)
875+ obfuscated = bytearray (len (secret ))
876+ wordhash = bytearray (hashlib .sha256 (word ).digest ())
877+ print (wordhash .hex ())
878+ shuffled = bytearray (scramble3 (secret ,magic ))
879+ print (shuffled )
880+ # shuffle secret and xor it with the first half of the word hash
881+ for i in range (0 , len (secret )):
882+ obfuscated [i ] = shuffled [i ] ^ wordhash [i % 16 ]
883+ return obfuscated
884+
885+ def scramble (st ,magic ):
886+ ret = bytearray (len (st ))
887+ padlen = len (st )
888+ for counter in range (len (st )):
889+ ivar2 = (padlen // 2 )- 2 * (counter % magic )+ magic + counter - 1
890+ ret [ivar2 % padlen ]= st [counter ]
891+ return ret
892+
893+ def obfuscate2 (secret , version ):
894+ if version == 1 : # v1 does not use obfuscation
895+ return secret
896+ magic , word = OBFUSCATION_TABLE ["V%d" % version ]
897+ # extend secret so that its length is divisible by the magic number
898+ if len (secret ) % magic != 0 :
899+ secret = secret + b'\x00 ' * (magic - len (secret ) % magic )
900+ obfuscated = bytearray (len (secret ))
901+ wordhash = bytearray (hashlib .sha256 (word ).digest ()[16 :])
902+ print (wordhash .hex ())
903+ shuffled = bytearray (scramble (secret ,magic ))
904+ # shuffle secret and xor it with the first half of the word hash
905+ for i in range (0 , len (secret )):
906+ obfuscated [i ] = shuffled [i ] ^ wordhash [i % 16 ]
907+ return obfuscated
813908
814909# obfuscate shared secret according to the VoucherEnvelope version
815910def obfuscate (secret , version ):
@@ -868,7 +963,6 @@ def __init__(self, voucherenv, dsn, secret):
868963
869964 def decryptvoucher (self ):
870965 shared = ("PIDv3" + self .encalgorithm + self .enctransformation + self .hashalgorithm ).encode ('ASCII' )
871-
872966 self .lockparams .sort ()
873967 for param in self .lockparams :
874968 if param == "ACCOUNT_SECRET" :
@@ -877,14 +971,24 @@ def decryptvoucher(self):
877971 shared += param .encode ('ASCII' ) + self .dsn
878972 else :
879973 _assert (False , "Unknown lock parameter: %s" % param )
880-
881- sharedsecret = obfuscate (shared , self .version )
882-
883- key = hmac .new (sharedsecret , b"PIDv3" , digestmod = hashlib .sha256 ).digest ()
884- aes = AES .new (key [:32 ], AES .MODE_CBC , self .cipheriv [:16 ])
885- b = aes .decrypt (self .ciphertext )
886- b = pkcs7unpad (b , 16 )
887-
974+
975+
976+ sharedsecrets = [obfuscate (shared , self .version ),obfuscate2 (shared , self .version ),obfuscate3 (shared , self .version )]
977+ decrypted = False
978+ ex = None
979+ for sharedsecret in sharedsecrets :
980+ key = hmac .new (sharedsecret , b"PIDv3" , digestmod = hashlib .sha256 ).digest ()
981+ aes = AES .new (key [:32 ], AES .MODE_CBC , self .cipheriv [:16 ])
982+ try :
983+ b = aes .decrypt (self .ciphertext )
984+ b = pkcs7unpad (b , 16 )
985+ decrypted = True
986+ print ("Decryption succeeded" )
987+ break
988+ except Exception as ex :
989+ print ("Decryption failed, trying next fallback " )
990+ if not decrypted :
991+ raise ex
888992 self .drmkey = BinaryIonParser (BytesIO (b ))
889993 addprottable (self .drmkey )
890994
@@ -923,6 +1027,7 @@ def parse(self):
9231027 while self .envelope .hasnext ():
9241028 self .envelope .next ()
9251029 field = self .envelope .getfieldname ()
1030+ print (field )
9261031 if field == "voucher" :
9271032 self .voucher = BinaryIonParser (BytesIO (self .envelope .lobvalue ()))
9281033 addprottable (self .voucher )
@@ -936,6 +1041,10 @@ def parse(self):
9361041 while self .envelope .hasnext ():
9371042 self .envelope .next ()
9381043 field = self .envelope .getfieldname ()
1044+ try :
1045+ print (self .envelope .stringvalue ())
1046+ except :
1047+ pass
9391048 if field == "encryption_algorithm" :
9401049 self .encalgorithm = self .envelope .stringvalue ()
9411050 elif field == "encryption_transformation" :
0 commit comments