Exemple #1
0
    def test_already_finalized(self, backend):
        ckdf = ConcatKDFHash(hashes.SHA256(), 16, None, backend)

        ckdf.derive(b"\x01" * 16)

        with pytest.raises(AlreadyFinalized):
            ckdf.derive(b"\x02" * 16)
Exemple #2
0
    def _derive(self, privkey, pubkey, alg, keydatalen, headers):
        # OtherInfo is defined in NIST SP 56A 5.8.1.2.1

        # AlgorithmID
        otherinfo = struct.pack('>I', len(alg))
        otherinfo += bytes(alg.encode('utf8'))

        # PartyUInfo
        apu = base64url_decode(headers['apu']) if 'apu' in headers else b''
        otherinfo += struct.pack('>I', len(apu))
        otherinfo += apu

        # PartyVInfo
        apv = base64url_decode(headers['apv']) if 'apv' in headers else b''
        otherinfo += struct.pack('>I', len(apv))
        otherinfo += apv

        # SuppPubInfo
        otherinfo += struct.pack('>I', keydatalen)

        # no SuppPrivInfo

        shared_key = privkey.exchange(ec.ECDH(), pubkey)
        ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                             length=keydatalen // 8,
                             otherinfo=otherinfo,
                             backend=self.backend)
        return ckdf.derive(shared_key)
Exemple #3
0
def kdfe(hashAlg, z, use, partyuinfo, partyvinfo, bits):
    halg = _get_digest(hashAlg)
    if halg is None:
        raise ValueError(f"unsupported digest algorithm: {hashAlg}")
    if bits % 8:
        raise ValueError(f"bad key length {bits}, not a multiple of 8")
    klen = int(bits / 8)
    otherinfo = use + partyuinfo + partyvinfo
    kdf = ConcatKDFHash(algorithm=halg(),
                        length=klen,
                        otherinfo=otherinfo,
                        backend=default_backend())
    return kdf.derive(z)
    def test_invalid_verify(self, backend):
        prk = binascii.unhexlify(
            b"52169af5c485dcc2321eb8d26d5efa21fb9b93c98e38412ee2484cf14f0d0d23"
        )

        oinfo = binascii.unhexlify(
            b"a1b2c3d4e53728157e634612c12d6d5223e204aeea4341565369647bd184bcd2"
            b"46f72971f292badaa2fe4124612cba")

        ckdf = ConcatKDFHash(hashes.SHA256(), 16, oinfo, backend)

        with pytest.raises(InvalidKey):
            ckdf.verify(prk, b"wrong key")
Exemple #5
0
    def test_invalid_verify(self, backend):
        prk = binascii.unhexlify(
            b"52169af5c485dcc2321eb8d26d5efa21fb9b93c98e38412ee2484cf14f0d0d23"
        )

        oinfo = binascii.unhexlify(
            b"a1b2c3d4e53728157e634612c12d6d5223e204aeea4341565369647bd184bcd2"
            b"46f72971f292badaa2fe4124612cba"
        )

        ckdf = ConcatKDFHash(hashes.SHA256(), 16, oinfo, backend)

        with pytest.raises(InvalidKey):
            ckdf.verify(prk, b"wrong key")
    def test_verify(self, backend):
        prk = binascii.unhexlify(
            b"52169af5c485dcc2321eb8d26d5efa21fb9b93c98e38412ee2484cf14f0d0d23"
        )

        okm = binascii.unhexlify(b"1c3bc9e7c4547c5191c0d478cccaed55")

        oinfo = binascii.unhexlify(
            b"a1b2c3d4e53728157e634612c12d6d5223e204aeea4341565369647bd184bcd2"
            b"46f72971f292badaa2fe4124612cba")

        ckdf = ConcatKDFHash(hashes.SHA256(), 16, oinfo, backend)

        ckdf.verify(prk, okm)
