Beispiel #1
0
    def test_wrap_invalid_key_to_wrap_length(self, backend):
        # Keys to wrap must be at least 16 bytes long
        with pytest.raises(ValueError):
            keywrap.aes_key_wrap(b"sixteen_byte_key", b"\x00" * 15, backend)

        # Keys to wrap must be a multiple of 8 bytes
        with pytest.raises(ValueError):
            keywrap.aes_key_wrap(b"sixteen_byte_key", b"\x00" * 23, backend)
Beispiel #2
0
    def test_wrap_invalid_key_to_wrap_length(self, backend):
        # Keys to wrap must be at least 16 bytes long
        with pytest.raises(ValueError):
            keywrap.aes_key_wrap(b"sixteen_byte_key", b"\x00" * 15, backend)

        # Keys to wrap must be a multiple of 8 bytes
        with pytest.raises(ValueError):
            keywrap.aes_key_wrap(b"sixteen_byte_key", b"\x00" * 23, backend)
Beispiel #3
0
 def generate_data_key(self):  # -> tuple[bytes, bytes]:
     data_key = os.urandom(32)
     encrypted_data_key = aes_key_wrap(
         wrapping_key=self._key_bytes,
         key_to_wrap=data_key,
     )
     return data_key, encrypted_data_key
Beispiel #4
0
    def wrap(self, key, bitsize, cek, headers):
        rk = self._get_key(key, 'encrypt')
        if not cek:
            cek = _randombits(bitsize)

        ek = aes_key_wrap(rk, cek, default_backend())

        return {'cek': cek, 'ek': ek}
Beispiel #5
0
    def aes_key_wrap(self, kek: bytes, key_to_wrap: bytes) -> bytes:
        """Wraps a key using a key-encrypting key (KEK).

        :param kek: The key-encrypting key
        :param key_to_wrap: Plain data
        :return: Wrapped key
        """
        return keywrap.aes_key_wrap(kek, key_to_wrap, default_backend())
def wrap_unwrap(key_1, key_2):  # Function to wrap and unwrap keys
    backend = default_backend()
    wrapped_key = keywrap.aes_key_wrap(
        key_2, key_1, backend=backend)  # Wrap key 1 with key 2
    unwrapped_key = keywrap.aes_key_unwrap(
        key_2, wrapped_key,
        backend=backend)  # Unwrapped the wrapped key with the key 2
    return wrapped_key, unwrapped_key
Beispiel #7
0
def wrap_key(security_control: SecurityControlField, wrapping_key: bytes,
             key_to_wrap: bytes):
    """
    Simple function to wrap a key for transfer
    """
    validate_key(security_control.security_suite, wrapping_key)
    validate_key(security_control.security_suite, key_to_wrap)
    wrapped_key = aes_key_wrap(wrapping_key, key_to_wrap)
    return wrapped_key
Beispiel #8
0
 def test_wrap(self, backend, subtests):
     params = _load_all_params(
         os.path.join("keywrap", "kwtestvectors"),
         ["KW_AE_128.txt", "KW_AE_192.txt", "KW_AE_256.txt"],
         load_nist_vectors,
     )
     for param in params:
         with subtests.test():
             wrapping_key = binascii.unhexlify(param["k"])
             key_to_wrap = binascii.unhexlify(param["p"])
             wrapped_key = keywrap.aes_key_wrap(wrapping_key, key_to_wrap,
                                                backend)
             assert param["c"] == binascii.hexlify(wrapped_key)
