Bug 1413937 - add sha384 and sha512 to pycert and pykey, r=keeler
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Thu, 09 Nov 2017 16:55:12 +0100
changeset 444453 c69e6ac63826176ea18339a44e7297164dd8a335
parent 444452 b9dda4555fa53291779a2d1612eb1de0d6261013
child 444454 1721ccb0d0d653e39acd11111f495ebe9308f1e2
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1413937
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1413937 - add sha384 and sha512 to pycert and pykey, r=keeler MozReview-Commit-ID: ArjNHLC1MFC Differential Revision: https://phabricator.services.mozilla.com/D185
security/manager/ssl/tests/unit/pycert.py
security/manager/ssl/tests/unit/pykey.py
--- a/security/manager/ssl/tests/unit/pycert.py
+++ b/security/manager/ssl/tests/unit/pycert.py
@@ -12,17 +12,18 @@ The input format is as follows:
 
 issuer:<issuer distinguished name specification>
 subject:<subject distinguished name specification>
 [version:{1,2,3,4}]
 [validity:<YYYYMMDD-YYYYMMDD|duration in days>]
 [issuerKey:<key specification>]
 [subjectKey:<key specification>]
 [signature:{sha256WithRSAEncryption,sha1WithRSAEncryption,
-            md5WithRSAEncryption,ecdsaWithSHA256}]
+            md5WithRSAEncryption,ecdsaWithSHA256,ecdsaWithSHA384,
+            ecdsaWithSHA512}]
 [serialNumber:<integer in the interval [1, 127]>]
 [extension:<extension name:<extension-specific data>>]
 [...]
 
 Known extensions are:
 basicConstraints:[cA],[pathLenConstraint]
 keyUsage:[digitalSignature,nonRepudiation,keyEncipherment,
           dataEncipherment,keyAgreement,keyCertSign,cRLSign]
@@ -328,16 +329,22 @@ def stringToAlgorithmIdentifiers(string)
         algorithmType = pykey.HASH_SHA256
         algorithm = univ.ObjectIdentifier('1.2.840.113549.1.1.11')
     elif string == 'md5WithRSAEncryption':
         algorithmType = pykey.HASH_MD5
         algorithm = rfc2459.md5WithRSAEncryption
     elif string == 'ecdsaWithSHA256':
         algorithmType = pykey.HASH_SHA256
         algorithm = univ.ObjectIdentifier('1.2.840.10045.4.3.2')
+    elif string == 'ecdsaWithSHA384':
+        algorithmType = pykey.HASH_SHA384
+        algorithm = univ.ObjectIdentifier('1.2.840.10045.4.3.3')
+    elif string == 'ecdsaWithSHA512':
+        algorithmType = pykey.HASH_SHA512
+        algorithm = univ.ObjectIdentifier('1.2.840.10045.4.3.4')
     else:
         raise UnknownAlgorithmTypeError(string)
     algorithmIdentifier.setComponentByName('algorithm', algorithm)
     return (algorithmIdentifier, algorithmType)
 
 def datetimeToTime(dt):
     """Takes a datetime object and returns an rfc2459.Time object with
     that time as its value as a GeneralizedTime"""
--- a/security/manager/ssl/tests/unit/pykey.py
+++ b/security/manager/ssl/tests/unit/pykey.py
@@ -40,16 +40,18 @@ import binascii
 import mock
 import rsa
 import sys
 
 # "constants" to make it easier for consumers to specify hash algorithms
 HASH_MD5 = 'hash:md5'
 HASH_SHA1 = 'hash:sha1'
 HASH_SHA256 = 'hash:sha256'
+HASH_SHA384 = 'hash:sha384'
+HASH_SHA512 = 'hash:sha512'
 
 def byteStringToHexifiedBitString(string):
     """Takes a string of bytes and returns a hex string representing
     those bytes for use with pyasn1.type.univ.BitString. It must be of
     the form "'<hex bytes>'H", where the trailing 'H' indicates to
     pyasn1 that the input is a hex string."""
     return "'%s'H" % binascii.hexlify(string)
 
@@ -583,16 +585,20 @@ class RSAKey(object):
         Intended for use with pyasn1.type.univ.BitString"""
         hashAlgorithmName = None
         if hashAlgorithm == HASH_MD5:
             hashAlgorithmName = "MD5"
         elif hashAlgorithm == HASH_SHA1:
             hashAlgorithmName = "SHA-1"
         elif hashAlgorithm == HASH_SHA256:
             hashAlgorithmName = "SHA-256"
+        elif hashAlgorithm == HASH_SHA384:
+            hashAlgorithmName = "SHA-384"
+        elif hashAlgorithm == HASH_SHA512:
+            hashAlgorithmName = "SHA-512"
         else:
             raise UnknownHashAlgorithmError(hashAlgorithm)
         rsaPrivateKey = rsa.PrivateKey(self.RSA_N, self.RSA_E, self.RSA_D, self.RSA_P, self.RSA_Q)
         signature = rsa.sign(data, rsaPrivateKey, hashAlgorithmName)
         return byteStringToHexifiedBitString(signature)
 
 
 ecPublicKey = univ.ObjectIdentifier('1.2.840.10045.2.1')
@@ -696,30 +702,28 @@ class ECCKey(object):
         subjectPublicKey = univ.BitString(hexifiedBitString)
         spki.setComponentByName('subjectPublicKey', subjectPublicKey)
         return spki
 
     def sign(self, data, hashAlgorithm):
         """Returns a hexified bit string representing a
         signature by this key over the specified data.
         Intended for use with pyasn1.type.univ.BitString"""
-        if hashAlgorithm != HASH_SHA256:
-            raise UnsupportedHashAlgorithmError(hashAlgorithm)
         # There is some non-determinism in ECDSA signatures. Work around
         # this by patching ecc.ecdsa.urandom to not be random.
         with mock.patch('ecc.ecdsa.urandom', side_effect=notRandom):
             # For some reason Key.sign returns an encoded point.
             # Decode it so we can encode it as a BITSTRING consisting
             # of a SEQUENCE of two INTEGERs.
             # Also patch in secp256k1 if applicable.
             if self.keyOID == secp256k1:
                 with mock.patch('ecc.curves.DOMAINS', {256: secp256k1Params}):
-                    x, y = encoding.dec_point(self.key.sign(data, 'sha256'))
+                    x, y = encoding.dec_point(self.key.sign(data, hashAlgorithm.split(':')[-1]))
             else:
-                x, y = encoding.dec_point(self.key.sign(data, 'sha256'))
+                x, y = encoding.dec_point(self.key.sign(data, hashAlgorithm.split(':')[-1]))
             point = ECPoint()
             point.setComponentByName('x', x)
             point.setComponentByName('y', y)
             return byteStringToHexifiedBitString(encoder.encode(point))
 
 
 def keyFromSpecification(specification):
     """Pass in a specification, get the appropriate key back."""