def from_jwk(jwk):
            try:
                obj = json.loads(jwk)
            except ValueError:
                raise InvalidKeyError('Key is not valid JSON')

            if obj.get != 'RSA':
                raise InvalidKeyError('Not an RSA key')

            if 'd' in obj and 'e' in obj and 'n' in obj:
                # Private key
                if 'oth' in obj:
                    raise InvalidKeyError(
                        'Unsupported RSA private key: > 2 primes not supported'
                    )

                other_props = ['p', 'q', 'dp', 'dq', 'qi']
                props_found = [prop in obj for prop in other_props]
                any_props_found = any(props_found)

                if any_props_found and not all(props_found):
                    raise InvalidKeyError(
                        'RSA key must include all parameters if any are present besides d'
                    )

                public_numbers = RSAPublicNumbers(
                    from_base64url_uint(obj['e']),
                    from_base64url_uint(obj['n']))

                if any_props_found:
                    numbers = RSAPrivateNumbers(
                        d=from_base64url_uint(obj['d']),
                        p=from_base64url_uint(obj['p']),
                        q=from_base64url_uint(obj['q']),
                        dmp1=from_base64url_uint(obj['dp']),
                        dmq1=from_base64url_uint(obj['dq']),
                        iqmp=from_base64url_uint(obj['qi']),
                        public_numbers=public_numbers)
                else:
                    d = from_base64url_uint(obj['d'])
                    p, q = rsa_recover_prime_factors(public_numbers.n, d,
                                                     public_numbers.e)

                    numbers = RSAPrivateNumbers(d=d,
                                                p=p,
                                                q=q,
                                                dmp1=rsa_crt_dmp1(d, p),
                                                dmq1=rsa_crt_dmq1(d, q),
                                                iqmp=rsa_crt_iqmp(p, q),
                                                public_numbers=public_numbers)

                return numbers.private_key(default_backend())
            elif 'n' in obj and 'e' in obj:
                # Public key
                numbers = RSAPublicNumbers(from_base64url_uint(obj['e']),
                                           from_base64url_uint(obj['n']))

                return numbers.public_key(default_backend())
            else:
                raise InvalidKeyError('Not a public or private key')
def rsa_pem_from_jwk(jwk):
    return (RSAPublicNumbers(
        n=decode_value(jwk["n"]),
        e=decode_value(jwk["e"])).public_key(default_backend()).public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo,
        ))
def _convert_rsa_private_key(keypair):
    backend = Backend()

    def _trim_bn_to_int(s):
        binary = s.lstrip(b'\x00')
        bn_ptr = backend._lib.BN_bin2bn(binary, len(binary), backend._ffi.NULL)
        try:
            return backend._bn_to_int(bn_ptr)
        finally:
            backend._lib.OPENSSL_free(bn_ptr)

    (n, e, d, iqmp, p, q) = [
        _trim_bn_to_int(value)
        for value in _read_KEY_RSA(io.BytesIO(keypair.private_key))
    ]

    numbers = RSAPrivateNumbers(
        d=d,
        p=p,
        q=q,
        dmp1=rsa_crt_dmp1(d, p),
        dmq1=rsa_crt_dmq1(d, q),
        iqmp=rsa_crt_iqmp(p, q),
        public_numbers=RSAPublicNumbers(e=e, n=n),
    )

    return numbers.private_key(backend)