Beispiel #9
0
    def encrypt(cls, pk, *args):
        """
        For convenience, the synopsis of the encoding method is given below;
        however, this section, [NIST-SP800-56A], and [RFC3394] are the
        normative sources of the definition.

            Obtain the authenticated recipient public key R
            Generate an ephemeral key pair {v, V=vG}
            Compute the shared point S = vR;
            m = symm_alg_ID || session key || checksum || pkcs5_padding;
            curve_OID_len = (byte)len(curve_OID);
            Param = curve_OID_len || curve_OID || public_key_alg_ID || 03
            || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || "Anonymous
            Sender    " || recipient_fingerprint;
            Z_len = the key size for the KEK_alg_ID used with AESKeyWrap
            Compute Z = KDF( S, Z_len, Param );
            Compute C = AESKeyWrap( Z, m ) as per [RFC3394]
            VB = convert point V to the octet string
            Output (MPI(VB) || len(C) || C).

        The decryption is the inverse of the method given.  Note that the
        recipient obtains the shared secret by calculating
        """
        # *args should be:
        # - m
        #
        _m, = args

        # m may need to be PKCS5-padded
        padder = PKCS7(64).padder()
        m = padder.update(_m) + padder.finalize()

        km = pk.keymaterial

        ct = cls()

        # generate ephemeral key pair, then store it in ct
        v = ec.generate_private_key(km.oid.curve(), default_backend())
        ct.vX = MPI(v.public_key().public_numbers().x)
        ct.vY = MPI(v.public_key().public_numbers().y)

        # compute the shared point S
        s = v.exchange(ec.ECDH(), km.__pubkey__())

        # derive the wrapping key
        z = km.kdf.derive_key(s, km.oid, PubKeyAlgorithm.ECDH, pk.fingerprint)

        # compute C
        ct.c = aes_key_wrap(z, m, default_backend())

        return ct
Beispiel #10
0
    def encrypt(cls, pk, *args):
        """
        For convenience, the synopsis of the encoding method is given below;
        however, this section, [NIST-SP800-56A], and [RFC3394] are the
        normative sources of the definition.

            Obtain the authenticated recipient public key R
            Generate an ephemeral key pair {v, V=vG}
            Compute the shared point S = vR;
            m = symm_alg_ID || session key || checksum || pkcs5_padding;
            curve_OID_len = (byte)len(curve_OID);
            Param = curve_OID_len || curve_OID || public_key_alg_ID || 03
            || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || "Anonymous
            Sender    " || recipient_fingerprint;
            Z_len = the key size for the KEK_alg_ID used with AESKeyWrap
            Compute Z = KDF( S, Z_len, Param );
            Compute C = AESKeyWrap( Z, m ) as per [RFC3394]
            VB = convert point V to the octet string
            Output (MPI(VB) || len(C) || C).

        The decryption is the inverse of the method given.  Note that the
        recipient obtains the shared secret by calculating
        """
        # *args should be:
        # - m
        #
        _m, = args

        # m may need to be PKCS5-padded
        padder = PKCS7(64).padder()
        m = padder.update(_m) + padder.finalize()

        km = pk.keymaterial

        ct = cls()

        # generate ephemeral key pair, then store it in ct
        v = ec.generate_private_key(km.oid.curve(), default_backend())
        ct.vX = MPI(v.public_key().public_numbers().x)
        ct.vY = MPI(v.public_key().public_numbers().y)

        # compute the shared point S
        s = v.exchange(ec.ECDH(), km.__pubkey__())

        # derive the wrapping key
        z = km.kdf.derive_key(s, km.oid, PubKeyAlgorithm.ECDH, pk.fingerprint)

        # compute C
        ct.c = aes_key_wrap(z, m, default_backend())

        return ct
def wrap_key_aes(key_to_wrap, wrapping_key=None):
    """ Wraps a key using the AES key wrapping mode of operation as specified in
    https://www.ietf.org/rfc/rfc3394.txt

    :param key_to_wrap: the key to be wrapped in the process.
    :param wrapping_key: the key to be used to wrap the key  = KEK, If non is provided,
        it is generated randomly
    :return: the wrapped key as well as the used key as (wrapped_result, wrapping_key)
    """
    # checking if key needs to be generated
    if wrapping_key is None:
        wrapping_key = os.urandom(len(key_to_wrap))

    return keywrap.aes_key_wrap(wrapping_key, key_to_wrap,
                                default_backend()), wrapping_key
