# 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 itertools import os from cryptography.hazmat.backends.openssl.backend import backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding, rsa from tests.utils import load_pkcs1_vectors, load_vectors_from_file def build_vectors(mgf1alg, hashalg, filename): vectors = load_vectors_from_file(filename, load_pkcs1_vectors) output = [] for vector in vectors: # RSA keys for this must be long enough to accommodate the length of # the underlying hash function. This means we can't use the keys from # the sha1 test vectors for sha512 tests because 1024-bit keys are too # small. Instead we parse the vectors for the test cases, then # generate our own 2048-bit keys for each. private, _ = vector skey = rsa.generate_private_key(65537, 2048, backend) pn = skey.private_numbers() examples = private["examples"] output.append(b"# =============================================") output.append(b"# Example") output.append(b"# Public key") output.append(b"# Modulus:") output.append(format(pn.public_numbers.n, "x")) output.append(b"# Exponent:") output.append(format(pn.public_numbers.e, "x")) output.append(b"# Private key") output.append(b"# Modulus:") output.append(format(pn.public_numbers.n, "x")) output.append(b"# Public exponent:") output.append(format(pn.public_numbers.e, "x")) output.append(b"# Exponent:") output.append(format(pn.d, "x")) output.append(b"# Prime 1:") output.append(format(pn.p, "x")) output.append(b"# Prime 2:") output.append(format(pn.q, "x")) output.append(b"# Prime exponent 1:") output.append(format(pn.dmp1, "x")) output.append(b"# Prime exponent 2:") output.append(format(pn.dmq1, "x")) output.append(b"# Coefficient:") output.append(format(pn.iqmp, "x")) pkey = skey.public_key() vectorkey = rsa.RSAPrivateNumbers( p=private["p"], q=private["q"], d=private["private_exponent"], dmp1=private["dmp1"], dmq1=private["dmq1"], iqmp=private["iqmp"], public_numbers=rsa.RSAPublicNumbers( e=private["public_exponent"], n=private["modulus"] ) ).private_key(backend) count = 1 for example in examples: message = vectorkey.decrypt( binascii.unhexlify(example["encryption"]), padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA1(), label=None ) ) assert message == binascii.unhexlify(example["message"]) ct = pkey.encrypt( message, padding.OAEP( mgf=padding.MGF1(algorithm=mgf1alg), algorithm=hashalg, label=None ) ) output.append( b"# OAEP Example {0} alg={1} mgf1={2}".format( count, hashalg.name, mgf1alg.name ) ) count += 1 output.append(b"# Message:") output.append(example["message"]) output.append(b"# Encryption:") output.append(binascii.hexlify(ct)) return b"\n".join(output) def write_file(data, filename): with open(filename, "w") as f: f.write(data) oaep_path = os.path.join( "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "oaep-vect.txt" ) hashalgs = [ hashes.SHA1(), hashes.SHA224(), hashes.SHA256(), hashes.SHA384(), hashes.SHA512(), ] for hashtuple in itertools.product(hashalgs, hashalgs): if ( isinstance(hashtuple[0], hashes.SHA1) and isinstance(hashtuple[1], hashes.SHA1) ): continue write_file( build_vectors(hashtuple[0], hashtuple[1], oaep_path), "oaep-{0}-{1}.txt".format(hashtuple[0].name, hashtuple[1].name) )