Exemple #4
0
 def private_numbers(self) -> RSAPrivateNumbers:
     n = self._backend._ffi.new("BIGNUM **")
     e = self._backend._ffi.new("BIGNUM **")
     d = self._backend._ffi.new("BIGNUM **")
     p = self._backend._ffi.new("BIGNUM **")
     q = self._backend._ffi.new("BIGNUM **")
     dmp1 = self._backend._ffi.new("BIGNUM **")
     dmq1 = self._backend._ffi.new("BIGNUM **")
     iqmp = self._backend._ffi.new("BIGNUM **")
     self._backend._lib.RSA_get0_key(self._rsa_cdata, n, e, d)
     self._backend.openssl_assert(n[0] != self._backend._ffi.NULL)
     self._backend.openssl_assert(e[0] != self._backend._ffi.NULL)
     self._backend.openssl_assert(d[0] != self._backend._ffi.NULL)
     self._backend._lib.RSA_get0_factors(self._rsa_cdata, p, q)
     self._backend.openssl_assert(p[0] != self._backend._ffi.NULL)
     self._backend.openssl_assert(q[0] != self._backend._ffi.NULL)
     self._backend._lib.RSA_get0_crt_params(self._rsa_cdata, dmp1, dmq1,
                                            iqmp)
     self._backend.openssl_assert(dmp1[0] != self._backend._ffi.NULL)
     self._backend.openssl_assert(dmq1[0] != self._backend._ffi.NULL)
     self._backend.openssl_assert(iqmp[0] != self._backend._ffi.NULL)
     return RSAPrivateNumbers(
         p=self._backend._bn_to_int(p[0]),
         q=self._backend._bn_to_int(q[0]),
         d=self._backend._bn_to_int(d[0]),
         dmp1=self._backend._bn_to_int(dmp1[0]),
         dmq1=self._backend._bn_to_int(dmq1[0]),
         iqmp=self._backend._bn_to_int(iqmp[0]),
         public_numbers=RSAPublicNumbers(
             e=self._backend._bn_to_int(e[0]),
             n=self._backend._bn_to_int(n[0]),
         ),
     )
Exemple #5
0
    def load_private_key(self):
        obj = self._dict_data

        if 'oth' in obj:  # pragma: no cover
            # https://tools.ietf.org/html/rfc7518#section-6.3.2.7
            raise ValueError('"oth" is not supported yet')

        public_numbers = RSAPublicNumbers(base64_to_int(obj['e']),
                                          base64_to_int(obj['n']))

        if has_all_prime_factors(obj):
            numbers = RSAPrivateNumbers(d=base64_to_int(obj['d']),
                                        p=base64_to_int(obj['p']),
                                        q=base64_to_int(obj['q']),
                                        dmp1=base64_to_int(obj['dp']),
                                        dmq1=base64_to_int(obj['dq']),
                                        iqmp=base64_to_int(obj['qi']),
                                        public_numbers=public_numbers)
        else:
            d = base64_to_int(obj['d'])
            p, q = rsa_recover_prime_factors(public_numbers.n, d,
                                             public_numbers.e)
            numbers = RSAPrivateNumbers(d=d,
                                        p=p,
                                        q=q,
                                        dmp1=rsa_crt_dmp1(d, p),
                                        dmq1=rsa_crt_dmq1(d, q),
                                        iqmp=rsa_crt_iqmp(p, q),
                                        public_numbers=public_numbers)

        return numbers.private_key(default_backend())
    def test_load_ssh_public_key_rsa(self, backend):
        ssh_key = (
            b"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDu/XRP1kyK6Cgt36gts9XAk"
            b"FiiuJLW6RU0j3KKVZSs1I7Z3UmU9/9aVh/rZV43WQG8jaR6kkcP4stOR0DEtll"
            b"PDA7ZRBnrfiHpSQYQ874AZaAoIjgkv7DBfsE6gcDQLub0PFjWyrYQUJhtOLQEK"
            b"vY/G0vt2iRL3juawWmCFdTK3W3XvwAdgGk71i6lHt+deOPNEPN2H58E4odrZ2f"
            b"sxn/adpDqfb2sM0kPwQs0aWvrrKGvUaustkivQE4XWiSFnB0oJB/lKK/CKVKuy"
            b"///ImSCGHQRvhwariN2tvZ6CBNSLh3iQgeB0AkyJlng7MXB2qYq/Ci2FUOryCX"
            b"2MzHvnbv testkey@localhost")

        key = load_ssh_public_key(ssh_key, backend)

        assert key is not None
        assert isinstance(key, interfaces.RSAPublicKey)

        numbers = key.public_numbers()

        expected_e = 0x10001
        expected_n = int(
            '00C3BBF5D13F59322BA0A0B77EA0B6CF570241628AE24B5BA454D'
            '23DCA295652B3523B67752653DFFD69587FAD9578DD6406F23691'
            'EA491C3F8B2D391D0312D9653C303B651067ADF887A5241843CEF'
            '8019680A088E092FEC305FB04EA070340BB9BD0F1635B2AD84142'
            '61B4E2D010ABD8FC6D2FB768912F78EE6B05A60857532B75B75EF'
            'C007601A4EF58BA947B7E75E38F3443CDD87E7C138A1DAD9D9FB3'
            '19FF69DA43A9F6F6B0CD243F042CD1A5AFAEB286BD46AEB2D922B'
            'D01385D6892167074A0907F94A2BF08A54ABB2FFFFC89920861D0'
            '46F8706AB88DDADBD9E8204D48B87789081E074024C8996783B31'
            '7076A98ABF0A2D8550EAF2097D8CCC7BE76EF', 16)

        expected = RSAPublicNumbers(expected_e, expected_n)

        assert numbers == expected