def test_keywrap(backend, wycheproof):
    wrapping_key = binascii.unhexlify(wycheproof.testcase["key"])
    key_to_wrap = binascii.unhexlify(wycheproof.testcase["msg"])
    expected = binascii.unhexlify(wycheproof.testcase["ct"])

    if (wycheproof.valid or
        (wycheproof.acceptable
         and wycheproof.testcase["comment"] != "invalid size of wrapped key")):
        result = keywrap.aes_key_wrap(wrapping_key, key_to_wrap, backend)
        assert result == expected

    if wycheproof.valid or wycheproof.acceptable:
        result = keywrap.aes_key_unwrap(wrapping_key, expected, backend)
        assert result == key_to_wrap
    else:
        with pytest.raises(keywrap.InvalidUnwrap):
            keywrap.aes_key_unwrap(wrapping_key, expected, backend)
Beispiel #13
0
    def encrypt(self, key, iv="", cek="", **kwargs):
        """
        Produces a JWE as defined in RFC7516 using symmetric keys

        :param key: Shared symmetric key
        :param iv: Initialization vector
        :param cek: Content master key
        :param kwargs: Extra keyword arguments, just ignore for now.
        :return:
        """
        _msg = as_bytes(self.msg)

        _args = self._dict
        try:
            _args["kid"] = kwargs["kid"]
        except KeyError:
            pass

        jwe = JWEnc(**_args)

        # If no iv and cek are given generate them
        iv = self._generate_iv(self["enc"], iv)
        cek = self._generate_key(self["enc"], cek)
        if isinstance(key, SYMKey):
            try:
                kek = key.key.encode("utf8")
            except AttributeError:
                kek = key.key
        elif isinstance(key, bytes):
            kek = key
        else:
            kek = intarr2str(key)

        # The iv for this function must be 64 bit
        # Which is certainly different from the one above
        jek = aes_key_wrap(kek, cek, default_backend())

        _enc = self["enc"]
        _auth_data = jwe.b64_encode_header()
        ctxt, tag, cek = self.enc_setup(_enc,
                                        _msg,
                                        auth_data=_auth_data,
                                        key=cek,
                                        iv=iv)
        return jwe.pack(parts=[jek, iv, ctxt, tag])
Beispiel #14
0
    def wrap(self, wrapping_key, key_to_wrap):
        # type: (bytes, bytes) -> bytes
        """Wrap key using AES keywrap.

        :param bytes wrapping_key: Loaded key with which to wrap
        :param bytes key_to_wrap: Raw key to wrap
        :returns: Wrapped key
        :rtype: bytes
        """
        if self.java_name not in ("AES", "AESWrap"):
            raise NotImplementedError('"wrap" is not supported by the "{}" cipher'.format(self.java_name))

        try:
            return keywrap.aes_key_wrap(wrapping_key=wrapping_key, key_to_wrap=key_to_wrap, backend=default_backend())
        except Exception:
            error_message = "Key wrap failed"
            _LOGGER.exception(error_message)
            raise WrappingError(error_message)
Beispiel #15
0
def test_keywrap(backend, wycheproof):
    wrapping_key = binascii.unhexlify(wycheproof.testcase["key"])
    key_to_wrap = binascii.unhexlify(wycheproof.testcase["msg"])
    expected = binascii.unhexlify(wycheproof.testcase["ct"])

    if (
        wycheproof.valid or (
            wycheproof.acceptable and
            wycheproof.testcase["comment"] != "invalid size of wrapped key"
        )
    ):
        result = keywrap.aes_key_wrap(wrapping_key, key_to_wrap, backend)
        assert result == expected

    if wycheproof.valid or wycheproof.acceptable:
        result = keywrap.aes_key_unwrap(wrapping_key, expected, backend)
        assert result == key_to_wrap
    else:
        with pytest.raises(keywrap.InvalidUnwrap):
            keywrap.aes_key_unwrap(wrapping_key, expected, backend)
 def wrap_key(self, key_data):
     key_data = six.ensure_binary(key_data)
     cipher_text = aes_key_wrap(self._key, key_data, default_backend())
     return cipher_text  # IV, cipher text, auth tag
 def wrap_key(self, key, algorithm='A256KW'):
     if algorithm == 'A256KW':
         return aes_key_wrap(self.kek, key, self.backend)
     else:
         raise ValueError(_ERROR_UNKNOWN_KEY_WRAP_ALGORITHM)
