def deserialize(self): try: self.x = base64_to_long(self.x) self.y = base64_to_long(self.y) except TypeError: raise DeSerializationNotPossible() self.curve = NISTEllipticCurve.by_name(self.crv) if self.d: self.d = base64_to_long(self.d) self.deser = True self.ser = False
def enc_setup(self, msg, auth_data, key=None, **kwargs): encrypted_key = "" # Generate the input parameters try: apu = b64d(kwargs["apu"]) except KeyError: apu = b64d(Random.get_random_bytes(16)) try: apv = b64d(kwargs["apv"]) except KeyError: apv = b64d(Random.get_random_bytes(16)) # Generate an ephemeral key pair curve = NISTEllipticCurve.by_name(key.crv) if "epk" in kwargs: epk = ECKey(key=kwargs["epk"], private=False) eprivk = ECKey(kwargs["epk"], private=True) else: (eprivk, epk) = curve.key_pair() # Derive the KEK and encrypt params = { "apu": b64e(apu), "apv": b64e(apv), #"epk": exportKey(epk, "EC", curve) } cek, iv = self._generate_key_and_iv(self.enc) if self.alg == "ECDH-ES": try: dk_len = KEYLEN[self.enc] except KeyError: raise Exception("Unknown key length for algorithm %s" % self.enc) cek = ecdh_derive_key(curve, eprivk, key, apu, apv, self.enc, 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(curve, eprivk, key, apu, apv, _post, klen) encrypted_key = aes_wrap_key(kek, cek) else: raise Exception("Unsupported algorithm %s" % self.alg) return cek, encrypted_key, iv, params
def ec_init(spec): """ :param spec: Key specifics of the form {"type": "EC", "crv": "P-256", "use": ["sig"]}, :return: A KeyBundle instance """ typ = spec["type"].upper() _key = NISTEllipticCurve.by_name(spec["crv"]) kb = KeyBundle(keytype=typ, keyusage=spec["use"]) for use in spec["use"]: priv, pub = _key.key_pair() ec = ECKey(x=pub[0], y=pub[1], d=priv, crv=spec["crv"]) ec.serialize() ec.use = use kb.append(ec) return kb
def enc_setup(self, msg, auth_data, key=None, **kwargs): encrypted_key = "" # Generate the input parameters try: apu = b64d(kwargs["apu"]) except KeyError: apu = b64d(Random.get_random_bytes(16)) try: apv = b64d(kwargs["apv"]) except KeyError: apv = b64d(Random.get_random_bytes(16)) # Generate an ephemeral key pair curve = NISTEllipticCurve.by_name(key.crv) if "epk" in kwargs: epk = ECKey(key=kwargs["epk"], private=False) eprivk = ECKey(kwargs["epk"], private=True) else: (eprivk, epk) = curve.key_pair() # Derive the KEK and encrypt params = { "apu": b64e(apu), "apv": b64e(apv), #"epk": exportKey(epk, "EC", curve) } cek, iv = self._generate_key_and_iv(self.enc) if self.alg == "ECDH-ES": try: dk_len = KEYLEN[self.enc] except KeyError: raise Exception( "Unknown key length for algorithm %s" % self.enc) cek = ecdh_derive_key(curve, eprivk, key, apu, apv, self.enc, 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(curve, eprivk, key, apu, apv, _post, klen) encrypted_key = aes_wrap_key(kek, cek) else: raise Exception("Unsupported algorithm %s" % self.alg) return cek, encrypted_key, iv, params
def deserialize(self): try: if isinstance(self.x, basestring): self.x = base64_to_long(self.x) if isinstance(self.y, basestring): self.y = base64_to_long(self.y) except TypeError: raise DeSerializationNotPossible() except ValueError as err: raise DeSerializationNotPossible("%s" % err) self.curve = NISTEllipticCurve.by_name(self.crv) if self.d: try: if isinstance(self.d, basestring): self.d = base64_to_long(self.d) except ValueError as err: raise DeSerializationNotPossible(str(err))
def deserialize(self): """ Starting with information gathered from the on-the-wire representation of an elliptic curve key initiate an Elliptic Curve. """ try: if isinstance(self.x, basestring): self.x = base64_to_long(self.x) if isinstance(self.y, basestring): self.y = base64_to_long(self.y) except TypeError: raise DeSerializationNotPossible() except ValueError as err: raise DeSerializationNotPossible("%s" % err) self.curve = NISTEllipticCurve.by_name(self.crv) if self.d: try: if isinstance(self.d, basestring): self.d = base64_to_long(self.d) except ValueError as err: raise DeSerializationNotPossible(str(err))
def deserialize(self): self.x = base64_to_long(self.x) self.y = base64_to_long(self.y) self.curve = NISTEllipticCurve.by_name(self.crv) if self.d: self.d = base64_to_long(self.d)
def decryptKey(alg, enc, jwk, encryptedKey, header={}): """ Decrypt a JWE encrypted key. @type alg: string @param alg: The JWE "alg" value specifying the key management algorithm @type enc: string @param enc: The JWE "enc" value specifying the encryption algorithm @type jwk: dict @param jwk: The key to be used, as an unserialized JWK object @type encryptedKey: bytes @param encryptedKey: The key to decrypt @type header: dict @param header: A header object containing additional parameters @rtype: bytes @return: The decrypted key """ key = importKey(jwk, private=True) if alg == "RSA1_5": sentinel = "fnord" cipher = PKCS1_v1_5.new(key) CEK = cipher.decrypt(encryptedKey, sentinel) if CEK == sentinel: raise Exception("Unable to unwrap key") return CEK elif alg == "RSA-OAEP": cipher = PKCS1_OAEP.new(key) CEK = cipher.decrypt(encryptedKey) return CEK elif alg in ["A128KW", "A192KW", "A256KW"]: return polyfills.aes_key_unwrap(key, encryptedKey) elif alg == "dir": if encryptedKey and len(encryptedKey) > 0: raise Exception("Direct encryption with non-empty encrypted key") return key elif alg in ["ECDH-ES", "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW"]: # Pull the input parameters epk = importKey(getOrRaise(header, "epk")) apu = b64dec(getOrRaise(header, "apu")) apv = b64dec(getOrRaise(header, "apv")) # Select the curve curve = NISTEllipticCurve.byName(getOrRaise(header["epk"], "crv")) # Derive the KEK and decrypt if alg == "ECDH-ES": dkLen = keyLength(enc) return polyfills.ECDH_deriveKey(curve, key, epk, apu, apv, enc, dkLen) elif alg == "ECDH-ES+A128KW": kek = polyfills.ECDH_deriveKey(curve, key, epk, apu, apv, "A128KW", 128) return polyfills.aes_key_unwrap(kek, encryptedKey) elif alg == "ECDH-ES+A192KW": kek = polyfills.ECDH_deriveKey(curve, key, epk, apu, apv, "A192KW", 192) return polyfills.aes_key_unwrap(kek, encryptedKey) elif alg == "ECDH-ES+A256KW": kek = polyfills.ECDH_deriveKey(curve, key, epk, apu, apv, "A256KW", 256) return polyfills.aes_key_unwrap(kek, encryptedKey) elif alg in ["A128GCMKW", "A192GCMKW", "A256GCMKW"]: iv = b64dec(getOrRaise(header, "iv")) tag = b64dec(getOrRaise(header, "tag")) gcm = AES_GCM(bytes_to_long(key)) return gcm.decrypt(bytes_to_long(iv), encryptedKey, bytes_to_long(tag), '') elif alg == "PBES2-HS256+A128KW": return polyfills.PBKDF_key_unwrap(key, encryptedKey, SHA256, 16, header) elif alg == "PBES2-HS384+A192KW": return polyfills.PBKDF_key_unwrap(key, encryptedKey, SHA384, 24, header) elif alg == "PBES2-HS512+A256KW": return polyfills.PBKDF_key_unwrap(key, encryptedKey, SHA512, 32, header) else: raise Exception("Unsupported key management algorithm " + alg)
def generateSenderParams(alg, enc, jwk, header={}, inCEK=None): """ Generate parameters for the sender of a JWE. This is essentially an encryptKey method, except (1) in some cases, the key is specified directly or derived ("dir", "ECDH"), and (2) other parameters besides the encrypted key are generated (e.g., the IV). This method returns several things: - A random CEK (can be overridden with the inCEK parameter) - The encrypted CEK - A random IV - A dictionary of parameters generated within this function The idea is that the parameters generated within this function (e.g., "epk", "p2s") should be added back to the JWE header @type alg: string @param alg: The JWE "alg" value specifying the key management algorithm @type enc: string @param enc: The JWE "enc" value specifying the encryption algorithm @type jwk: dict @param jwk: The key to be used, as an unserialized JWK object @type header: dict @param header: A header object with additional parameters @type inCEK: bytes @param inCEK: A fixed CEK (overrides random CEK generation) @rtype: tuple @return: (CEK, encryptedKey, IV, params), the first three as bytes, params as dict. """ # Generate a random key/iv for enc (CEK, IV) = generateKeyIV(enc) if inCEK: CEK = inCEK encryptedKey = "" params = {} key = importKey(jwk, private=False) # Encrypt key / generate params as defined by alg if alg == "RSA1_5": cipher = PKCS1_v1_5.new(key) encryptedKey = cipher.encrypt(CEK) elif alg == "RSA-OAEP": (CEK, IV) = generateKeyIV(enc) cipher = PKCS1_OAEP.new(key) encryptedKey = cipher.encrypt(CEK) elif alg in ["A128KW", "A192KW", "A256KW"]: encryptedKey = polyfills.aes_key_wrap(key, CEK) elif alg == "dir": CEK = key elif alg in ["ECDH-ES", "ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW"]: # Generate the input parameters apu = b64dec(header["apu"]) if "apu" in header else Random.get_random_bytes(16) apv = b64dec(header["apv"]) if "apv" in header else Random.get_random_bytes(16) # Generate an ephemeral key pair curve = NISTEllipticCurve.byName(getOrRaise(jwk, "crv")) if "epk" in header: epk = importKey(header["epk"], private=False) eprivk = importKey(header["epk"], private=True) else: (eprivk, epk) = curve.keyPair() # Derive the KEK and encrypt params = { "apu": b64enc(apu), "apv": b64enc(apv), "epk": exportKey(epk, "EC", curve) } if alg == "ECDH-ES": dkLen = keyLength(enc) CEK = polyfills.ECDH_deriveKey(curve, eprivk, key, apu, apv, enc, dkLen) elif alg == "ECDH-ES+A128KW": kek = polyfills.ECDH_deriveKey(curve, eprivk, key, apu, apv, "A128KW", 128) encryptedKey = polyfills.aes_key_wrap(kek, CEK) elif alg == "ECDH-ES+A192KW": kek = polyfills.ECDH_deriveKey(curve, eprivk, key, apu, apv, "A192KW", 192) encryptedKey = polyfills.aes_key_wrap(kek, CEK) elif alg == "ECDH-ES+A256KW": kek = polyfills.ECDH_deriveKey(curve, eprivk, key, apu, apv, "A256KW", 256) encryptedKey = polyfills.aes_key_wrap(kek, CEK) elif alg in ["A128GCMKW", "A192GCMKW", "A256GCMKW"]: iv = Random.get_random_bytes(12) gcm = AES_GCM(bytes_to_long(key)) encryptedKey, tag = gcm.encrypt(bytes_to_long(iv), CEK, '') params = { "iv": b64enc(iv), "tag": b64enc(long_to_bytes(tag,16)) } elif alg == "PBES2-HS256+A128KW": (CEK, IV) = generateKeyIV(enc) (encryptedKey, params) = \ polyfills.PBKDF_key_wrap( key, CEK, SHA256, 16, header ) elif alg == "PBES2-HS384+A192KW": (CEK, IV) = generateKeyIV(enc) (encryptedKey, params) = \ polyfills.PBKDF_key_wrap( key, CEK, SHA384, 24, header ) elif alg == "PBES2-HS512+A256KW": (CEK, IV) = generateKeyIV(enc) (encryptedKey, params) = \ polyfills.PBKDF_key_wrap( key, CEK, SHA512, 32, header ) else: raise Exception("Unsupported key management algorithm " + alg) return (CEK, encryptedKey, IV, params)