Exemple #7
0
    def validate(self, message):
        """Verify the signature of self RSA fulfillment.

        The signature of self RSA fulfillment is verified against the
        provided message and the condition's public modulus.

        Args:
            message (bytes): Message to verify.

        Returns:
            bool: Whether self fulfillment is valid.

        """
        if not isinstance(message, bytes):
            raise Exception('Message must be provided as bytes, was: ' +
                            message)

        public_numbers = RSAPublicNumbers(
            PUBLIC_EXPONENT,
            int.from_bytes(self.modulus, byteorder='big'),
        )
        public_key = public_numbers.public_key(default_backend())
        try:
            public_key.verify(
                self.signature, message,
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=SALT_LENGTH,
                ), hashes.SHA256())
        except InvalidSignature as exc:
            raise ValidationError('Invalid RSA signature') from exc

        return True
Exemple #8
0
    def _process_ssh_rsa(self, data):
        """Parses ssh-rsa public keys."""
        current_position, raw_e = self._unpack_by_int(data, 0)
        current_position, raw_n = self._unpack_by_int(data, current_position)

        unpacked_e = self._parse_long(raw_e)
        unpacked_n = self._parse_long(raw_n)

        self.rsa = RSAPublicNumbers(unpacked_e,
                                    unpacked_n).public_key(default_backend())
        self.bits = self.rsa.key_size

        if self.strict_mode:
            min_length = self.RSA_MIN_LENGTH_STRICT
            max_length = self.RSA_MAX_LENGTH_STRICT
        else:
            min_length = self.RSA_MIN_LENGTH_LOOSE
            max_length = self.RSA_MAX_LENGTH_LOOSE
        if self.bits < min_length:
            raise TooShortKeyError(
                "%s key data can not be shorter than %s bits (was %s)" %
                (self.key_type, min_length, self.bits))
        if self.bits > max_length:
            raise TooLongKeyError(
                "%s key data can not be longer than %s bits (was %s)" %
                (self.key_type, max_length, self.bits))
        return current_position
async def fetch_keys(client: httpx.AsyncClient) -> None:
    """
    Fetch JWT keys and store them in the JWT_KEYS that will act as a cache.
    """
    # TODO: Handling of the JWKS should be refactored to a separate library and it
    #  should make sure the caching + fetching fresh data is implemented according to
    #  standards. This simplified version now caches the keys forever (= until restart).
    url = openid_conf.jwks_uri

    logger.info("Fetching JWKS", url=url)

    response = await client.get(url)
    key_data = response.json()
    for entry in key_data["keys"]:
        kid = entry["kid"]
        algorithm = entry["alg"]
        if entry.get("kty") == "RSA" and "n" in entry and "e" in entry:
            n = urlsafe_b64_to_unsigned_int(entry["n"])
            e = urlsafe_b64_to_unsigned_int(entry["e"])
            key = RSAPublicNumbers(e=e, n=n).public_key(default_backend())
        else:
            key = load_der_x509_certificate(b64decode(entry["x5c"][0]),
                                            default_backend()).public_key()
        JWT_KEYS[kid] = {
            "algorithm": algorithm,
            "key": key,
        }
        logger.info("Added JWT key",
                    kid=kid,
                    algorithm=algorithm,
                    type=type(key).__name__)
