Ejemplo n.º 1
0
 def generate_csr(self, private_key, subject_name, extensions=None):
     common_name = subject_name.get_attributes_for_oid(
         NameOID.COMMON_NAME)[0].value
     info = CertificationRequestInfo({
         'version':
         0,
         'subject':
         Name.build({
             'country_name': 'US',
             'state_or_province_name': 'North Carolina',
             'organization_name': 'Hyperledger',
             'organizational_unit_name': 'Fabric',
             'common_name': common_name
         }),
         'subject_pk_info':
         PublicKeyInfo.load(encode_ec_public_key(private_key.public_key)),
         'attributes':
         CRIAttributes([])
     })
     hash = hashlib.sha256(info.dump()).digest()
     signature = private_key.private_key.sign(hash,
                                              mechanism=Mechanism.ECDSA)
     csr = CertificationRequest({
         'certification_request_info':
         info,
         'signature_algorithm': {
             'algorithm': 'sha256_ecdsa',
             'parameters': None
         },
         'signature':
         encode_ecdsa_signature(signature)
     })
     der = csr.dump()
     result = x509.load_der_x509_csr(der, default_backend())
     return result
Ejemplo n.º 2
0
    def _address_from_pub(pubkey: bytes):
        public_der = encode_ec_public_key(pubkey)

        # public key in der encoding is 32 bytes of header stuff, then 65 bytes of the uncompressed public key
        # so we start from the 33rd byte
        pub_uncompressed = public_der[24:].hex()
        return pubkey_to_addr(pub_uncompressed)
Ejemplo n.º 3
0
    def pkcs11_to_crypto_key(self,
                             pkcs11_public_key: pkcs11.KeyType) -> PublicKey:
        """
        Convert a `pkcs11` public key to a `cryptography` public key.

        :param pkcs11.KeyType pkcs11_public_key: A `pkcs11` format public key.
        :return: A `cryptography` format public key.
        :rtype: :class:`PublicKey`
        """
        if self.pkcs11_key_type == pkcs11.KeyType.RSA:
            der_public_key = encode_rsa_public_key(pkcs11_public_key)
        elif self.pkcs11_key_type == pkcs11.KeyType.DSA:
            y = int.from_bytes(pkcs11_public_key[pkcs11.Attribute.VALUE],
                               byteorder="big")
            g = int.from_bytes(pkcs11_public_key[pkcs11.Attribute.BASE],
                               byteorder="big")
            p = int.from_bytes(pkcs11_public_key[pkcs11.Attribute.PRIME],
                               byteorder="big")
            q = int.from_bytes(pkcs11_public_key[pkcs11.Attribute.SUBPRIME],
                               byteorder="big")

            der_public_key = DSA.construct(
                (y, g, p, q)).export_key(format="DER")
        elif self.pkcs11_key_type == pkcs11.KeyType.EC:
            der_public_key = encode_ec_public_key(pkcs11_public_key)
        else:
            raise TypeError(f"Key type for {pkcs11_public_key} not supported")

        return load_der_public_key(der_public_key)
Ejemplo n.º 4
0
 def _load_key(self):
     with self.token.open(user_pin=self.user_pin) as session:
         keys = session.get_objects(
             {pkcs11.Attribute.CLASS: pkcs11.ObjectClass.PUBLIC_KEY})
         for key in keys:
             if key.label == self.label:
                 self.public_key = encode_ec_public_key(key)[24:]
                 self._address = self._address_from_pub(key)
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    def __init__(self, key_name):
        # load pkcs11 lib
        self.lib = pkcs11.lib(os.environ['PKCS11_LIB'])
        self.user_pin = os.environ['USER_PIN']
        self.token = next(self.lib.get_tokens())  # get any token
        self.key_name = key_name

        # initiate session via pkcs11
        start = time.time()
        self.session = self.token.open(user_pin=self.user_pin)
        print("time (connect) {}s".format(time.time() - start))
        start = time.time()

        # get key returns >1 key for some reason
        # key = session.get_key(object_class=ObjectClass.PRIVATE_KEY,
        #                         key_type=KeyType.EC,
        #                         label=self.key_name)

        # get key by iterating through all session objects instead
        iterator = self.session.get_objects({
            Attribute.KEY_TYPE: KeyType.EC,
            Attribute.CLASS: ObjectClass.PRIVATE_KEY,
            Attribute.LABEL: self.key_name
        })
        self.key = next(iterator)
        print(self.key)
        print("time (get private key) {}s".format(time.time() - start))
        start = time.time()
        _ = next(iterator)  # test get_objects() still returns > 1
        iterator._finalize()

        iterator = self.session.get_objects({
            Attribute.KEY_TYPE: KeyType.EC,
            Attribute.CLASS: ObjectClass.PUBLIC_KEY,
            Attribute.LABEL: self.key_name
        })
        pub = next(iterator)
        print(pub)
        pubder = ec.encode_ec_public_key(pub)
        self.pubcrypto = serialization.load_der_public_key(
            pubder, default_backend())
        print("time (get public key) {}s".format(time.time() - start))
        _ = next(iterator)  # test get_objects() still returns > 1
        iterator._finalize()
