def testEncryptSymmetric(self): data = OpenPGP.LiteralDataPacket('This is text.', 'u', 'stuff.txt') encrypted = OpenPGP.cryptography.Wrapper(OpenPGP.Message( [data])).encrypt('secret') decrypted = OpenPGP.cryptography.Wrapper(encrypted).decrypt_symmetric( 'secret') nose.tools.assert_equal(decrypted[0].data, b'This is text.')
def sign(self, packet, hash='SHA256', keyid=None): if self._key and not isinstance(packet, OpenPGP.Packet) and not isinstance(packet, OpenPGP.Message): packet = OpenPGP.LiteralDataPacket(packet) else: packet = self._parse_packet(packet) if isinstance(packet, OpenPGP.SecretKeyPacket) or isinstance(packet, Crypto.PublicKey.RSA._RSAobj) or isinstance(packet, Crypto.PublicKey.DSA._DSAobj) or (hasattr(packet, '__getitem__') and isinstance(packet[0], OpenPGP.SecretKeyPacket)): key = packet message = self._message else: key = self._key message = packet if not key or not message: return None # Missing some data if isinstance(message, OpenPGP.Message): message = message.signature_and_data()[1] if not (isinstance(key, Crypto.PublicKey.RSA._RSAobj) or isinstance(packet, Crypto.PublicKey.DSA._DSAobj)): key = self.__class__(key) if not keyid: keyid = key.key().fingerprint()[-16:] key = key.private_key(keyid) key_algorithm = None if isinstance(key, Crypto.PublicKey.RSA._RSAobj): key_algorithm = 'RSA' elif isinstance(key, Crypto.PublicKey.DSA._DSAobj): key_algorithm = 'DSA' sig = OpenPGP.SignaturePacket(message, key_algorithm, hash.upper()) if keyid: sig.hashed_subpackets.append(OpenPGP.SignaturePacket.IssuerPacket(keyid)) def doDSA(h, m): return list(key.sign(h.new(m).digest()[0:int(Crypto.Util.number.size(key.q) / 8)], Crypto.Random.random.StrongRandom().randint(1,key.q-1))) sig.sign_data({'RSA': { 'MD5': lambda m: [Crypto.Signature.PKCS1_v1_5.new(key).sign(Crypto.Hash.MD5.new(m))], 'RIPEMD160': lambda m: [Crypto.Signature.PKCS1_v1_5.new(key).sign(Crypto.Hash.RIPEMD.new(m))], 'SHA1': lambda m: [Crypto.Signature.PKCS1_v1_5.new(key).sign(Crypto.Hash.SHA.new(m))], 'SHA224': lambda m: [Crypto.Signature.PKCS1_v1_5.new(key).sign(Crypto.Hash.SHA224.new(m))], 'SHA256': lambda m: [Crypto.Signature.PKCS1_v1_5.new(key).sign(Crypto.Hash.SHA256.new(m))], 'SHA384': lambda m: [Crypto.Signature.PKCS1_v1_5.new(key).sign(Crypto.Hash.SHA384.new(m))], 'SHA512': lambda m: [Crypto.Signature.PKCS1_v1_5.new(key).sign(Crypto.Hash.SHA512.new(m))], }, 'DSA': { 'MD5': lambda m: doDSA(Crypto.Hash.MD5, m), 'RIPEMD160': lambda m: doDSA(Crypto.Hash.RIPEMD, m), 'SHA1': lambda m: doDSA(Crypto.Hash.SHA, m), 'SHA224': lambda m: doDSA(Crypto.Hash.SHA224, m), 'SHA256': lambda m: doDSA(Crypto.Hash.SHA256, m), 'SHA384': lambda m: doDSA(Crypto.Hash.SHA384, m), 'SHA512': lambda m: doDSA(Crypto.Hash.SHA512, m), }}) return OpenPGP.Message([sig, message])
def encrypt(self, passphrases_and_keys, symmetric_algorithm=9): cipher, key_bytes, key_block_bytes = self.get_cipher( symmetric_algorithm) if not cipher: raise Exception("Unsupported cipher") prefix = Crypto.Random.new().read(key_block_bytes) prefix += prefix[-2:] key = Crypto.Random.new().read(key_bytes) session_cipher = cipher(key)(None) to_encrypt = prefix + self._message.to_bytes() mdc = OpenPGP.ModificationDetectionCodePacket( Crypto.Hash.SHA.new(to_encrypt + b'\xD3\x14').digest()) to_encrypt += mdc.to_bytes() def doEncrypt(cipher): ctx = cipher.encryptor() return lambda x: ctx.update(x) + ctx.finalize() encrypted = [ OpenPGP.IntegrityProtectedDataPacket( self._block_pad_unpad(key_block_bytes, to_encrypt, doEncrypt(session_cipher))) ] if not isinstance(passphrases_and_keys, collections.Iterable) or hasattr( passphrases_and_keys, 'encode'): passphrases_and_keys = [passphrases_and_keys] for psswd in passphrases_and_keys: if isinstance(psswd, OpenPGP.PublicKeyPacket): if not psswd.key_algorithm in [1, 2, 3]: raise Exception("Only RSA keys are supported.") rsa = self.__class__(psswd).public_key() pkcs1 = Crypto.Cipher.PKCS1_v1_5.new(rsa) esk = pkcs1.encrypt( pack('!B', symmetric_algorithm) + key + pack('!H', OpenPGP.checksum(key))) esk = pack('!H', OpenPGP.bitlength(esk)) + esk encrypted = [ OpenPGP.AsymmetricSessionKeyPacket( psswd.key_algorithm, psswd.fingerprint(), esk) ] + encrypted elif hasattr(psswd, 'encode'): psswd = psswd.encode('utf-8') s2k = OpenPGP.S2K(Crypto.Random.new().read(10)) packet_cipher = cipher(s2k.make_key(psswd, key_bytes))(None) esk = self._block_pad_unpad( key_block_bytes, pack('!B', symmetric_algorithm) + key, doEncrypt(packet_cipher)) encrypted = [ OpenPGP.SymmetricSessionKeyPacket(s2k, esk, symmetric_algorithm) ] + encrypted return OpenPGP.Message(encrypted)
def test_partial_results(self): m = OpenPGP.Message.parse( OpenPGP.Message([ OpenPGP.UserIDPacket('My name <*****@*****.**>'), OpenPGP.UserIDPacket('Your name <*****@*****.**>') ]).to_bytes()) m[0] # Just the first one nose.tools.assert_equal(len(m.force()), 2)
def testEncryptAsymmetric(self): key = OpenPGP.Message.parse( open(os.path.dirname(__file__) + '/data/helloKey.gpg', 'rb').read()) data = OpenPGP.LiteralDataPacket('This is text.', 'u', 'stuff.txt') encrypted = OpenPGP.Crypto.Wrapper(OpenPGP.Message([data ])).encrypt(key) decryptor = OpenPGP.Crypto.Wrapper(key) decrypted = decryptor.decrypt(encrypted) nose.tools.assert_equal(decrypted[0].data, b'This is text.')
def sign_key_userid(self, packet, hash='SHA256', keyid=None): if isinstance(packet, list): packet = OpenPGP.Message(packet) elif not isinstance(packet, OpenPGP.Message): packet = OpenPGP.Message.parse(packet) key = self.key(keyid) if not key or not packet: # Missing some data return None if not keyid: keyid = key.fingerprint()[-16:] key = self.private_key(keyid) sig = None for p in packet: if isinstance(p, OpenPGP.SignaturePacket): sig = p if not sig: sig = OpenPGP.SignaturePacket(packet, 'RSA', hash.upper()) sig.signature_type = 0x13 sig.hashed_subpackets.append(OpenPGP.SignaturePacket.KeyFlagsPacket([0x01])) sig.hashed_subpackets.append(OpenPGP.SignaturePacket.IssuerPacket(keyid)) packet.append(sig) def doDSA(h, m): return list(key.sign(h.new(m).digest()[0:int(Crypto.Util.number.size(key.q) / 8)], Crypto.Random.random.StrongRandom().randint(1,key.q-1))) def doRSA(h, m): ctx = key.signer(padding.PKCS1v15(), h()) ctx.update(m) return [ctx.finalize()] sig.sign_data({'RSA': { 'MD5': lambda m: doRSA(hashes.MD5, m), 'RIPEMD160': lambda m: doRSA(hashes.RIPEMD160, m), 'SHA1': lambda m: doRSA(hashes.SHA1, m), 'SHA224': lambda m: doRSA(hashes.SHA224, m), 'SHA256': lambda m: doRSA(hashes.SHA256, m), 'SHA384': lambda m: doRSA(hashes.SHA384, m), 'SHA512': lambda m: doRSA(hashes.SHA512, m) }, 'DSA': { 'MD5': lambda m: doDSA(Crypto.Hash.MD5, m), 'RIPEMD160': lambda m: doDSA(Crypto.Hash.RIPEMD, m), 'SHA1': lambda m: doDSA(Crypto.Hash.SHA, m), 'SHA224': lambda m: doDSA(Crypto.Hash.SHA224, m), 'SHA256': lambda m: doDSA(Crypto.Hash.SHA256, m), 'SHA384': lambda m: doDSA(Crypto.Hash.SHA384, m), 'SHA512': lambda m: doDSA(Crypto.Hash.SHA512, m), }}) return packet
def decrypt(self, packet): if isinstance(packet, list): packet = OpenPGP.Message(packet) elif not isinstance(packet, OpenPGP.Message): packet = OpenPGP.Message.parse(packet) if isinstance(packet, OpenPGP.SecretKeyPacket) or isinstance( packet, rsa.RSAPrivateKey) or ( hasattr(packet, '__getitem__') and isinstance(packet[0], OpenPGP.SecretKeyPacket)): keys = packet else: keys = self._key self._message = packet if not keys or not self._message: return None # Missing some data if not isinstance(keys, rsa.RSAPrivateKey): keys = self.__class__(keys) for p in self._message: if isinstance(p, OpenPGP.AsymmetricSessionKeyPacket): if isinstance(keys, rsa.RSAPrivateKey): sk = self.try_decrypt_session(keys, p.encrypted_data[2:]) elif len(p.keyid.replace('0', '')) < 1: for k in keys.key: sk = self.try_decrypt_session( self.convert_private_key(k), p.encyrpted_data[2:]) if sk: break else: key = keys.private_key(p.keyid) sk = self.try_decrypt_session(key, p.encrypted_data[2:]) if not sk: continue r = self.decrypt_packet(self.encrypted_data(), sk[0], sk[1]) if r: return r return None # Failed
def sign(self, packet, hash='SHA256', keyid=None): if self._key and not isinstance(packet, OpenPGP.Packet) and not isinstance(packet, OpenPGP.Message): packet = OpenPGP.LiteralDataPacket(packet) else: packet = self._parse_packet(packet) if isinstance(packet, OpenPGP.SecretKeyPacket) or isinstance(packet, RSAPrivateKey) or isinstance(packet, DSAPrivateKey) or (hasattr(packet, '__getitem__') and isinstance(packet[0], OpenPGP.SecretKeyPacket)): key = packet message = self._message else: key = self._key message = packet if not key or not message: return None # Missing some data if isinstance(message, OpenPGP.Message): message = message.signature_and_data()[1] if not (isinstance(key, RSAPrivateKey) or isinstance(key, DSAPrivateKey)): key = self.__class__(key) if not keyid: keyid = key.key().fingerprint()[-16:] key = key.private_key(keyid) key_algorithm = None if isinstance(key, RSAPrivateKey): key_algorithm = 'RSA' elif isinstance(key, DSAPrivateKey): key_algorithm = 'DSA' sig = OpenPGP.SignaturePacket(message, key_algorithm, hash.upper()) if keyid: sig.hashed_subpackets.append(OpenPGP.SignaturePacket.IssuerPacket(keyid)) def doDSA(h, m): ctx = key.signer(h()) ctx.update(m) return list(self._decode_dsa_der(ctx.finalize())) def doRSA(h, m): ctx = key.signer(padding.PKCS1v15(), h()) ctx.update(m) return [ctx.finalize()] sig.sign_data({'RSA': { 'MD5': lambda m: doRSA(hashes.MD5, m), 'RIPEMD160': lambda m: doRSA(hashes.RIPEMD160, m), 'SHA1': lambda m: doRSA(hashes.SHA1, m), 'SHA224': lambda m: doRSA(hashes.SHA224, m), 'SHA256': lambda m: doRSA(hashes.SHA256, m), 'SHA384': lambda m: doRSA(hashes.SHA384, m), 'SHA512': lambda m: doRSA(hashes.SHA512, m) }, 'DSA': { 'MD5': lambda m: doDSA(hashes.MD5, m), 'RIPEMD160': lambda m: doDSA(hashes.RIPME160, m), 'SHA1': lambda m: doDSA(hashes.SHA1, m), 'SHA224': lambda m: doDSA(hashes.SHA224, m), 'SHA256': lambda m: doDSA(hashes.SHA256, m), 'SHA384': lambda m: doDSA(hashes.SHA384, m), 'SHA512': lambda m: doDSA(hashes.SHA512, m) }}) return OpenPGP.Message([sig, message])