Exemple #10
0
def rsa_pem_from_jwk():
    return RSAPublicNumbers(
        n=decode_value(jwts["keys"][0]['n']),
        e=decode_value(jwts["keys"][0]['e'])).public_key(
            default_backend()).public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo)
Exemple #11
0
def test_response_values(app, client):
    """
    Do some more thorough checking on the response obtained from the JWKS
    endpoint.

    Because fence only uses the RSA algorithm for signing and validating JWTs,
    the ``alg``, ``kty``, ``use``, and ``key_ops`` fields are hard-coded for
    this.

    Furthermore, every JWK in the response should have values for the RSA
    public modulus ``n`` and exponent ``e`` which may be used to reconstruct
    the public key.
    """
    keys = client.get('/.well-known/jwks').json['keys']
    app_kids = [keypair.kid for keypair in app.keypairs]
    app_public_keys = [keypair.public_key for keypair in app.keypairs]
    for key in keys:
        assert key['alg'] == 'RS256'
        assert key['kty'] == 'RSA'
        assert key['use'] == 'sig'
        assert key['key_ops'] == 'verify'
        assert key['kid'] in app_kids
        # Attempt to reproduce the public key from the values for the public
        # modulus and exponent provided in the response, using cryptography
        # primitives.
        n = int(base64.b64decode(key['n']))
        e = int(base64.b64decode(key['e']))
        numbers = RSAPublicNumbers(e, n)
        key = numbers.public_key(default_backend())
        key_pem = key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo)
        assert key_pem in app_public_keys
Exemple #12
0
 def rsa_pem_from_jwk(self, jwk: AzureAdKey):
     return (RSAPublicNumbers(
         n=self.decode_value(jwk.n), e=self.decode_value(jwk.e)).public_key(
             default_backend()).public_bytes(
                 encoding=serialization.Encoding.PEM,
                 format=serialization.PublicFormat.SubjectPublicKeyInfo,
             ))
Exemple #13
0
 def get_key(self, kid):
     keys = self.get_keys().get('keys')
     key = list(filter(lambda x: x.get('kid') == kid, keys))[0]
     _e = key['e']
     _n = key['n']
     e = int.from_bytes(base64url_decode(_e), 'big')
     n = int.from_bytes(base64url_decode(_n), 'big')
     return RSAPublicNumbers(e, n).public_key(default_backend())
Exemple #14
0
def _key_from_xml(node, backend):
    mod = int.from_bytes(base64.b64decode(
        node.xpath('RSAKeyValue/Modulus')[0].text),
                         byteorder='big')
    exp = int.from_bytes(base64.b64decode(
        node.xpath('RSAKeyValue/Exponent')[0].text),
                         byteorder='big')
    return RSAPublicNumbers(exp, mod).public_key(backend)
 def _convert(exponent: int, modulus: int) -> bytearray:
     components = RSAPublicNumbers(exponent, modulus)
     pub = components.public_key(backend=default_backend())
     key_bytes = pub.public_bytes(
         encoding=serialization.Encoding.PEM,
         format=serialization.PublicFormat.SubjectPublicKeyInfo,
     )
     return cast(bytearray, key_bytes)
Exemple #16
0
 def rsa_pem_from_jwk(key):
     return RSAPublicNumbers(
         n=AuthenticationHelper.decode_value(key['n']),
         e=AuthenticationHelper.decode_value(key['e'])
     ).public_key(default_backend()).public_bytes(
         encoding=serialization.Encoding.PEM,
         format=serialization.PublicFormat.SubjectPublicKeyInfo
     )
