if passphrase: passphrase = tobytes(passphrase) found = False try: p8_private_key = PBES1.decrypt(p8_private_key, passphrase) found = True except PbesError, e: error_str = "PBES1[%s]" % str(e) except ValueError: error_str = "PBES1[Invalid]" if not found: try: p8_private_key = PBES2.decrypt(p8_private_key, passphrase) found = True except PbesError, e: error_str += ",PBES2[%s]" % str(e) except ValueError: error_str += ",PBES2[Invalid]" if not found: raise ValueError("Error decoding PKCS#8 (%s)" % error_str) pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4)) if len(pk_info) == 2 and not passphrase: raise ValueError("Not a valid clear PKCS#8 structure " "(maybe it is encrypted?)") #
if passphrase: passphrase = tobytes(passphrase) found = False try: p8_private_key = PBES1.decrypt(p8_private_key, passphrase) found = True except PbesError, e: error_str = "PBES1[%s]" % str(e) except ValueError: error_str = "PBES1[Invalid]" if not found: try: p8_private_key = PBES2.decrypt(p8_private_key, passphrase) found = True except PbesError, e: error_str += ",PBES2[%s]" % str(e) except ValueError: error_str += ",PBES2[Invalid]" if not found: raise ValueError("Error decoding PKCS#8 (%s)" % error_str) pk_info = decode_der(DerSequence, p8_private_key) if len(pk_info) == 2 and not passphrase: raise ValueError("Not a valid clear PKCS#8 structure " "(maybe it is encrypted?)") if not 3 <= len(pk_info) <= 4 or pk_info[0] != 0: raise ValueError("Not a valid PrivateKeyInfo SEQUENCE")
def unwrap(p8_private_key, passphrase=None): """Unwrap a private key from a PKCS#8 blob (clear or encrypted). :Parameters: p8_private_key : byte string The private key wrapped into a PKCS#8 blob, DER encoded. passphrase : (byte) string The passphrase to use to decrypt the blob (if it is encrypted). :Return: A tuple containing: #. the algorithm identifier of the wrapped key (OID, dotted string) #. the private key (byte string, DER encoded) #. the associated parameters (byte string, DER encoded) or ``None`` :Raises ValueError: If decoding fails """ if passphrase: passphrase = tobytes(passphrase) found = False try: p8_private_key = PBES1.decrypt(p8_private_key, passphrase) found = True except PbesError as e: error_str = "PBES1[%s]" % str(e) except ValueError: error_str = "PBES1[Invalid]" if not found: try: p8_private_key = PBES2.decrypt(p8_private_key, passphrase) found = True except PbesError as e: error_str += ",PBES2[%s]" % str(e) except ValueError: error_str += ",PBES2[Invalid]" if not found: raise ValueError("Error decoding PKCS#8 (%s)" % error_str) pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4)) if len(pk_info) == 2 and not passphrase: raise ValueError("Not a valid clear PKCS#8 structure " "(maybe it is encrypted?)") # # PrivateKeyInfo ::= SEQUENCE { # version Version, # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, # privateKey PrivateKey, # attributes [0] IMPLICIT Attributes OPTIONAL # } # Version ::= INTEGER if pk_info[0] != 0: raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") # PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier # # EncryptedPrivateKeyInfo ::= SEQUENCE { # encryptionAlgorithm EncryptionAlgorithmIdentifier, # encryptedData EncryptedData # } # EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier # AlgorithmIdentifier ::= SEQUENCE { # algorithm OBJECT IDENTIFIER, # parameters ANY DEFINED BY algorithm OPTIONAL # } algo = DerSequence().decode(pk_info[1], nr_elements=(1, 2)) algo_oid = DerObjectId().decode(algo[0]).value if len(algo) == 1: algo_params = None else: try: DerNull().decode(algo[1]) algo_params = None except: algo_params = algo[1] # EncryptedData ::= OCTET STRING private_key = DerOctetString().decode(pk_info[2]).payload return (algo_oid, private_key, algo_params)
def unwrap(p8_private_key, passphrase=None): """Unwrap a private key from a PKCS#8 blob (clear or encrypted). :Parameters: p8_private_key : byte string The private key wrapped into a PKCS#8 blob, DER encoded. passphrase : (byte) string The passphrase to use to decrypt the blob (if it is encrypted). :Return: A tuple containing: #. the algorithm identifier of the wrapped key (OID, dotted string) #. the private key (byte string, DER encoded) #. the associated parameters (byte string, DER encoded) or ``None`` :Raises ValueError: If decoding fails """ if passphrase: passphrase = tobytes(passphrase) found = False try: p8_private_key = PBES1.decrypt(p8_private_key, passphrase) found = True except PbesError as e: error_str = "PBES1[%s]" % str(e) except ValueError: error_str = "PBES1[Invalid]" if not found: try: p8_private_key = PBES2.decrypt(p8_private_key, passphrase) found = True except PbesError as e: error_str += ",PBES2[%s]" % str(e) except ValueError: error_str += ",PBES2[Invalid]" if not found: raise ValueError("Error decoding PKCS#8 (%s)" % error_str) pk_info = decode_der(DerSequence, p8_private_key) if len(pk_info) == 2 and not passphrase: raise ValueError("Not a valid clear PKCS#8 structure " "(maybe it is encrypted?)") if not 3 <= len(pk_info) <= 4 or pk_info[0] != 0: raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") # # AlgorithmIdentifier ::= SEQUENCE { # algorithm OBJECT IDENTIFIER, # parameters ANY DEFINED BY algorithm OPTIONAL # } # algo_id = decode_der(DerSequence, pk_info[1]) if not 1 <= len(algo_id) <= 2: raise ValueError("Not a valid AlgorithmIdentifier SEQUENCE") algo = decode_der(DerObjectId, algo_id[0]).value private_key = decode_der(DerOctetString, pk_info[2]).payload if len(algo_id) == 2 and algo_id[1] != b('\x05\x00'): params = algo_id[1] else: params = None return (algo, private_key, params)
def test6(self): ct = PBES2.encrypt(self.ref, self.passphrase, 'scryptAndAES256-CBC') pt = PBES2.decrypt(ct, self.passphrase) self.assertEqual(self.ref, pt)
def test3(self): ct = PBES2.encrypt(self.ref, self.passphrase, 'PBKDF2WithHMAC-SHA1AndAES192-CBC') pt = PBES2.decrypt(ct, self.passphrase) self.assertEqual(self.ref, pt)
def unwrap(p8_private_key, passphrase=None): """Unwrap a private key from a PKCS#8 blob (clear or encrypted). Args: p8_private_key (byte string): The private key wrapped into a PKCS#8 blob, DER encoded. passphrase (byte string or string): The passphrase to use to decrypt the blob (if it is encrypted). Return: A tuple containing #. the algorithm identifier of the wrapped key (OID, dotted string) #. the private key (byte string, DER encoded) #. the associated parameters (byte string, DER encoded) or ``None`` Raises: ValueError : if decoding fails """ if passphrase: passphrase = tobytes(passphrase) found = False try: p8_private_key = PBES1.decrypt(p8_private_key, passphrase) found = True except PbesError as e: error_str = "PBES1[%s]" % str(e) except ValueError: error_str = "PBES1[Invalid]" if not found: try: p8_private_key = PBES2.decrypt(p8_private_key, passphrase) found = True except PbesError as e: error_str += ",PBES2[%s]" % str(e) except ValueError: error_str += ",PBES2[Invalid]" if not found: raise ValueError("Error decoding PKCS#8 (%s)" % error_str) pk_info = DerSequence().decode(p8_private_key, nr_elements=(2, 3, 4, 5)) if len(pk_info) == 2 and not passphrase: raise ValueError("Not a valid clear PKCS#8 structure " "(maybe it is encrypted?)") # RFC5208, PKCS#8, version is v1(0) # # PrivateKeyInfo ::= SEQUENCE { # version Version, # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, # privateKey PrivateKey, # attributes [0] IMPLICIT Attributes OPTIONAL # } # # RFC5915, Asymmetric Key Package, version is v2(1) # # OneAsymmetricKey ::= SEQUENCE { # version Version, # privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, # privateKey PrivateKey, # attributes [0] Attributes OPTIONAL, # ..., # [[2: publicKey [1] PublicKey OPTIONAL ]], # ... # } if pk_info[0] == 0: if len(pk_info) not in (3, 4): raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") elif pk_info[0] == 1: if len(pk_info) not in (3, 4, 5): raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") else: raise ValueError("Not a valid PrivateKeyInfo SEQUENCE") algo = DerSequence().decode(pk_info[1], nr_elements=(1, 2)) algo_oid = DerObjectId().decode(algo[0]).value if len(algo) == 1: algo_params = None else: try: DerNull().decode(algo[1]) algo_params = None except: algo_params = algo[1] # PrivateKey ::= OCTET STRING private_key = DerOctetString().decode(pk_info[2]).payload # We ignore attributes and (for v2 only) publickey return (algo_oid, private_key, algo_params)