Beispiel #18
0
 def wrap_key(self, key, algorithm='A256KW'):
     if algorithm == 'A256KW':
         return aes_key_wrap(self.kek, key, self.backend)
     else:
         raise ValueError(_ERROR_UNKNOWN_KEY_WRAP_ALGORITHM)
 def wrap(self, cek, headers, key):
     op_key = key.get_op_key('wrapKey')
     self._check_key(op_key)
     ek = aes_key_wrap(op_key, cek, default_backend())
     return ek
Beispiel #20
0
 def wrap_key(cls, wrapping_key, key_to_wrap):
     return aes_key_wrap(wrapping_key, key_to_wrap, default_backend())
Beispiel #21
0
 def wrap(self, cek, headers, key):
     self._check_key(key)
     ek = aes_key_wrap(key, cek, default_backend())
     return ek
Beispiel #22
0
 def encrypt(self, data_key: bytes) -> bytes:
     encrypted_data_key = aes_key_wrap(
         wrapping_key=self._key_bytes,
         key_to_wrap=data_key,
     )
     return encrypted_data_key
def AESKeyWrap():
    print("\n\n\n===========================================")
    print("Welcome to Key Wrap (KW) Mode of Operation")
    print("===========================================")
    print(" ")

    print(
        "Key wrapping and un-wrapping requires 3 parameters in order to function correctly:\n"
    )
    print(
        "\n1) The key encrytion key or 'the wrapping key', which must be of 16, 24 or 32 bytes in value in order for AES to function."
    )
    print(
        "2) The key that is to be wrapped 'key to wrap', this is also of 16, 24 or 32 bytes in value."
    )
    print(
        "3) Finally, the wrapped key, this is the encrypted value of the key which is also used in the unwrapping process."
    )

    print(
        "\nFor simplicity's sake, we have already defined a value for the key encryption key to be b'1234567890123456'."
    )

    wrappingKey = b'1234567890123456'  # Must be 16,24,32 bytes
    userYN = input("Do you wish to change this value?(y/n):")
    if (userYN == "y"):
        wrappingKey = input(
            "Enter a new value for the wrapping key(MUST BE OF 16, 24 OR 32 BYTES):"
        )
        wrappingKey = wrappingKey.encode('utf-8')
        while (True):
            if ((len(wrappingKey) % 8 == 0) and len(wrappingKey) >= 16
                    and len(wrappingKey) <= 32):
                break
            print("The wrapping key must be a valid AES key length")
            wrappingKey = input(
                "Enter a new value for the wrapping key.(MUST BE OF 16, 24 OR 32 BYTES):"
            )
            wrappingKey = wrappingKey.encode('utf-8')

    print(
        "\nAnd again, for simplicity's sake we've defined the key that is to be wrapped to be b'wow-this-is-fun!'"
    )

    keyToWrap = b'wow-this-is-fun!'  # Must be 16,24,32 bytes

    userYN = input("Do you wish to change this value?(y/n):")
    if (userYN == "y"):
        keyToWrap = input(
            "Enter a new value for key to be wrapped.(MUST BE OF 16, 24 OR 32 BYTES):"
        )
        keyToWrap = keyToWrap.encode('utf-8')
        while (True):
            if ((len(keyToWrap) % 8 == 0) and len(keyToWrap) >= 16
                    and len(keyToWrap) <= 32):
                break
            print("The wrapping key must be a valid AES key length")
            keyToWrap = input(
                "Enter a new value for the wrapping key(MUST BE OF 16, 24 OR 32 BYTES):"
            )
            keyToWrap = keyToWrap.encode('utf-8')

    wrappedKey = keywrap.aes_key_wrap(wrappingKey,
                                      keyToWrap,
                                      backend=default_backend())

    print("\nThe encrypted value for the wrapped key is:", wrappedKey)
    input("Press Enter to see how we computed the wrapped key value...")

    print("\nWhat just happened?")
    print("-------------------------------------")
    print(
        "\nSo to go over how we got the encrypted value, lets take a moment to recall all the components involved."
    )
    print(
        "First off, when the program asked about setting a key encryption key, this key value is what's going to remain constant in both wrapping and un-wrapping the new key (Defaulted to b'1234567890123456' if no input)."
    )
    print(
        "The 'new key' is essentially the symmetric key we are wrapping so that we have a safe transfer of keys from the sender side to the receiver."
    )
    print(
        "This 'new key', we will dub it as the 'keyToWrap' value and this is the second value the program asked for your input. It was defaulted to b'wow-this-is-fun!' if there was no input."
    )
    print("\nSo now we have the following: ")
    print(
        "1) Key Encryption Key 'wrappinKey' = b'1234567890123456' or whatever you inputted."
    )
    print(
        "2) New Symmetric Key 'keyToWrap' = b'wow-this-is-fun!' or whatever you inputted."
    )
    print(
        "\nFinally, the program used the 'wrappingKey' to encrypt the 'keyToWrap' and that's how we got our 'WrappedKey' value."
    )
    print("To clarify, the wrapped key is:", wrappedKey)

    input(
        "Press Enter to see how we can return back to our 'keyToWrap' value..."
    )
    print("\nWhat about un-wrapping?")
    print("-------------------------------------")
    print(
        "\nNow if we wanted to get back our 'keyToWrap' which would be the symmetric key we wanted to exchange, it is actually quite simple given the parameters and values."
    )
    print(
        "This is most helpful when trying to decrypt the wrapped key as the receiver of the new symmetric key."
    )
    print(
        "\nJust like what we stated above when figuring out our wrapped key value, lets see what we have:"
    )
    print(
        "1) Key Encrytion key 'wrappingKey' = b'1234567890123456' or whatever it was you inputted. (REMEMBER THIS PARAMETER REMAINS CONSTANT FOR BOTH OPERATIONS)"
    )
    print("2) 'wrappedKey' = ", wrappedKey)
    print(
        "\nJust like before, using the two values and then decrypting using AES, we get back our 'keyToWrap' value"
    )
    c = keywrap.aes_key_unwrap(wrappingKey,
                               wrappedKey,
                               backend=default_backend())

    print(
        "After decrypting we end up with the symmetric key that was to be exchanged between sender and receiver:",
        c)
    def enc_setup(self, msg, key=None, auth_data=b'', **kwargs):
        """

        :param msg: Message to be encrypted
        :param auth_data:
        :param key: An EC key
        :param kwargs:
        :return:
        """
        encrypted_key = ""
        self.msg = msg
        self.auth_data = auth_data

        # Generate the input parameters
        try:
            apu = b64d(kwargs["apu"])
        except KeyError:
            apu = get_random_bytes(16)
        try:
            apv = b64d(kwargs["apv"])
        except KeyError:
            apv = get_random_bytes(16)

        # Handle Local Key and Ephemeral Public Key
        if not key or not isinstance(key, ECKey):
            raise ValueError(
                "EC Key Required for ECDH-ES JWE Encryption Setup")

        # epk is either an Elliptic curve key instance or a JWK description of
        # one. This key belongs to the entity on the other side.
        try:
            _epk = kwargs['epk']
        except KeyError:
            _epk = ec.generate_private_key(NIST2SEC[as_unicode(key.crv)],
                                           default_backend())
            epk = ECKey().load_key(_epk.public_key())
        else:
            if isinstance(_epk, ec.EllipticCurvePrivateKey):
                epk = ECKey().load_key(_epk)
            elif isinstance(_epk, ECKey):
                epk = _epk
                _epk = epk.private_key()
            else:
                raise ValueError("epk of a type I can't handle")

        params = {
            "apu": b64e(apu),
            "apv": b64e(apv),
            "epk": epk.serialize(False)
        }

        cek = iv = None
        if 'cek' in kwargs and kwargs['cek']:
            cek = kwargs['cek']
        if 'iv' in kwargs and kwargs['iv']:
            iv = kwargs['iv']

        iv = self._generate_iv(self.enc, iv=iv)

        if self.alg == "ECDH-ES":
            try:
                dk_len = KEY_LEN[self.enc]
            except KeyError:
                raise ValueError("Unknown key length for algorithm %s" %
                                 self.enc)

            cek = ecdh_derive_key(_epk, key.pub_key, apu, apv,
                                  str(self.enc).encode(), dk_len)
        elif self.alg in [
                "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW"
        ]:
            _pre, _post = self.alg.split("+")
            klen = int(_post[1:4])
            kek = ecdh_derive_key(_epk, key.pub_key, apu, apv,
                                  str(_post).encode(), klen)
            cek = self._generate_key(self.enc, cek=cek)
            encrypted_key = aes_key_wrap(kek, cek, default_backend())
        else:
            raise Exception("Unsupported algorithm %s" % self.alg)

        return cek, encrypted_key, iv, params, epk