Exemple #17
0
def public_rsa_to_crypto(public):
    e = public.parameters.rsaDetail.exponent
    if e == 0:
        e = 65537 # F4, default exponent
    nbytes = buffer_to_bytes(public.unique.rsa)
    n = int.from_bytes(nbytes, 'big')
    key = RSAPublicNumbers(e, n).public_key(default_backend())
    return key
Exemple #18
0
    def validate_cert(cert, pubkey):
        from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers

        buf = TPMv1.decrypt_block(cert[8:], pubkey)
        if buf is None:
            return None
        mod = bytearray(buf[36:107] + cert[139:196])
        return RSAPublicNumbers(pubkey.e, Util.long_from_bytes(mod))
Exemple #19
0
 def __init__(self, json):
     super().__init__(json)
     decoded_n = bytes_to_int(urlsafe_b64decode(self.n))
     decoded_e = bytes_to_int(urlsafe_b64decode(self.e))
     rsa_public_key = RSAPublicNumbers(decoded_e, decoded_n).public_key(
         default_backend())
     self.public_key = rsa_public_key.public_bytes(
         Encoding.PEM, PublicFormat.SubjectPublicKeyInfo).decode()
Exemple #20
0
def rsa_pem_from_jwk(jwk):
    public_num = RSAPublicNumbers(n=decode_value(jwk['n']),
                                  e=decode_value(jwk['e']))
    public_key = public_num.public_key(default_backend())
    pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo)
    return pem
Exemple #21
0
def pubkey_from_tpm2b_public(public: bytes) -> pubkey_type:
    (public, rest) = _extract_tpm2b(public)
    if len(rest) != 0:
        raise ValueError("More in tpm2b_public than tpmt_public")
    # Extract type, [nameAlg], and [objectAttributes] (we don't care about the
    #  latter two)
    (alg_type, _, _) = struct.unpack(">HHI", public[0:8])
    # Ignore the authPolicy
    (_, sym_parms) = _extract_tpm2b(public[8:])
    # Ignore the non-asym-alg parameters
    (sym_mode, ) = struct.unpack(">H", sym_parms[0:2])
    # Ignore the sym_mode and keybits (4 bytes), possibly symmetric (2) and sign
    #  scheme (2)
    to_skip = 4 + 2  # sym_mode, keybits and sign scheme
    if sym_mode != TPM2_ALG_NULL:
        to_skip = to_skip + 2
    asym_parms = sym_parms[to_skip:]

    # Handle fields
    if alg_type == TPM_ALG_RSA:
        (keybits, exponent) = struct.unpack(">HI", asym_parms[0:6])
        if exponent == 0:
            exponent = 65537
        (modulus, _) = _extract_tpm2b(asym_parms[6:])
        if (len(modulus) * 8) != keybits:
            raise ValueError(
                f"Misparsed either modulus or keybits: {len(modulus)}*8 != {keybits}"
            )
        bmodulus = int.from_bytes(modulus, byteorder="big")

        numbers = RSAPublicNumbers(exponent, bmodulus)
        return numbers.public_key(backend=default_backend())

    if alg_type == TPM_ALG_ECC:
        (curve, _) = struct.unpack(">HH", asym_parms[0:4])
        asym_x = asym_parms[4:]
        curve = _curve_from_curve_id(curve)

        (x, asym_y) = _extract_tpm2b(asym_x)
        (y, rest) = _extract_tpm2b(asym_y)
        if len(rest) != 0:
            raise ValueError("Misparsed: more contents after X and Y")

        if (len(x) * 8) != curve.key_size:
            raise ValueError(
                f"Misparsed either X or curve: {len(x)}*8 != {curve.key_size}")
        if (len(y) * 8) != curve.key_size:
            raise ValueError(
                f"Misparsed either Y or curve curve: {len(y)}*8 != {curve.key_size}"
            )

        bx = int.from_bytes(x, byteorder="big")
        by = int.from_bytes(y, byteorder="big")

        numbers = EllipticCurvePublicNumbers(bx, by, curve)
        return numbers.public_key(backend=default_backend())

    raise ValueError(f"Invalid tpm2b_public type: {alg_type}")
