def computeO(userPassword, ownerPassword, revision): from reportlab.lib.arciv import ArcIV #print 'digest of hello is %s' % md5('hello').digest() assert revision in (2, 3), 'Unknown algorithm revision %s' % revision if ownerPassword in (None, ''): ownerPassword = userPassword ownerPad = ownerPassword + PadString ownerPad = ownerPad[0:32] password = userPassword + PadString userPad = password[:32] digest = md5(ownerPad).digest() if revision == 2: O = ArcIV(digest[:5]).encode(userPad) elif revision == 3: for i in range(50): digest = md5(digest).digest() digest = digest[:16] O = userPad for i in range(20): thisKey = xorKey(i, digest) O = ArcIV(thisKey).encode(O) return O
def computeO(userPassword, ownerPassword, revision): from reportlab.lib.arciv import ArcIV #print 'digest of hello is %s' % md5('hello').digest() assert revision in (2, 3), 'Unknown algorithm revision %s' % revision if not ownerPassword: ownerPassword = userPassword ownerPad = asBytes(ownerPassword) + PadString ownerPad = ownerPad[0:32] password = asBytes(userPassword) + PadString userPad = password[:32] digest = md5(ownerPad).digest() if DEBUG: print( 'PadString=%s\nownerPad=%s\npassword=%s\nuserPad=%s\ndigest=%s\nrevision=%s' % (ascii(PadString), ascii(ownerPad), ascii(password), ascii(userPad), ascii(digest), revision)) if revision == 2: O = ArcIV(digest[:5]).encode(userPad) elif revision == 3: for i in range(50): digest = md5(digest).digest() digest = digest[:16] O = userPad for i in range(20): thisKey = xorKey(i, digest) O = ArcIV(thisKey).encode(O) if DEBUG: print('computeO(%s,%s,%s)==>%s' % tuple([ hexText(str(x)) for x in (userPassword, ownerPassword, revision, O) ])) return O
def encryptionkey(password, OwnerKey, Permissions, FileId1, revision=2): # FileId1 is first string of the fileid array # add padding string #AR force same as iText example #Permissions = -1836 #int(Permissions - 2**31) password = asBytes(password) + PadString # truncate to 32 bytes password = password[:32] # translate permissions to string, low order byte first p = Permissions # + 2**32L permissionsString = b"" for i in range(4): byte = (p & 0xff) # seems to match what iText does p = p >> 8 permissionsString += int2Byte(byte % 256) hash = md5(asBytes(password)) hash.update(asBytes(OwnerKey)) hash.update(asBytes(permissionsString)) hash.update(asBytes(FileId1)) md5output = hash.digest() if revision == 2: key = md5output[:5] elif revision == 3: #revision 3 algorithm - loop 50 times for x in range(50): md5output = md5(md5output).digest() key = md5output[:16] if DEBUG: print('encryptionkey(%s,%s,%s,%s,%s)==>%s' % tuple([ hexText(str(x)) for x in (password, OwnerKey, Permissions, FileId1, revision, key) ])) return key
def encryptionkey(password, OwnerKey, Permissions, FileId1, revision=2): # FileId1 is first string of the fileid array # add padding string #AR force same as iText example #Permissions = -1836 #int(Permissions - 2**31) password = password + PadString # truncate to 32 bytes password = password[:32] # translate permissions to string, low order byte first p = Permissions # + 2**32L permissionsString = "" for i in range(4): byte = (p & 0xff) # seems to match what iText does p = p >> 8 permissionsString = permissionsString + chr(byte % 256) hash = md5(password) hash.update(OwnerKey) hash.update(permissionsString) hash.update(FileId1) md5output = hash.digest() if revision == 2: key = md5output[:5] elif revision == 3: #revision 3 algorithm - loop 50 times for x in range(50): md5output = md5(md5output).digest() key = md5output[:16] return key
def computeO(userPassword, ownerPassword, revision): from reportlab.lib.arciv import ArcIV #print 'digest of hello is %s' % md5('hello').digest() assert revision in (2,3), 'Unknown algorithm revision %s' % revision if not ownerPassword: ownerPassword = userPassword ownerPad = asBytes(ownerPassword) + PadString ownerPad = ownerPad[0:32] password = asBytes(userPassword) + PadString userPad = password[:32] digest = md5(ownerPad).digest() if DEBUG: print('PadString=%s\nownerPad=%s\npassword=%s\nuserPad=%s\ndigest=%s\nrevision=%s' % (ascii(PadString),ascii(ownerPad),ascii(password),ascii(userPad),ascii(digest),revision)) if revision == 2: O = ArcIV(digest[:5]).encode(userPad) elif revision == 3: for i in range(50): digest = md5(digest).digest() digest = digest[:16] O = userPad for i in range(20): thisKey = xorKey(i, digest) O = ArcIV(thisKey).encode(O) if DEBUG: print('computeO(%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (userPassword, ownerPassword, revision,O)])) return O
def encryptionkey(password, OwnerKey, Permissions, FileId1, revision=2): # FileId1 is first string of the fileid array # add padding string #AR force same as iText example #Permissions = -1836 #int(Permissions - 2**31) password = asBytes(password) + PadString # truncate to 32 bytes password = password[:32] # translate permissions to string, low order byte first p = Permissions# + 2**32L permissionsString = b"" for i in range(4): byte = (p & 0xff) # seems to match what iText does p = p>>8 permissionsString += int2Byte(byte % 256) hash = md5(asBytes(password)) hash.update(asBytes(OwnerKey)) hash.update(asBytes(permissionsString)) hash.update(asBytes(FileId1)) md5output = hash.digest() if revision==2: key = md5output[:5] elif revision==3: #revision 3 algorithm - loop 50 times for x in range(50): md5output = md5(md5output).digest() key = md5output[:16] if DEBUG: print('encryptionkey(%s,%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (password, OwnerKey, Permissions, FileId1, revision, key)])) return key
def computeU(encryptionkey, encodestring=PadString, revision=None, documentId=None): revision = checkRevision(revision) from reportlab.lib.arciv import ArcIV if revision == 2: result = ArcIV(encryptionkey).encode(encodestring) elif revision == 3: assert documentId is not None, "Revision 3 algorithm needs the document ID!" h = md5(PadString) h.update(rawBytes(documentId)) tmp = h.digest() tmp = ArcIV(encryptionkey).encode(tmp) for n in range(1, 20): thisKey = xorKey(n, encryptionkey) tmp = ArcIV(thisKey).encode(tmp) while len(tmp) < 32: tmp += b'\0' result = tmp if DEBUG: print('computeU(%s,%s,%s,%s)==>%s' % tuple([ hexText(str(x)) for x in (encryptionkey, encodestring, revision, documentId, result) ])) return result
def encodePDF(key, objectNumber, generationNumber, string, revision=2): "Encodes a string or stream" #print 'encodePDF (%s, %d, %d, %s)' % (hexText(key), objectNumber, generationNumber, string) # extend 3 bytes of the object Number, low byte first newkey = key n = objectNumber for i in range(3): newkey += int2Byte(n & 0xff) n = n >> 8 # extend 2 bytes of the generationNumber n = generationNumber for i in range(2): newkey += int2Byte(n & 0xff) n = n >> 8 md5output = md5(newkey).digest() if revision == 2: key = md5output[:10] elif revision == 3: key = md5output #all 16 bytes from reportlab.lib.arciv import ArcIV encrypted = ArcIV(key).encode(string) #print 'encrypted=', hexText(encrypted) if DEBUG: print('encodePDF(%s,%s,%s,%s,%s)==>%s' % tuple([ hexText(str(x)) for x in (key, objectNumber, generationNumber, string, revision, encrypted) ])) return encrypted
def encodePDF(key, objectNumber, generationNumber, string, revision=None): "Encodes a string or stream" revision = checkRevision(revision) #print 'encodePDF (%s, %d, %d, %s)' % (hexText(key), objectNumber, generationNumber, string) # extend 3 bytes of the object Number, low byte first if revision in (2, 3): newkey = key n = objectNumber for i in range(3): newkey += int2Byte(n & 0xff) n = n >> 8 # extend 2 bytes of the generationNumber n = generationNumber for i in range(2): newkey += int2Byte(n & 0xff) n = n >> 8 md5output = md5(newkey).digest() if revision == 2: key = md5output[:10] elif revision == 3: key = md5output #all 16 bytes from reportlab.lib.arciv import ArcIV encrypted = ArcIV(key).encode(string) #print 'encrypted=', hexText(encrypted) elif revision == 5: iv = os_urandom(16) encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC(key, iv=iv)) # pkcs7 style padding so that the size of the encrypted block is multiple of 16 string_len = len(string) padding = "" padding_len = (16 - (string_len % 16)) if string_len > 16 else (16 - string_len) if padding_len > 0: padding = chr(padding_len) * padding_len if isinstance(string, str): string = (string + padding).encode("utf-8") else: string += asBytes(padding) encrypted = iv + encrypter.feed(string) encrypted += encrypter.feed() if DEBUG: print('encodePDF(%s,%s,%s,%s,%s)==>%s' % tuple([ hexText(str(x)) for x in (key, objectNumber, generationNumber, string, revision, encrypted) ])) return encrypted
def computeU(encryptionkey, encodestring=PadString,revision=2,documentId=None): from reportlab.lib.arciv import ArcIV if revision == 2: result = ArcIV(encryptionkey).encode(encodestring) elif revision == 3: assert documentId is not None, "Revision 3 algorithm needs the document ID!" h = md5(PadString) h.update(rawBytes(documentId)) tmp = h.digest() tmp = ArcIV(encryptionkey).encode(tmp) for n in range(1,20): thisKey = xorKey(n, encryptionkey) tmp = ArcIV(thisKey).encode(tmp) while len(tmp) < 32: tmp += b'\0' result = tmp if DEBUG: print('computeU(%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (encryptionkey, encodestring,revision,documentId,result)])) return result
def encodePDF(key, objectNumber, generationNumber, string, revision=5): "Encodes a string or stream" #print 'encodePDF (%s, %d, %d, %s)' % (hexText(key), objectNumber, generationNumber, string) # extend 3 bytes of the object Number, low byte first if revision in (2, 3): newkey = key n = objectNumber for i in range(3): newkey = newkey + chr(n & 0xff) n = n >> 8 # extend 2 bytes of the generationNumber n = generationNumber for i in range(2): newkey = newkey + chr(n & 0xff) n = n >> 8 md5output = md5(newkey).digest() if revision == 2: key = md5output[:10] elif revision == 3: key = md5output #all 16 bytes from reportlab.lib.arciv import ArcIV encrypted = ArcIV(key).encode(string) #print 'encrypted=', hexText(encrypted) elif revision == 5: # pkcs7 style padding so that the size of the encrypted block is multiple of 16 padding_len = 16 - (len(string) % 16) padding = "" if padding_len > 0: padding = chr(padding_len) * padding_len if isinstance(string, str): string = (string + padding).encode("utf-8") else: string += bytes(padding, "ascii") iv = Random.new().read(16) aes_cipher = AES.new(key, AES.MODE_CBC, iv) encrypted = iv + aes_cipher.encrypt(string) return encrypted
def computeU(encryptionkey, encodestring=PadString, revision=2, documentId=None): from reportlab.lib.arciv import ArcIV if revision == 2: result = ArcIV(encryptionkey).encode(encodestring) elif revision == 3: assert documentId is not None, "Revision 3 algorithm needs the document ID!" h = md5(PadString) h.update(documentId) tmp = h.digest() tmp = ArcIV(encryptionkey).encode(tmp) for n in range(1, 20): thisKey = xorKey(n, encryptionkey) tmp = ArcIV(thisKey).encode(tmp) while len(tmp) < 32: tmp = tmp + '\000' result = tmp return result
def encodePDF(key, objectNumber, generationNumber, string, revision=2): "Encodes a string or stream" #print 'encodePDF (%s, %d, %d, %s)' % (hexText(key), objectNumber, generationNumber, string) # extend 3 bytes of the object Number, low byte first newkey = key n = objectNumber for i in range(3): newkey += int2Byte(n & 0xff) n = n>>8 # extend 2 bytes of the generationNumber n = generationNumber for i in range(2): newkey += int2Byte(n & 0xff) n = n>>8 md5output = md5(newkey).digest() if revision == 2: key = md5output[:10] elif revision == 3: key = md5output #all 16 bytes from reportlab.lib.arciv import ArcIV encrypted = ArcIV(key).encode(string) #print 'encrypted=', hexText(encrypted) if DEBUG: print('encodePDF(%s,%s,%s,%s,%s)==>%s' % tuple([hexText(str(x)) for x in (key, objectNumber, generationNumber, string, revision,encrypted)])) return encrypted