crypto docstrings.

This commit is contained in:
William Grant
2011-03-12 15:37:25 +11:00
parent 7dec2e4697
commit 7fa823748d
+54 -19
View File
@@ -68,11 +68,16 @@ ASN1_RSAPrivateKey = [
] ]
class DigestTooLarge(Exception):
pass
def parse_public_key(data): def parse_public_key(data):
"""Parse an RSA public key. """Parse an RSA public key.
@param data: A DER-encoded X.509 subjectPublicKeyInfo @param data: DER-encoded X.509 subjectPublicKeyInfo
containing an RFC3447 RSAPublicKey. containing an RFC3447 RSAPublicKey.
@return: RSA public key
""" """
x = asn1_parse(ASN1_Object, data) x = asn1_parse(ASN1_Object, data)
# Not sure why the [1:] is necessary to skip a byte. # Not sure why the [1:] is necessary to skip a byte.
@@ -85,6 +90,11 @@ def parse_public_key(data):
def parse_private_key(data): def parse_private_key(data):
"""Parse an RSA private key.
@param data: DER-encoded RFC3447 RSAPrivateKey.
@return: RSA private key
"""
pka = asn1_parse(ASN1_RSAPrivateKey, data) pka = asn1_parse(ASN1_RSAPrivateKey, data)
pk = { pk = {
'version': pka[0][0], 'version': pka[0][0],
@@ -100,14 +110,13 @@ def parse_private_key(data):
return pk return pk
def EMSA_PKCS1_v1_5_encode(digest, modlen, hashid): def EMSA_PKCS1_v1_5_encode(digest, mlen, hashid):
"""Encode a digest with EMSA-PKCS1-v1_5. """Encode a digest with RFC3447 EMSA-PKCS1-v1_5.
Defined in RFC3447 section 9.2. @param digest: digest byte string to encode
@param mlen: desired message length
@param digest: A digest value to encode. @param hashid: ID of the hash used to generate the digest
@param modlen: The desired message length. @return: encoded digest byte string
@param hashid: The ID of the hash used to generate the digest.
""" """
dinfo = asn1_build( dinfo = asn1_build(
(SEQUENCE, [ (SEQUENCE, [
@@ -117,15 +126,16 @@ def EMSA_PKCS1_v1_5_encode(digest, modlen, hashid):
]), ]),
(OCTET_STRING, digest), (OCTET_STRING, digest),
])) ]))
if len(dinfo)+3 > modlen: if len(dinfo)+3 > mlen:
raise Exception("Hash too large for modulus") # XXX: DKIMException raise Exception("Hash too large for modulus") # XXX: DKIMException
return "\x00\x01"+"\xff"*(modlen-len(dinfo)-3)+"\x00"+dinfo return "\x00\x01"+"\xff"*(mlen-len(dinfo)-3)+"\x00"+dinfo
def str2int(s): def str2int(s):
"""Convert an octet string to an integer. """Convert a byte string to an integer.
Octet string assumed to represent a positive integer. @param s: byte string representing a positive integer to convert
@return: converted integer
""" """
r = 0 r = 0
for c in s: for c in s:
@@ -134,13 +144,13 @@ def str2int(s):
def int2str(n, length=-1): def int2str(n, length=-1):
"""Convert an integer to an octet string. Number must be positive. """Convert an integer to a byte string.
@param n: Number to convert. @param n: positive integer to convert
@param length: Minimum length, or -1 to return the smallest number of @param length: minimum length
bytes that represent the integer. @return: converted bytestring, of at least the minimum length if it was
specified
""" """
assert n >= 0 assert n >= 0
r = [] r = []
while length < 0 or len(r) < length: while length < 0 or len(r) < length:
@@ -153,11 +163,27 @@ def int2str(n, length = -1):
return ''.join(r) return ''.join(r)
def perform_rsa(input, exponent, modulus, modlen): def perform_rsa(message, exponent, modulus, mlen):
return int2str(pow(str2int(input), exponent, modulus), modlen) """Perform RSA signing or verification.
@param message: byte string to operate on
@param exponent: public or private key exponent
@param modulus: key modulus
@param mlen: desired output length
@return: byte string result of the operation
"""
return int2str(pow(str2int(message), exponent, modulus), mlen)
def RSASSA_PKCS1_v1_5_sign(digest, hashid, private_exponent, modulus): def RSASSA_PKCS1_v1_5_sign(digest, hashid, private_exponent, modulus):
"""Sign a digest with RFC3447 RSASSA-PKCS1-v1_5.
@param digest: digest byte string to sign
@param hashid: ID of the hash used to generate the digest
@param private_exponent: private key exponent
@param modulus: key modulus
@return: signed digest byte string
"""
modlen = len(int2str(modulus)) modlen = len(int2str(modulus))
encoded_digest = EMSA_PKCS1_v1_5_encode(digest, modlen, hashid) encoded_digest = EMSA_PKCS1_v1_5_encode(digest, modlen, hashid)
return perform_rsa(encoded_digest, private_exponent, modulus, modlen) return perform_rsa(encoded_digest, private_exponent, modulus, modlen)
@@ -165,6 +191,15 @@ def RSASSA_PKCS1_v1_5_sign(digest, hashid, private_exponent, modulus):
def RSASSA_PKCS1_v1_5_verify(digest, hashid, signature, public_exponent, def RSASSA_PKCS1_v1_5_verify(digest, hashid, signature, public_exponent,
modulus): modulus):
"""Verify a digest signed with RFC3447 RSASSA-PKCS1-v1_5.
@param digest: digest byte string to check
@param hashid: ID of the hash used to generate the digest
@param signature: signed digest byte string
@param public_exponent: public key exponent
@param modulus: key modulus
@return: True if the signature is valid, False otherwise
"""
modlen = len(int2str(modulus)) modlen = len(int2str(modulus))
encoded_digest = EMSA_PKCS1_v1_5_encode(digest, modlen, hashid) encoded_digest = EMSA_PKCS1_v1_5_encode(digest, modlen, hashid)
signed_digest = perform_rsa(signature, public_exponent, modulus, modlen) signed_digest = perform_rsa(signature, public_exponent, modulus, modlen)