1# This file is dual licensed under the terms of the Apache License, Version 2# 2.0, and the BSD License. See the LICENSE file in the root of this repository 3# for complete details. 4 5from __future__ import absolute_import, division, print_function 6 7import binascii 8import itertools 9import os 10 11from cryptography.hazmat.backends.openssl.backend import backend 12from cryptography.hazmat.primitives import hashes 13from cryptography.hazmat.primitives.asymmetric import padding, rsa 14 15from tests.utils import load_pkcs1_vectors, load_vectors_from_file 16 17 18def build_vectors(mgf1alg, hashalg, filename): 19 vectors = load_vectors_from_file(filename, load_pkcs1_vectors) 20 21 output = [] 22 for vector in vectors: 23 # RSA keys for this must be long enough to accommodate the length of 24 # the underlying hash function. This means we can't use the keys from 25 # the sha1 test vectors for sha512 tests because 1024-bit keys are too 26 # small. Instead we parse the vectors for the test cases, then 27 # generate our own 2048-bit keys for each. 28 private, _ = vector 29 skey = rsa.generate_private_key(65537, 2048, backend) 30 pn = skey.private_numbers() 31 examples = private["examples"] 32 output.append(b"# =============================================") 33 output.append(b"# Example") 34 output.append(b"# Public key") 35 output.append(b"# Modulus:") 36 output.append(format(pn.public_numbers.n, "x")) 37 output.append(b"# Exponent:") 38 output.append(format(pn.public_numbers.e, "x")) 39 output.append(b"# Private key") 40 output.append(b"# Modulus:") 41 output.append(format(pn.public_numbers.n, "x")) 42 output.append(b"# Public exponent:") 43 output.append(format(pn.public_numbers.e, "x")) 44 output.append(b"# Exponent:") 45 output.append(format(pn.d, "x")) 46 output.append(b"# Prime 1:") 47 output.append(format(pn.p, "x")) 48 output.append(b"# Prime 2:") 49 output.append(format(pn.q, "x")) 50 output.append(b"# Prime exponent 1:") 51 output.append(format(pn.dmp1, "x")) 52 output.append(b"# Prime exponent 2:") 53 output.append(format(pn.dmq1, "x")) 54 output.append(b"# Coefficient:") 55 output.append(format(pn.iqmp, "x")) 56 pkey = skey.public_key() 57 vectorkey = rsa.RSAPrivateNumbers( 58 p=private["p"], 59 q=private["q"], 60 d=private["private_exponent"], 61 dmp1=private["dmp1"], 62 dmq1=private["dmq1"], 63 iqmp=private["iqmp"], 64 public_numbers=rsa.RSAPublicNumbers( 65 e=private["public_exponent"], 66 n=private["modulus"] 67 ) 68 ).private_key(backend) 69 count = 1 70 71 for example in examples: 72 message = vectorkey.decrypt( 73 binascii.unhexlify(example["encryption"]), 74 padding.OAEP( 75 mgf=padding.MGF1(algorithm=hashes.SHA1()), 76 algorithm=hashes.SHA1(), 77 label=None 78 ) 79 ) 80 assert message == binascii.unhexlify(example["message"]) 81 ct = pkey.encrypt( 82 message, 83 padding.OAEP( 84 mgf=padding.MGF1(algorithm=mgf1alg), 85 algorithm=hashalg, 86 label=None 87 ) 88 ) 89 output.append( 90 b"# OAEP Example {0} alg={1} mgf1={2}".format( 91 count, hashalg.name, mgf1alg.name 92 ) 93 ) 94 count += 1 95 output.append(b"# Message:") 96 output.append(example["message"]) 97 output.append(b"# Encryption:") 98 output.append(binascii.hexlify(ct)) 99 100 return b"\n".join(output) 101 102 103def write_file(data, filename): 104 with open(filename, "w") as f: 105 f.write(data) 106 107 108oaep_path = os.path.join( 109 "asymmetric", "RSA", "pkcs-1v2-1d2-vec", "oaep-vect.txt" 110) 111hashalgs = [ 112 hashes.SHA1(), 113 hashes.SHA224(), 114 hashes.SHA256(), 115 hashes.SHA384(), 116 hashes.SHA512(), 117] 118for hashtuple in itertools.product(hashalgs, hashalgs): 119 if ( 120 isinstance(hashtuple[0], hashes.SHA1) and 121 isinstance(hashtuple[1], hashes.SHA1) 122 ): 123 continue 124 125 write_file( 126 build_vectors(hashtuple[0], hashtuple[1], oaep_path), 127 "oaep-{0}-{1}.txt".format(hashtuple[0].name, hashtuple[1].name) 128 ) 129