def pkcs_emsa_pss_verify(M, EM, emBits, h, mgf, sLen): """ Implements EMSA-PSS-VERIFY() function described in Sect. 9.1.2 of RFC 3447 Input: M : message to be encoded, an octet string EM : encoded message, an octet string of length emLen=ceil(emBits/8) emBits: maximal bit length of the integer resulting of pkcs_os2ip(EM) h : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls', 'sha256', 'sha384'). hLen denotes the length in octets of the hash function output. mgf : the mask generation function f : seed, maskLen -> mask sLen : intended length in octets of the salt Output: True if the verification is ok, False otherwise. """ # 1) is not done hLen = _hashFuncParams[h][0] # 2) hFunc = _hashFuncParams[h][2] mHash = hFunc(M) emLen = int(math.ceil(emBits / 8.)) # 3) if emLen < hLen + sLen + 2: return False if EM[-1] != '\xbc': # 4) return False l = emLen - hLen - 1 # 5) maskedDB = EM[:l] H = EM[l:l + hLen] l = (8 * emLen - emBits) / 8 # 6) rem = 8 * emLen - emBits - 8 * l # additionnal bits andMask = l * '\xff' if rem: val = reduce(lambda x, y: x + y, map(lambda x: 1 << x, range(8 - rem))) j = chr(~val & 0xff) andMask += j l += 1 if strand(maskedDB[:l], andMask) != '\x00' * l: return False dbMask = mgf(H, emLen - hLen - 1) # 7) DB = strxor(maskedDB, dbMask) # 8) l = (8 * emLen - emBits) / 8 # 9) rem = 8 * emLen - emBits - 8 * l # additionnal bits andMask = l * '\x00' if rem: j = chr( reduce(lambda x, y: x + y, map(lambda x: 1 << x, range(8 - rem)))) andMask += j l += 1 DB = strand(DB[:l], andMask) + DB[l:] l = emLen - hLen - sLen - 1 # 10) if DB[:l] != '\x00' * (l - 1) + '\x01': return False salt = DB[-sLen:] # 11) MPrime = '\x00' * 8 + mHash + salt # 12) HPrime = hFunc(MPrime) # 13) return H == HPrime # 14)
def pkcs_emsa_pss_encode(M, emBits, h, mgf, sLen): """ Implements EMSA-PSS-ENCODE() function described in Sect. 9.1.1 of RFC 3447 Input: M : message to be encoded, an octet string emBits: maximal bit length of the integer resulting of pkcs_os2ip(EM), where EM is the encoded message, output of the function. h : hash function name (in 'md2', 'md4', 'md5', 'sha1', 'tls', 'sha256', 'sha384'). hLen denotes the length in octets of the hash function output. mgf : the mask generation function f : seed, maskLen -> mask sLen : intended length in octets of the salt Output: encoded message, an octet string of length emLen = ceil(emBits/8) On error, None is returned. """ # 1) is not done hLen = _hashFuncParams[h][0] # 2) hFunc = _hashFuncParams[h][2] mHash = hFunc(M) emLen = int(math.ceil(emBits / 8.)) if emLen < hLen + sLen + 2: # 3) warning("encoding error (emLen < hLen + sLen + 2)") return None salt = randstring(sLen) # 4) MPrime = '\x00' * 8 + mHash + salt # 5) H = hFunc(MPrime) # 6) PS = '\x00' * (emLen - sLen - hLen - 2) # 7) DB = PS + '\x01' + salt # 8) dbMask = mgf(H, emLen - hLen - 1) # 9) maskedDB = strxor(DB, dbMask) # 10) l = (8 * emLen - emBits) / 8 # 11) rem = 8 * emLen - emBits - 8 * l # additionnal bits andMask = l * '\x00' if rem: j = chr( reduce(lambda x, y: x + y, map(lambda x: 1 << x, range(8 - rem)))) andMask += j l += 1 maskedDB = strand(maskedDB[:l], andMask) + maskedDB[l:] EM = maskedDB + H + '\xbc' # 12) return EM # 13)