1# -*- coding: utf-8 -*- 2# 3# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# https://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Functions for PKCS#1 version 2 encryption and signing 18 19This module implements certain functionality from PKCS#1 version 2. Main 20documentation is RFC 2437: https://tools.ietf.org/html/rfc2437 21""" 22 23from rsa._compat import range 24from rsa import ( 25 common, 26 pkcs1, 27 transform, 28) 29 30 31def mgf1(seed, length, hasher='SHA-1'): 32 """ 33 MGF1 is a Mask Generation Function based on a hash function. 34 35 A mask generation function takes an octet string of variable length and a 36 desired output length as input, and outputs an octet string of the desired 37 length. The plaintext-awareness of RSAES-OAEP relies on the random nature of 38 the output of the mask generation function, which in turn relies on the 39 random nature of the underlying hash. 40 41 :param bytes seed: seed from which mask is generated, an octet string 42 :param int length: intended length in octets of the mask, at most 2^32(hLen) 43 :param str hasher: hash function (hLen denotes the length in octets of the hash 44 function output) 45 46 :return: mask, an octet string of length `length` 47 :rtype: bytes 48 49 :raise OverflowError: when `length` is too large for the specified `hasher` 50 :raise ValueError: when specified `hasher` is invalid 51 """ 52 53 try: 54 hash_length = pkcs1.HASH_METHODS[hasher]().digest_size 55 except KeyError: 56 raise ValueError( 57 'Invalid `hasher` specified. Please select one of: {hash_list}'.format( 58 hash_list=', '.join(sorted(pkcs1.HASH_METHODS.keys())) 59 ) 60 ) 61 62 # If l > 2^32(hLen), output "mask too long" and stop. 63 if length > (2**32 * hash_length): 64 raise OverflowError( 65 "Desired length should be at most 2**32 times the hasher's output " 66 "length ({hash_length} for {hasher} function)".format( 67 hash_length=hash_length, 68 hasher=hasher, 69 ) 70 ) 71 72 # Looping `counter` from 0 to ceil(l / hLen)-1, build `output` based on the 73 # hashes formed by (`seed` + C), being `C` an octet string of length 4 74 # generated by converting `counter` with the primitive I2OSP 75 output = b''.join( 76 pkcs1.compute_hash( 77 seed + transform.int2bytes(counter, fill_size=4), 78 method_name=hasher, 79 ) 80 for counter in range(common.ceil_div(length, hash_length) + 1) 81 ) 82 83 # Output the leading `length` octets of `output` as the octet string mask. 84 return output[:length] 85 86 87__all__ = [ 88 'mgf1', 89] 90 91if __name__ == '__main__': 92 print('Running doctests 1000x or until failure') 93 import doctest 94 95 for count in range(1000): 96 (failures, tests) = doctest.testmod() 97 if failures: 98 break 99 100 if count % 100 == 0 and count: 101 print('%i times' % count) 102 103 print('Doctests done') 104