def generate_private_key(self): parameters = self.session.create_domain_parameters( KeyType.EC, {Attribute.EC_PARAMS: encode_named_curve_parameters('secp256r1')}, local=True) public_template = { Attribute.KEY_TYPE: KeyType.EC, Attribute.CLASS: ObjectClass.PUBLIC_KEY, Attribute.TOKEN: True, Attribute.VERIFY: True, } private_template = { Attribute.KEY_TYPE: KeyType.EC, Attribute.CLASS: ObjectClass.PRIVATE_KEY, Attribute.TOKEN: True, Attribute.PRIVATE: True, Attribute.SIGN: True, Attribute.EXTRACTABLE: False, Attribute.SENSITIVE: True } public_key, private_key = parameters.generate_keypair( store=True, public_template=public_template, private_template=private_template) ecpt = bytes(OctetString.load(public_key[Attribute.EC_POINT])) hash = hashlib.sha256(ecpt) ski = hash.digest() hexski = hash.hexdigest() public_key[Attribute.ID] = ski public_key[Attribute.LABEL] = hexski private_key[Attribute.ID] = ski private_key[Attribute.LABEL] = hexski return PKCS11KeyPair(public_key, private_key)
def test_ecdh(self): # A key we generated earlier self.session.create_domain_parameters(KeyType.EC, { Attribute.EC_PARAMS: encode_named_curve_parameters('secp256r1'), }, local=True)\ .generate_keypair() # Retrieve our keypair, with our public key encoded for interchange alice_priv = self.session.get_key(key_type=KeyType.EC, object_class=ObjectClass.PRIVATE_KEY) alice_pub = self.session.get_key(key_type=KeyType.EC, object_class=ObjectClass.PUBLIC_KEY) alice_pub = encode_ec_public_key(alice_pub) from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.serialization import \ Encoding, PublicFormat, load_der_public_key # Bob generates a keypair, with their public key encoded for # interchange bob_priv = ec.generate_private_key(ec.SECP256R1, default_backend()) bob_pub = bob_priv.public_key().public_bytes( Encoding.DER, PublicFormat.SubjectPublicKeyInfo, ) # Bob converts Alice's key to internal format and generates their # shared key bob_shared_key = bob_priv.exchange( ec.ECDH(), load_der_public_key(alice_pub, default_backend()), ) key = alice_priv.derive_key( KeyType.GENERIC_SECRET, 256, mechanism_param=( KDF.NULL, None, # N.B. it seems like SoftHSMv2 requires an EC_POINT to be # DER-encoded, which is not what the spec says decode_ec_public_key(bob_pub, encode_ec_point=Is.softhsm2) [Attribute.EC_POINT], ), template={ Attribute.SENSITIVE: False, Attribute.EXTRACTABLE: True, }, ) alice_shared_key = key[Attribute.VALUE] # We should have the same shared key self.assertEqual(bob_shared_key, alice_shared_key)
def test_sign_ecdsa(self): parameters = self.session.create_domain_parameters( KeyType.EC, {Attribute.EC_PARAMS: encode_named_curve_parameters('secp256r1')}, local=True) pub, priv = parameters.generate_keypair() mechanism = Mechanism.ECDSA data = b'HI BOB!' ecdsa = priv.sign(data, mechanism=mechanism) self.assertTrue(pub.verify(data, ecdsa, mechanism=mechanism))
def test_sign_eddsa(self): parameters = self.session.create_domain_parameters( KeyType.EC, { # use "Ed25519" once https://github.com/wbond/asn1crypto/pull/134 # is merged Attribute.EC_PARAMS: encode_named_curve_parameters('1.3.101.112') }, local=True) pub, priv = parameters.generate_keypair() mechanism = Mechanism.EDDSA data = b'HI BOB!' eddsa = priv.sign(data, mechanism=mechanism) self.assertTrue(pub.verify(data, eddsa, mechanism=mechanism))
def generate(self): if not self._address: # if we got here, we didn't succeed in loading during _load_key, so we can just generate a new one without # being afraid of multiple objects # todo: handle multiple objects a little more gracefully? We'll see how other HSMs handle this shit... with self.token.open(rw=True, user_pin=self.user_pin) as session: ecparams = session.create_domain_parameters( pkcs11.KeyType.EC, { pkcs11.Attribute.EC_PARAMS: ec.encode_named_curve_parameters('secp256k1'), }, local=True) pub, _ = ecparams.generate_keypair(label=self.label, store=True) self._address = self._address_from_pub(pub) self.public_key = encode_ec_public_key(pub)[24:] return self.label
def generate_ec(self, curve, label, object_id='', store=True): """ Generates an EC key. @param curve: The name of the desired elliptic curve. @param label: The label of the key. @param object_id: The unique identifier of the key as a string. @raise ValueError: Raised when an invalid curve is passed. @return: The key. """ if curve not in Session.__ec_curves: raise ValueError('Invalid EC curve.') parameters = self.p11.create_domain_parameters( KeyType.EC, {Attribute.EC_PARAMS: encode_named_curve_parameters(curve)}, local=True) return parameters.generate_keypair(label=label, id=bytes(object_id, 'utf-8'), store=store)
def test_ecdsa(self): # A key we generated earlier self.session.create_domain_parameters(KeyType.EC, { Attribute.EC_PARAMS: encode_named_curve_parameters('secp256r1'), }, local=True)\ .generate_keypair() priv = self.session.get_key(key_type=KeyType.EC, object_class=ObjectClass.PRIVATE_KEY) signature = priv.sign(b'Data to sign', mechanism=Mechanism.ECDSA_SHA1) # Encode as ASN.1 for OpenSSL signature = encode_ecdsa_signature(signature) from oscrypto.asymmetric import load_public_key, ecdsa_verify pub = self.session.get_key(key_type=KeyType.EC, object_class=ObjectClass.PUBLIC_KEY) pub = load_public_key(encode_ec_public_key(pub)) ecdsa_verify(pub, signature, b'Data to sign', 'sha1')
tokens = lib.get_tokens() token = next(tokens) # get any token try: # connect to hsm via pkcs11 token and pin with token.open(user_pin=os.environ['USER_PIN'], rw=True) as session: # ec curve params ecparams = session.create_domain_parameters( KeyType.EC, { # hardcoded curve name for secp256k1 taken from https://www.flexiprovider.de/CurveOIDs.html # asn1crypto python library currently missing the secp256k1 named curve parameters Attribute.EC_PARAMS: ec.encode_named_curve_parameters('1.3.132.0.10'), }, local=True) try: pub, priv = ecparams.generate_keypair(store=True, label="{}".format( os.environ['KEY_LABEL'])) except Exception as e: print("key already exists") for obj in session.get_objects({ Attribute.KEY_TYPE: KeyType.EC, Attribute.LABEL: "{}".format(os.environ['KEY_LABEL']) }):
from pkcs11.util.ec import encode_named_curve_parameters if __name__ == "__main__": lib = pkcs11.lib("/usr/lib/softhsm/libsofthsm2.so") token = lib.get_token(token_label="token") with token.open(rw=True, user_pin="1234") as session: session.generate_keypair(pkcs11.KeyType.RSA, 2048, label="small_rsa_key", store=True) session.generate_keypair(pkcs11.KeyType.RSA, 4096, label="big_rsa_key", store=True) session.generate_keypair(pkcs11.KeyType.DSA, 2048, label="dsa_key", store=True) ecparams = session.create_domain_parameters( pkcs11.KeyType.EC, { pkcs11.Attribute.EC_PARAMS: encode_named_curve_parameters("secp256r1") }, local=True, ) ecparams.generate_keypair(store=True, label="ec_key")