def to_dict(self): if not self.is_public(): public_key = self.prepared_key.get_verifying_key() else: public_key = self.prepared_key crv = { ecdsa.curves.NIST256p: 'P-256', ecdsa.curves.NIST384p: 'P-384', ecdsa.curves.NIST521p: 'P-521', }[self.prepared_key.curve] # Calculate the key size in bytes. Section 6.2.1.2 and 6.2.1.3 of # RFC7518 prescribes that the 'x', 'y' and 'd' parameters of the curve # points must be encoded as octed-strings of this length. key_size = self.prepared_key.curve.baselen data = { 'alg': self._algorithm, 'kty': 'EC', 'crv': crv, 'x': long_to_base64(public_key.pubkey.point.x(), size=key_size), 'y': long_to_base64(public_key.pubkey.point.y(), size=key_size), } if not self.is_public(): data['d'] = long_to_base64( self.prepared_key.privkey.secret_multiplier, size=key_size) return data
def to_dict(self): if not self.is_public(): public_key = self.prepared_key.get_verifying_key() else: public_key = self.prepared_key crv = { ecdsa.curves.NIST256p: 'P-256', ecdsa.curves.NIST384p: 'P-384', ecdsa.curves.NIST521p: 'P-521', }[self.prepared_key.curve] # Calculate the key size in bytes. Section 6.2.1.2 and 6.2.1.3 of # RFC7518 prescribes that the 'x', 'y' and 'd' parameters of the curve # points must be encoded as octed-strings of this length. key_size = self.prepared_key.curve.baselen data = { 'alg': self._algorithm, 'kty': 'EC', 'crv': crv, 'x': long_to_base64(public_key.pubkey.point.x(), size=key_size), 'y': long_to_base64(public_key.pubkey.point.y(), size=key_size), } if not self.is_public(): data['d'] = long_to_base64( self.prepared_key.privkey.secret_multiplier, size=key_size ) return data
def to_dict(self): if not self.is_public(): public_key = self.prepared_key.public_key() else: public_key = self.prepared_key crv = { 'secp256r1': 'P-256', 'secp384r1': 'P-384', 'secp521r1': 'P-521', }[self.prepared_key.curve.name] # Calculate the key size in bytes. Section 6.2.1.2 and 6.2.1.3 of # RFC7518 prescribes that the 'x', 'y' and 'd' parameters of the curve # points must be encoded as octed-strings of this length. key_size = (self.prepared_key.curve.key_size + 7) // 8 data = { 'alg': self._algorithm, 'kty': 'EC', 'crv': crv, 'x': long_to_base64(public_key.public_numbers().x, size=key_size), 'y': long_to_base64(public_key.public_numbers().y, size=key_size), } if not self.is_public(): data['d'] = long_to_base64( self.prepared_key.private_numbers().private_value, size=key_size) return data
def to_dict(self): if not self.is_public(): public_key = self.prepared_key.public_key() else: public_key = self.prepared_key crv = { 'secp256r1': 'P-256', 'secp384r1': 'P-384', 'secp521r1': 'P-521', }[self.prepared_key.curve.name] # Calculate the key size in bytes. Section 6.2.1.2 and 6.2.1.3 of # RFC7518 prescribes that the 'x', 'y' and 'd' parameters of the curve # points must be encoded as octed-strings of this length. key_size = (self.prepared_key.curve.key_size + 7) // 8 data = { 'alg': self._algorithm, 'kty': 'EC', 'crv': crv, 'x': long_to_base64(public_key.public_numbers().x, size=key_size), 'y': long_to_base64(public_key.public_numbers().y, size=key_size), } if not self.is_public(): data['d'] = long_to_base64( self.prepared_key.private_numbers().private_value, size=key_size ) return data
def create_jwk(): private_key = ec.generate_private_key(ec.SECP256R1(), default_backend()) public_key = private_key.public_key() pub_key = { 'alg': 'ES256', 'kty': 'EC', 'crv': 'P-256', 'use': 'sig', 'x': long_to_base64( public_key.public_numbers().x, size=32 ).decode('utf-8'), 'y': long_to_base64( public_key.public_numbers().y, size=32 ).decode('utf-8'), } priv_key = dict(pub_key) priv_key['d'] = long_to_base64( private_key.private_numbers().private_value, size=32 ).decode('utf-8') logger.debug("create_jwk()= " + json.dumps(pub_key, indent=4)) return priv_key, pub_key
def gen_jwks(): """Generate JSON Web Key Set (JWKS), exposing the public key details, based on the private key. Returns: dict: an RFC 7517-compliant data structure Refs: - https://tools.ietf.org/html/rfc7517 (specifying the JWKS format) - https://tools.ietf.org/html/rfc7518 (specifying key parameterization) """ log.info("Generate JSON Web Key Set") public_numbers = _public_key_cryptography.public_numbers() # Generate Key ID parameter, see # https://tools.ietf.org/html/rfc7517#section-4.5 # Make it depend on the (public) key specifics. fingerprint = "%s%sRSA" % (public_numbers.e, public_numbers.n) key_id = hashlib.sha256(fingerprint.encode('utf-8')).hexdigest() # `n` and `e` are Base64urlUInt-encoded values, see # https://tools.ietf.org/html/rfc7518#section-6.3 return { 'keys': [{ 'kid': key_id, 'kty': 'RSA', 'n': long_to_base64(public_numbers.n).decode('ascii'), 'e': long_to_base64(public_numbers.e).decode('ascii'), 'alg': 'RS256', 'use': 'sig' }] }
def generate_ecdsa_key(kid=6, jwkey=None, pem_priv=None, pem_pub=None): """ Creates a key using ECDSA algorithm :param kid: Customer key ID. Key ID to define key slot number in the key storage. Key ID must be in range 6-10 :param jwkey: Filename of the key in JWK format to create. If None, JWK file will not be created :param pem_priv: Filename of the private key in PEM format to create. If None, PEM file will not be created :param pem_pub: Filename of the public key in PEM format to create. If None, PEM file will not be created :return: """ private_key = ec.generate_private_key(ec.SECP256R1(), default_backend()) public_key = private_key.public_key() key_json = { 'alg': 'ES256', 'kty': 'EC', 'crv': 'P-256', 'use': 'sig', 'kid': str(kid), 'x': long_to_base64(public_key.public_numbers().x, size=32).decode('utf-8'), 'y': long_to_base64(public_key.public_numbers().y, size=32).decode('utf-8'), 'd': long_to_base64(private_key.private_numbers().private_value, size=32).decode('utf-8'), } key_str = json.dumps(key_json, indent=4) if jwkey: os.makedirs(os.path.dirname(jwkey), exist_ok=True) with open(jwkey, 'w') as fp: fp.write(key_str) logger.info(f'Created key in {jwkey}') key = ECKey(key_json, ALGORITHMS.ES256) if pem_priv: os.makedirs(os.path.dirname(pem_priv), exist_ok=True) with open(pem_priv, 'wb') as fp: fp.write(key.to_pem().strip()) if pem_pub: os.makedirs(os.path.dirname(pem_pub), exist_ok=True) with open(pem_pub, 'wb') as fp: fp.write(key.public_key().to_pem().strip()) return key_str
def to_dict(self): if not self.is_public(): public_key = self.prepared_key.public_key() else: public_key = self.prepared_key data = { 'alg': self._algorithm, 'kty': 'RSA', 'n': long_to_base64(public_key.public_numbers().n), 'e': long_to_base64(public_key.public_numbers().e), } if not self.is_public(): data.update({ 'd': long_to_base64(self.prepared_key.private_numbers().d), 'p': long_to_base64(self.prepared_key.private_numbers().p), 'q': long_to_base64(self.prepared_key.private_numbers().q), 'dp': long_to_base64(self.prepared_key.private_numbers().dmp1), 'dq': long_to_base64(self.prepared_key.private_numbers().dmq1), 'qi': long_to_base64(self.prepared_key.private_numbers().iqmp), }) return data
def to_dict(self): if not self.is_public(): public_key = self.public_key()._prepared_key else: public_key = self._prepared_key data = { 'alg': self._algorithm, 'kty': 'RSA', 'n': long_to_base64(public_key.n).decode('ASCII'), 'e': long_to_base64(public_key.e).decode('ASCII'), } if not self.is_public(): data.update({ 'd': long_to_base64(self._prepared_key.d).decode('ASCII'), 'p': long_to_base64(self._prepared_key.p).decode('ASCII'), 'q': long_to_base64(self._prepared_key.q).decode('ASCII'), 'dp': long_to_base64(self._prepared_key.exp1).decode('ASCII'), 'dq': long_to_base64(self._prepared_key.exp2).decode('ASCII'), 'qi': long_to_base64(self._prepared_key.coef).decode('ASCII'), }) return data
def to_dict(self): data = { 'alg': self._algorithm, 'kty': 'RSA', 'n': long_to_base64(self.prepared_key.n), 'e': long_to_base64(self.prepared_key.e), } if not self.is_public(): # Section 6.3.2 of RFC7518 prescribes that when we include the # optional parameters p and q, we must also include the values of # dp and dq, which are not readily available from PyCrypto - so we # calculate them. Moreover, PyCrypto stores the inverse of p # modulo q rather than the inverse of q modulo p, so we switch # p and q. As far as I can tell, this is OK - RFC7518 only # asserts that p is the 'first factor', but does not specify # what 'first' means in this case. dp = self.prepared_key.d % (self.prepared_key.p - 1) dq = self.prepared_key.d % (self.prepared_key.q - 1) data.update({ 'd': long_to_base64(self.prepared_key.d), 'p': long_to_base64(self.prepared_key.q), 'q': long_to_base64(self.prepared_key.p), 'dp': long_to_base64(dq), 'dq': long_to_base64(dp), 'qi': long_to_base64(self.prepared_key.u), }) return data
def to_dict(self): if not self.is_public(): public_key = self.public_key()._prepared_key else: public_key = self._prepared_key data = { "alg": self._algorithm, "kty": "RSA", "n": long_to_base64(public_key.n).decode("ASCII"), "e": long_to_base64(public_key.e).decode("ASCII"), } if not self.is_public(): data.update({ "d": long_to_base64(self._prepared_key.d).decode("ASCII"), "p": long_to_base64(self._prepared_key.p).decode("ASCII"), "q": long_to_base64(self._prepared_key.q).decode("ASCII"), "dp": long_to_base64(self._prepared_key.exp1).decode("ASCII"), "dq": long_to_base64(self._prepared_key.exp2).decode("ASCII"), "qi": long_to_base64(self._prepared_key.coef).decode("ASCII"), }) return data
def to_dict(self): if not self.is_public(): public_key = self.prepared_key.get_verifying_key() else: public_key = self.prepared_key crv = None for key, value in self.CURVE_NAMES: if key == self.prepared_key.curve: crv = value if not crv: raise KeyError(f"Can't match {self.prepared_key.curve}") # Calculate the key size in bytes. Section 6.2.1.2 and 6.2.1.3 of # RFC7518 prescribes that the 'x', 'y' and 'd' parameters of the curve # points must be encoded as octed-strings of this length. key_size = self.prepared_key.curve.baselen data = { "alg": self._algorithm, "kty": "EC", "crv": crv, "x": long_to_base64(public_key.pubkey.point.x(), size=key_size).decode("ASCII"), "y": long_to_base64(public_key.pubkey.point.y(), size=key_size).decode("ASCII"), } if not self.is_public(): data["d"] = long_to_base64( self.prepared_key.privkey.secret_multiplier, size=key_size).decode("ASCII") return data
def to_dict(self): if not self.is_public(): public_key = self.public_key()._prepared_key else: public_key = self._prepared_key data = { 'alg': self._algorithm, 'kty': 'RSA', 'n': long_to_base64(public_key.n), 'e': long_to_base64(public_key.e), } if not self.is_public(): data.update({ 'd': long_to_base64(self._prepared_key.d), 'p': long_to_base64(self._prepared_key.p), 'q': long_to_base64(self._prepared_key.q), 'dp': long_to_base64(self._prepared_key.exp1), 'dq': long_to_base64(self._prepared_key.exp2), 'qi': long_to_base64(self._prepared_key.coef), }) return data
def test_long_to_base64(self, longdata, kwargs, b64): assert utils.long_to_base64(longdata, **kwargs) == b64
def test_long_to_base64(self): assert utils.long_to_base64(0xDEADBEEF) == b'3q2-7w' assert utils.long_to_base64(0xCAFED00D, size=10) == b'AAAAAAAAyv7QDQ'