Exemple #22
0
def jwk_to_pem(jwk):
    exponent = base64_to_long(jwk['e'])
    modulus = base64_to_long(jwk['n'])
    numbers = RSAPublicNumbers(exponent, modulus)
    public_key = numbers.public_key(backend=default_backend())
    pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo)
    return pem
Exemple #23
0
 def test_load_p12(self):
     cert = PinkSign(p12_data=base64.b64decode(TEST_CERT['pfx']),
                     prikey_password=TEST_CERT['signPw'])
     expected_public_numbers = RSAPublicNumbers(e=65537, n=TEST_CERT['n'])
     self.assertEqual(cert.pubkey.public_numbers(), expected_public_numbers)
     expected = RSAPrivateNumbers(p=TEST_CERT['p'], q=TEST_CERT['q'], d=TEST_CERT['d'], dmp1=TEST_CERT['dmp1'],
                                  dmq1=TEST_CERT['dmq1'], iqmp=TEST_CERT['iqmp'],
                                  public_numbers=expected_public_numbers)
     self.assertEqual(expected, cert.prikey.private_numbers())
def pubKeyToRSA (key):
	#get available RSA components from public key
    buff = b64decode(key)
    mod = (int.from_bytes(buff[0:129],byteorder='big'))
    exp = (int.from_bytes(buff[129:132],byteorder='big'))
    
    #construct the RSA object
    rsa=RSAPublicNumbers(exp,mod).public_key(backend = default_backend())
    return rsa;
Exemple #25
0
 def __init__(self, json):
     self._json = json
     self.expires = datetime.now() + timedelta(minutes=JWK_EXPIRES_MIN)
     decoded_n = bytes_to_int(urlsafe_b64decode(self.n))
     decoded_e = bytes_to_int(urlsafe_b64decode(self.e))
     rsa_public_key = RSAPublicNumbers(decoded_e, decoded_n).public_key(
         default_backend())
     self.public_key = rsa_public_key.public_bytes(
         Encoding.PEM, PublicFormat.SubjectPublicKeyInfo).decode()
Exemple #26
0
 def get_PEM_from_RSA(self, modulus, exponent):
     exponent_long = self.base64_to_long(exponent)
     modulus_long = self.base64_to_long(modulus)
     numbers = RSAPublicNumbers(exponent_long, modulus_long)
     public_key = numbers.public_key(backend=default_backend())
     pem = public_key.public_bytes(
         encoding=serialization.Encoding.PEM,
         format=serialization.PublicFormat.SubjectPublicKeyInfo)
     return pem
def pemFromModExp(modulus, exponent):
    exponentlong = base64_to_long(exponent)
    moduluslong = base64_to_long(modulus)
    numbers = RSAPublicNumbers(exponentlong, moduluslong)
    public_key = numbers.public_key(backend=default_backend())
    pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo)
    return pem
def from_jwk(obj):

    if obj.get('kty') != 'RSA':
        raise InvalidKeyError('Not an RSA key')

    # Public key
    numbers = RSAPublicNumbers(from_base64url_uint(obj['e']),
                               from_base64url_uint(obj['n']))

    return numbers.public_key(default_backend())
Exemple #29
0
def rsa_pem_from_jwk(jsonKeyResult):
    print(jsonKeyResult['keys'][0]['n'])
    exponent = base64_to_long(jsonKeyResult['keys'][0]['e'])
    modulus = base64_to_long(jsonKeyResult['keys'][0]['n'])
    numbers = RSAPublicNumbers(exponent, modulus)
    public_key = numbers.public_key(backend=default_backend())
    pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo)
    return pem
Exemple #30
0
 def verify(self):
     """ Verify the SSHCSR object in situ """
     public_key = RSAPublicNumbers(self.public_key.e, self.public_key.n)
     try:
         public_key.public_key(default_backend()).verify(
             base64.b64decode(self.signature), self.json(False),
             padding.PKCS1v15(), hashes.SHA256())
         return True
     except InvalidSignature:
         return False