blob: 1d7de6c472eedc3eb03f40efbe039855d7be3f4e [file] [log] [blame]
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
import binascii
import os
import pytest
from cryptography.exceptions import AlreadyFinalized, InvalidKey, _Reasons
from cryptography.hazmat.backends.interfaces import HMACBackend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand
from ...utils import (
load_nist_vectors,
load_vectors_from_file,
raises_unsupported_algorithm,
)
@pytest.mark.requires_backend_interface(interface=HMACBackend)
class TestHKDF(object):
def test_length_limit(self, backend):
big_length = 255 * hashes.SHA256().digest_size + 1
with pytest.raises(ValueError):
HKDF(
hashes.SHA256(),
big_length,
salt=None,
info=None,
backend=backend,
)
def test_already_finalized(self, backend):
hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
hkdf.derive(b"\x01" * 16)
with pytest.raises(AlreadyFinalized):
hkdf.derive(b"\x02" * 16)
hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
hkdf.verify(b"\x01" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
with pytest.raises(AlreadyFinalized):
hkdf.verify(b"\x02" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
def test_verify(self, backend):
hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
hkdf.verify(b"\x01" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
def test_verify_invalid(self, backend):
hkdf = HKDF(hashes.SHA256(), 16, salt=None, info=None, backend=backend)
with pytest.raises(InvalidKey):
hkdf.verify(b"\x02" * 16, b"gJ\xfb{\xb1Oi\xc5sMC\xb7\xe4@\xf7u")
def test_unicode_typeerror(self, backend):
with pytest.raises(TypeError):
HKDF(hashes.SHA256(), 16, salt=u"foo", info=None, backend=backend)
with pytest.raises(TypeError):
HKDF(hashes.SHA256(), 16, salt=None, info=u"foo", backend=backend)
with pytest.raises(TypeError):
hkdf = HKDF(
hashes.SHA256(), 16, salt=None, info=None, backend=backend
)
hkdf.derive(u"foo")
with pytest.raises(TypeError):
hkdf = HKDF(
hashes.SHA256(), 16, salt=None, info=None, backend=backend
)
hkdf.verify(u"foo", b"bar")
with pytest.raises(TypeError):
hkdf = HKDF(
hashes.SHA256(), 16, salt=None, info=None, backend=backend
)
hkdf.verify(b"foo", u"bar")
def test_derive_short_output(self, backend):
hkdf = HKDF(hashes.SHA256(), 4, salt=None, info=None, backend=backend)
assert hkdf.derive(b"\x01" * 16) == b"gJ\xfb{"
def test_derive_long_output(self, backend):
vector = load_vectors_from_file(
os.path.join("KDF", "hkdf-generated.txt"), load_nist_vectors
)[0]
hkdf = HKDF(
hashes.SHA256(),
int(vector["l"]),
salt=vector["salt"],
info=vector["info"],
backend=backend,
)
ikm = binascii.unhexlify(vector["ikm"])
assert hkdf.derive(ikm) == binascii.unhexlify(vector["okm"])
def test_buffer_protocol(self, backend):
vector = load_vectors_from_file(
os.path.join("KDF", "hkdf-generated.txt"), load_nist_vectors
)[0]
hkdf = HKDF(
hashes.SHA256(),
int(vector["l"]),
salt=vector["salt"],
info=vector["info"],
backend=backend,
)
ikm = bytearray(binascii.unhexlify(vector["ikm"]))
assert hkdf.derive(ikm) == binascii.unhexlify(vector["okm"])
@pytest.mark.requires_backend_interface(interface=HMACBackend)
class TestHKDFExpand(object):
def test_derive(self, backend):
prk = binascii.unhexlify(
b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
)
okm = (
b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
b"5bf34007208d5b887185865"
)
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
assert binascii.hexlify(hkdf.derive(prk)) == okm
def test_buffer_protocol(self, backend):
prk = bytearray(
binascii.unhexlify(
b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2"
b"b3e5"
)
)
okm = (
b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
b"5bf34007208d5b887185865"
)
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
assert binascii.hexlify(hkdf.derive(prk)) == okm
def test_verify(self, backend):
prk = binascii.unhexlify(
b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
)
okm = (
b"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c"
b"5bf34007208d5b887185865"
)
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
assert hkdf.verify(prk, binascii.unhexlify(okm)) is None
def test_invalid_verify(self, backend):
prk = binascii.unhexlify(
b"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
)
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
with pytest.raises(InvalidKey):
hkdf.verify(prk, b"wrong key")
def test_already_finalized(self, backend):
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
hkdf.derive(b"first")
with pytest.raises(AlreadyFinalized):
hkdf.derive(b"second")
def test_unicode_error(self, backend):
info = binascii.unhexlify(b"f0f1f2f3f4f5f6f7f8f9")
hkdf = HKDFExpand(hashes.SHA256(), 42, info, backend)
with pytest.raises(TypeError):
hkdf.derive(u"first")
def test_invalid_backend():
pretend_backend = object()
with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
HKDF(hashes.SHA256(), 16, None, None, pretend_backend)
with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
HKDFExpand(hashes.SHA256(), 16, None, pretend_backend)