Exemple #7
0
    def derive_key(self, s, curve, pkalg, fingerprint):
        # wrapper around the Concatenation KDF method provided by cryptography
        # assemble the additional data as defined in RFC 6637:
        #  Param = curve_OID_len || curve_OID || public_key_alg_ID || 03 || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || "Anonymous
        data = bytearray()
        data += encoder.encode(curve.value)[1:]
        data.append(pkalg)
        data += b'\x03\x01'
        data.append(self.halg)
        data.append(self.encalg)
        data += b'Anonymous Sender    '
        data += binascii.unhexlify(fingerprint.replace(' ', ''))

        ckdf = ConcatKDFHash(algorithm=getattr(hashes, self.halg.name)(), length=self.encalg.key_size // 8, otherinfo=bytes(data), backend=default_backend())
        return ckdf.derive(s)
Exemple #8
0
    def derive_key(self, s, curve, pkalg, fingerprint):
        # wrapper around the Concatenation KDF method provided by cryptography
        # assemble the additional data as defined in RFC 6637:
        #  Param = curve_OID_len || curve_OID || public_key_alg_ID || 03 || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || "Anonymous
        data = bytearray()
        data += encoder.encode(curve.value)[1:]
        data.append(pkalg)
        data += b'\x03\x01'
        data.append(self.halg)
        data.append(self.encalg)
        data += b'Anonymous Sender    '
        data += binascii.unhexlify(fingerprint.replace(' ', ''))

        ckdf = ConcatKDFHash(algorithm=getattr(hashes, self.halg.name)(), length=self.encalg.key_size // 8, otherinfo=bytes(data), backend=default_backend())
        return ckdf.derive(s)
Exemple #9
0
    def test_verify(self, backend):
        prk = binascii.unhexlify(
            b"52169af5c485dcc2321eb8d26d5efa21fb9b93c98e38412ee2484cf14f0d0d23"
        )

        okm = binascii.unhexlify(b"1c3bc9e7c4547c5191c0d478cccaed55")

        oinfo = binascii.unhexlify(
            b"a1b2c3d4e53728157e634612c12d6d5223e204aeea4341565369647bd184bcd2"
            b"46f72971f292badaa2fe4124612cba"
        )

        ckdf = ConcatKDFHash(hashes.SHA256(), 16, oinfo, backend)

        assert ckdf.verify(prk, okm) is None
def test_invalid_backend():
    pretend_backend = object()

    with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
        ConcatKDFHash(hashes.SHA256(), 16, None, pretend_backend)
    with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
        ConcatKDFHMAC(hashes.SHA256(), 16, None, None, pretend_backend)
Exemple #11
0
    def __init__(self, credential_id, app_id):
        if not hasattr(serialization.Encoding, "X962"):
            raise unittest.SkipTest("Requires Cryptography >= 2.5")

        assert isinstance(credential_id, six.binary_type)
        assert isinstance(app_id, six.binary_type)

        # Note: do not use in production, no garantees is provided this is
        # cryptographically safe to use.
        priv_key_params = ConcatKDFHash(
            algorithm=hashes.SHA256(),
            length=32,
            otherinfo=credential_id + app_id,
            backend=default_backend(),
        ).derive(self._priv_key_bytes)
        self.app_id = app_id

        self.priv_key = ec.derive_private_key(bytes2int(priv_key_params),
                                              ec.SECP256R1(),
                                              default_backend())
        self.pub_key = self.priv_key.public_key()
        self.public_key_bytes = self.pub_key.public_bytes(
            serialization.Encoding.X962,
            serialization.PublicFormat.UncompressedPoint)

        self.credential_id = self.key_handle = credential_id
Exemple #12
0
 def ecdh_get_shared_secret(self, private_key, partner_public_key):
     shared_key = private_key.exchange(ec.ECDH(), partner_public_key)
     shared_key = ConcatKDFHash(
         algorithm=hashes.SHA256(),
         length=32,
         otherinfo=None,
         backend=default_backend()).derive(shared_key)
     return base64.urlsafe_b64encode(shared_key)
Exemple #13
0
    def _derive(self, privkey, pubkey, alg, bitsize, headers):
        # OtherInfo is defined in NIST SP 56A 5.8.1.2.1

        # AlgorithmID
        otherinfo = struct.pack('>I', len(alg))
        otherinfo += bytes(alg.encode('utf8'))

        # PartyUInfo
        apu = base64url_decode(headers['apu']) if 'apu' in headers else b''
        otherinfo += struct.pack('>I', len(apu))
        otherinfo += apu

        # PartyVInfo
        apv = base64url_decode(headers['apv']) if 'apv' in headers else b''
        otherinfo += struct.pack('>I', len(apv))
        otherinfo += apv

        # SuppPubInfo
        otherinfo += struct.pack('>I', bitsize)

        # no SuppPrivInfo

        # Shared Key generation
        if isinstance(privkey, ec.EllipticCurvePrivateKey):
            if isinstance(pubkey, ec.EllipticCurvePublicKey):
                aff_nums = pubkey.public_numbers()
                x, y = aff_nums.x, aff_nums.y
            else:
                x, y = pubkey

            P = vulnecc.AffinePoint(vulnecc.curveP256_vuln, x, y)
            s = privkey.private_numbers().private_value
            shared = s * P
            shared_key = int.to_bytes(shared.x, 32, "big")
        else:
            # X25519/X448
            shared_key = privkey.exchange(pubkey)

        ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                             length=_inbytes(bitsize),
                             otherinfo=otherinfo,
                             backend=self.backend)
        return ckdf.derive(shared_key)
Exemple #14
0
def decrypt_ecdh(ec_key, pub_pem, payload, other_info):
    """ Decrypt a payload using ECDH shared secret to derive AES256-GCM key
    Args:
        My private key
        Peer's public key
        Payload to decrypt
        Application specific context information
    Return:
        Decrypted payload
    """
    peer_public_key = serialization.load_pem_public_key(
        pub_pem, backend=default_backend())
    secret = compute_ecdh_secret(ec_key, peer_public_key)
    ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                         length=32,
                         otherinfo=other_info,
                         backend=default_backend())
    key = ckdf.derive(secret)
    plaintext = decrypt_aes_gcm(key, payload[:12], payload[12:])
    return plaintext