Beispiel #25
0
 def key_wrap(cls, kek: 'SK', data: bytes):
     if cls.get_key_length() != len(kek.k):
         raise ValueError("Key has the wrong length")
     return aes_key_wrap(wrapping_key=kek.k, key_to_wrap=data, backend=default_backend())
Beispiel #26
0
 def wrap_key(self, key_to_wrap: bytes) -> bytes:
     try:
         return aes_key_wrap(self._key, key_to_wrap)
     except Exception as err:
         raise EncodeError("Failed to wrap key.") from err
Beispiel #27
0
 def test_wrap(self, backend, params):
     wrapping_key = binascii.unhexlify(params["k"])
     key_to_wrap = binascii.unhexlify(params["p"])
     wrapped_key = keywrap.aes_key_wrap(wrapping_key, key_to_wrap, backend)
     assert params["c"] == binascii.hexlify(wrapped_key)
Beispiel #28
0
 def wrap(self, enc_alg, headers, key):
     cek = enc_alg.generate_cek()
     op_key = key.get_op_key('wrapKey')
     self._check_key(op_key)
     ek = aes_key_wrap(op_key, cek, default_backend())
     return {'ek': ek, 'cek': cek}
 def wrap_data_key(self, data_key: bytes) -> bytes:
     return aes_key_wrap(
         wrapping_key=self._wrapping_key,
         key_to_wrap=data_key,
     )