Ejemplo n.º 8
0
    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')
Ejemplo n.º 9
0
    def test_import_key_params(self):
        der = base64.b64decode("""
        MIICXDCCAc8GByqGSM49AgEwggHCAgEBME0GByqGSM49AQECQgH/////////////
        ////////////////////////////////////////////////////////////////
        /////////zCBngRCAf//////////////////////////////////////////////
        ///////////////////////////////////////8BEFRlT65YY4cmh+SmiGgtoVA
        7qLacluZsxXzuLSJkY7xCeFWGTlR7H6TexZSwL07sb8HNXPfiD0sNPHvRR/Ua1A/
        AAMVANCeiAApHLhTlsxnFzkyhKqg2mS6BIGFBADGhY4GtwQE6c2ePstmI5W0Qpxk
        gTkFP7Uh+CivYGtNPbqhS1537+dZKP4dwSei/6jeM0izwYVqQpv5fn4xwuW9ZgEY
        OSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQmQMVQuQE/rQdh
        NTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////////////////
        ////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEBA4GGAAQBMLgt
        gTFBGr0f7YrWwZsCPpLxaUQvUKvz2C6ghiFmxc2EzBgxDY+ywnmG4T++EVZhJHTP
        eIOnVRcHXXivkRe+YMQBbH/fZyqfCe41vIl39bwhqli839AAj/WoxXZuilpKaXBp
        vGbx2380UIhrec1jFjItOOg/Xp9dOecjQZK7Z0wVq1U=
        """)
        key = self.session.create_object(decode_ec_public_key(der))
        self.assertIsInstance(key, pkcs11.PublicKey)

        # We should get back to identity
        self.assertEqual(encode_ec_public_key(key), der)
Ejemplo n.º 10
0
    def test_import_key_named_curve(self):
        der = base64.b64decode("""
        MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEa6Q5Hs+j71J1lc+VziafH+uL6603
        R8gTAphQD0iLG9Q9RgAvDQdFFpzkvXI+mEGVNRMmT/BA1OtficHcAXTdXA==
        """)
        key = self.session.create_object(decode_ec_public_key(der))
        self.assertIsInstance(key, pkcs11.PublicKey)

        # Something signed with OpenSSL
        signature = base64.b64decode("""
        MEYCIQD1nDlli+uLuGX3eobKJe7PsRYkYJ4F15bjqbbB+MHewwIhAPGFRwyuFOvH
        zuj+sxXwk1CsDWN7AXbmHufOlOarXpiq
        """)
        signature = decode_ecdsa_signature(signature)

        self.assertTrue(
            key.verify(b'Data to sign',
                       signature,
                       mechanism=Mechanism.ECDSA_SHA1))

        # We should get back to identity
        self.assertEqual(encode_ec_public_key(key), der)
Ejemplo n.º 11
0
            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'])
            }):
                if obj.object_class == ObjectClass.PUBLIC_KEY:
                    pub = obj

        print("{}".format(pub))
        pubder = ec.encode_ec_public_key(pub)
        pubcrypto = serialization.load_der_public_key(pubder,
                                                      default_backend())
        print(
            pubcrypto.public_bytes(
                serialization.Encoding.X962,
                serialization.PublicFormat.CompressedPoint).hex())

        # # do uncompressed -> compressed manually
        # # similar result as above
        # point = pub[Attribute.EC_POINT]
        # if point[1] == 0x41 and point[2] == 0x04:
        #     x = int(point[3:35].hex(), 16)
        #     y = int(point[35:].hex(), 16)
        #     multisig += '21'
        #     multisig += ('%02x' % (2+(y&1))) + ('%064x' % x)