Exemple #15
0
def encrypt_ecdh(ec_key, pub_pem, payload, other_info):
    """ Encrypt a payload using ECDH shared secret to derive AES256-GCM key
    Args:
        My private key
        Peer's public key
        Payload to encrypt
        Application specific context information
    Return:
        Encrypted payload
    """
    peer_public_key = serialization.load_pem_public_key(
        pub_pem, backend=default_backend())
    secret = compute_ecdh_secret(ec_key, peer_public_key)
    ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                         length=32,
                         otherinfo=other_info,
                         backend=default_backend())
    key = ckdf.derive(secret)
    nonce = os.urandom(12)
    ciphertext = nonce + encrypt_aes_gcm(key, nonce, payload, other_info)
    return ciphertext
    def test_already_finalized(self, backend):
        ckdf = ConcatKDFHash(hashes.SHA256(), 16, None, backend)

        ckdf.derive(b"\x01" * 16)

        with pytest.raises(AlreadyFinalized):
            ckdf.derive(b"\x02" * 16)
Exemple #17
0
    def deliver(self, key, pubkey, headers, bit_size):
        # AlgorithmID
        if self.key_size is None:
            alg_id = _u32be_len_input(headers['enc'])
        else:
            alg_id = _u32be_len_input(headers['alg'])

        # PartyUInfo
        apu_info = _u32be_len_input(headers.get('apu'), True)

        # PartyVInfo
        apv_info = _u32be_len_input(headers.get('apv'), True)

        # SuppPubInfo
        pub_info = struct.pack('>I', bit_size)

        other_info = alg_id + apu_info + apv_info + pub_info
        shared_key = key.exchange_shared_key(pubkey)
        ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                             length=bit_size // 8,
                             otherinfo=other_info,
                             backend=default_backend())
        return ckdf.derive(shared_key)
Exemple #18
0
    def test_unicode_typeerror(self, backend):
        with pytest.raises(TypeError):
            ConcatKDFHash(
                hashes.SHA256(),
                16,
                otherinfo=u"foo",
                backend=backend
            )

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(
                hashes.SHA256(),
                16,
                otherinfo=None,
                backend=backend
            )

            ckdf.derive(u"foo")

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(
                hashes.SHA256(),
                16,
                otherinfo=None,
                backend=backend
            )

            ckdf.verify(u"foo", b"bar")

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(
                hashes.SHA256(),
                16,
                otherinfo=None,
                backend=backend
            )

            ckdf.verify(b"foo", u"bar")
    def test_unicode_typeerror(self, backend):
        with pytest.raises(TypeError):
            ConcatKDFHash(
                hashes.SHA256(),
                16,
                otherinfo="foo",  # type: ignore[arg-type]
                backend=backend,
            )

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(hashes.SHA256(),
                                 16,
                                 otherinfo=None,
                                 backend=backend)

            ckdf.derive("foo")  # type: ignore[arg-type]

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(hashes.SHA256(),
                                 16,
                                 otherinfo=None,
                                 backend=backend)

            ckdf.verify("foo", b"bar")  # type: ignore[arg-type]

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(hashes.SHA256(),
                                 16,
                                 otherinfo=None,
                                 backend=backend)

            ckdf.verify(b"foo", "bar")  # type: ignore[arg-type]
    def test_length_limit(self, backend):
        big_length = hashes.SHA256().digest_size * (2**32 - 1) + 1

        with pytest.raises(ValueError):
            ConcatKDFHash(hashes.SHA256(), big_length, None, backend)
    def test_unicode_typeerror(self, backend):
        with pytest.raises(TypeError):
            ConcatKDFHash(
                hashes.SHA256(), 16, otherinfo=u"foo", backend=backend
            )

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(
                hashes.SHA256(), 16, otherinfo=None, backend=backend
            )

            ckdf.derive(u"foo")

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(
                hashes.SHA256(), 16, otherinfo=None, backend=backend
            )

            ckdf.verify(u"foo", b"bar")

        with pytest.raises(TypeError):
            ckdf = ConcatKDFHash(
                hashes.SHA256(), 16, otherinfo=None, backend=backend
            )

            ckdf.verify(b"foo", u"bar")
Exemple #22
0
import base64
import os
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash
from cryptography.hazmat.backends import default_backend

# The sample code is extracted from the book Python Cryptography
# The book can be downloaded from https://leanpub.com/cryptop
# Online Crypto Playgroud https://8gwifi.org
# Author Anish Nath

backend = default_backend()
otherinfo = b"concatkdf-example"
ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                     length=32,
                     otherinfo=otherinfo,
                     backend=backend)

# CKDF Derive key

key = ckdf.derive(b"input key")
base64.b64encode(key)

# CKDF Verify Key
ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                     length=32,
                     otherinfo=otherinfo,
                     backend=backend)

ckdf.verify(b"input key", key)
Exemple #23
0
 def compute_derived_key(self, shared_key, fixed_info, bit_size):
     ckdf = ConcatKDFHash(algorithm=hashes.SHA256(),
                          length=bit_size // 8,
                          otherinfo=fixed_info,
                          backend=default_backend())
     return ckdf.derive(shared_key)