Beispiel #30
0
 def wrap_key(cls, wrapping_key, key_to_wrap):
     return aes_key_wrap(wrapping_key, key_to_wrap, default_backend())
Beispiel #31
0
 def test_wrap(self, backend, params):
     wrapping_key = binascii.unhexlify(params["k"])
     key_to_wrap = binascii.unhexlify(params["p"])
     wrapped_key = keywrap.aes_key_wrap(wrapping_key, key_to_wrap, backend)
     assert params["c"] == binascii.hexlify(wrapped_key)
Beispiel #32
0
 def wrap_key(self, key, algorithm='A256KW'):
     if algorithm == 'A256KW':
         return aes_key_wrap(self.kek, key, self.backend)
     raise ValueError('Unknown key wrap algorithm.')
Beispiel #33
0
 def test_wrap_invalid_key_length(self, backend):
     # The wrapping key must be of length [16, 24, 32]
     with pytest.raises(ValueError):
         keywrap.aes_key_wrap(b"badkey", b"sixteen_byte_key", backend)
Beispiel #34
0
def key_wrap(wrapping_key, key_to_wrap):
    return aes_key_wrap(wrapping_key, key_to_wrap, _BACKEND)
Beispiel #35
0
 def wrap_cek(self, cek, key):
     op_key = key.get_op_key('wrapKey')
     self._check_key(op_key)
     ek = aes_key_wrap(op_key, cek, default_backend())
     return {'ek': ek, 'cek': cek}
Beispiel #36
0
 def test_wrap_invalid_key_length(self, backend):
     # The wrapping key must be of length [16, 24, 32]
     with pytest.raises(ValueError):
         keywrap.aes_key_wrap(b"badkey", b"sixteen_byte_key", backend)
Beispiel #37
0
 def transform(self, data):
     aes_key_wrap(self._key, data, default_backend())