def sign(self, data): ecdsa_sig = None try: # Hash and apply ECDSA hashBuf = bytesToC(Digest.SHA256(data)) ecdsa_sig = o.ECDSA_do_sign(hashBuf, 32, self.ec_key) # Encode the signature into 64 bytes rBuf = bytesToC(bytearray(32)) sBuf = bytesToC(bytearray(32)) rLen = o.BN_bn2bin(ecdsa_sig.contents.r, rBuf) sLen = o.BN_bn2bin(ecdsa_sig.contents.s, sBuf) rBytes = bytearray(32 - rLen) + cToBytes(rBuf)[:rLen] sBytes = bytearray(32 - sLen) + cToBytes(sBuf)[:sLen] sigBytes = rBytes + sBytes assert (len(sigBytes) == 64) finally: if ecdsa_sig: o.ECDSA_SIG_free(ecdsa_sig) # Double-check the signature before returning assert (OpenSSL_ECPublicKey(self.rawPublicKey).verify(data, sigBytes)) return sigBytes
def sign(self, data): privateKeyNum = bytesToNumber(self.rawPrivateKey) hash = Digest.SHA256(data) g = generator_256 n = g.order() x = bytesToNumber(self.rawPublicKey[:32]) y = bytesToNumber(self.rawPublicKey[32:]) pubkey = Public_key(g, Point(g.curve(), x, y)) privkey = Private_key(pubkey, privateKeyNum) # Generating random nonce k per FIPS 186-3 B.5.1: # (except we use 32 extra bytes instead of 8 before reduction) # Random bytes taken from os.urandom as well as HMAC(privkey,hash) # REVIEW THIS CAREFULLY!!! CHANGE AT YOUR PERIL!!! # 64 random bytes and HMAC(rawPrivateKey,hash) are used as key for an # HMAC PRF to generate a 64-byte value which is reduced modulo # n to produce the nonce # # The use of HMAC(rawPrivateKey,hash) means this construction # will be secure even if os.urandom fails, however we include # os.urandom anyways out of an excess of caution randBytes0 = bytearray(os.urandom(64)) randBytes0 += Digest.HMAC_SHA256(self.rawPrivateKey, hash) randBytes = Digest.HMAC_SHA256(randBytes0, bytearray([1])) randBytes += Digest.HMAC_SHA256(randBytes0, bytearray([2])) c = bytesToNumber(randBytes) k = (c % (n - 1)) + 1 hashNum = bytesToNumber(hash) sig = privkey.sign(hashNum, k) sigBytes = numberToBytes(sig.r, 32) + numberToBytes(sig.s, 32) # Double-check the signature before returning assert (Python_ECPublicKey(self.rawPublicKey).verify(data, sigBytes)) return sigBytes
def verify(self, data, signature): assert(len(signature) == 64) hashNum = bytesToNumber(Digest.SHA256(data)) g = generator_256 x = bytesToNumber(self.rawPublicKey[ : 32]) y = bytesToNumber(self.rawPublicKey[32 : ]) pubkey = Public_key(g, Point(g.curve(), x,y)) sig = Signature(bytesToNumber(signature[:32]), bytesToNumber(signature[32:])) return pubkey.verifies(hashNum, sig)
def getSignature(self, data): # Produce ASN.1 signature hash = Digest.SHA256(data) asn1SigBytes = self.ec.sign_dsa_asn1(hash) # Convert stupid ASN.1 signature into 64-byte signature # Double-check before returning sigBytes = self._convertToRawSignature(asn1SigBytes) assert (ECPublicKey(self.rawPublicKey, self.ec).verify(data, sigBytes)) return sigBytes
def verify(self, data, signature): assert (len(signature) == 64) ecdsa_sig = None try: # Create ECDSA_SIG ecdsa_sig = o.ECDSA_SIG_new() rBuf = bytesToC(signature[:32]) sBuf = bytesToC(signature[32:]) o.BN_bin2bn(rBuf, 32, ecdsa_sig.contents.r) o.BN_bin2bn(sBuf, 32, ecdsa_sig.contents.s) # Hash and verify ECDSA hashBuf = bytesToC(Digest.SHA256(data)) retval = o.ECDSA_do_verify(hashBuf, 32, ecdsa_sig, self.ec_key) if retval == 1: return True elif retval == 0: return False else: assert (False) finally: if ecdsa_sig: o.ECDSA_SIG_free(ecdsa_sig)
def getFingerprint(self): digest = Digest.SHA256(self.rawPublicKey) assert (len(digest) == 32) s = b2a_base32(digest).lower()[:25] return "%s.%s.%s.%s.%s" % (s[:5], s[5:10], s[10:15], s[15:20], s[20:25])
def __init__(self, data=None): if data is None: return #self.key_sha256 = bytearray(32) #self.cert_sha256 = bytearray(32) self.notAfter = 0 # Below values are populated for TACK certs self.tackExt = None # Below values hold cert contents excluding TACK stuff self.preExtBytes = None self.extBytes = None self.postExtBytes = None p = ASN1Parser(data) #Get the tbsCertificate tbsCertificateP = p.getChild(0) #Is the optional version field present? #This determines which index the key is at if tbsCertificateP.value[0] == 0xA0: subjectPublicKeyInfoIndex = 6 validityIndex = 4 else: subjectPublicKeyInfoIndex = 5 validityIndex = 3 #Get the subjectPublicKeyInfo spkiP = tbsCertificateP.getChild(subjectPublicKeyInfoIndex) #Parse the notAfter time validityP = tbsCertificateP.getChild(validityIndex) notAfterP = validityP.getChild(1) if notAfterP.type == 0x17: # UTCTime self.notAfter = Time.parseASN1UTCTime(notAfterP.value) elif notAfterP.type == 0x18: # GeneralizedTime self.notAfter = Time.parseASN1GeneralizedTime(notAfterP.value) else: raise SyntaxError() # Get the hash values self.cert_sha256 = Digest.SHA256(data) self.key_sha256 = Digest.SHA256(spkiP.getTotalBytes()) # Check if this is a TACK certificate: #Get the tbsCertificate versionP = tbsCertificateP.getChild(0) if versionP.type != 0xA0: # i.e. tag of [0], version return # X.509 version field not present versionPP = versionP.getTagged() if versionPP.value != bytearray([0x02]): return # X.509 version field does not equal v3 # Find extensions element x = 0 while 1: certFieldP = tbsCertificateP.getChild(x) if not certFieldP: raise SyntaxError("X.509 extensions not present") if certFieldP.type == 0xA3: # i.e. tag of [3], extensions break x += 1 self.preExtBytes = data[versionP.offset:certFieldP.offset] self.extBytes = bytearray() # Iterate through extensions x = 0 certFieldPP = certFieldP.getTagged() while 1: extFieldP = certFieldPP.getChild(x) if not extFieldP: break # Check the extnID and parse out TACK if present extnIDP = extFieldP.getChild(0) if extnIDP.value == TlsCertificate.OID_TACK: if self.tackExt: raise SyntaxError("More than one TACK Extension") # OK! We found a TACK, parse it.. self.tackExt = TackExtension(extFieldP.getChild(1).value) else: # Collect all non-TACK extensions: self.extBytes += data[extFieldP.offset :\ extFieldP.offset + extFieldP.getTotalLength()] x += 1 # Finish copying the tail of the certificate self.postExtBytes = data[certFieldP.offset + certFieldP.getTotalLength():]
def verify(self, data, signature): # Convert 64-byte signature into a stupid ASN.1 signature asn1SigBytes = self._convertToAsn1Signature(signature) hash = Digest.SHA256(data) return self.ec.verify_dsa_asn1(hash, asn1SigBytes)