def step4(self, buffer): (pa, qa, ra, c6, d7, d8, c7, d9) = unpackList(buffer) if not self.isValidArgument(pa) or not self.isValidArgument(qa) or not self.isValidArgument(ra): raise exceptions.CryptoError("Invalid pa/qa/ra values", errors.ERR_SMP_CHECK_FAILED) if not self.checkCoordsProof('6', c6, d7, d8, self.gb2, self.gb3, pa, qa): raise exceptions.CryptoError("Proof 6 check failed", errors.ERR_SMP_CHECK_FAILED) if not self.checkEqualLogs('7', c7, d9, self.g3a, mulm(qa, self.invm(self.qb), self.mod), ra): raise exceptions.CryptoError("Proof 7 check failed", errors.ERR_SMP_CHECK_FAILED) inv = self.invm(self.qb) rb = pow(mulm(qa, inv, self.mod), self.x3, self.mod) (c8, d10) = self.createEqualLogsProof('8', qa, inv, self.x3) rab = pow(ra, self.x3, self.mod) inv = self.invm(self.pb) if rab == mulm(pa, inv, self.mod): self.match = True # Send rb, c8, d10 return packList(rb, c8, d10)
def step5(self, buffer): (rb, c8, d10) = unpackList(buffer) if not self.isValidArgument(rb): raise exceptions.CryptoError("Invalid rb values", errors.ERR_SMP_CHECK_FAILED) if not self.checkEqualLogs('8', c8, d10, self.g3b, mulm(self.qa, self.invm(self.qb), self.mod), rb): raise exceptions.CryptoError("Proof 8 check failed", errors.ERR_SMP_CHECK_FAILED) rab = pow(rb, self.x3, self.mod) inv = self.invm(self.pb) if rab == mulm(self.pa, inv, self.mod): self.match = True
def __handleSMPCommand(self, command, payload): try: if command == constants.COMMAND_SMP_0: # Fire the SMP request callback with the given question self.smpRequestCallback(constants.SMP_CALLBACK_REQUEST, self.remoteNick, payload) elif command == constants.COMMAND_SMP_1: # If there's already an smp object, go ahead to step 1. # Otherwise, save the payload until we have an answer from the user to respond with if self.smp: self.__doSMPStep1(payload) else: self.smpStep1 = payload elif command == constants.COMMAND_SMP_2: self.__doSMPStep2(payload) elif command == constants.COMMAND_SMP_3: self.__doSMPStep3(payload) elif command == constants.COMMAND_SMP_4: self.__doSMPStep4(payload) else: # This shouldn't happen raise exceptions.CryptoError(errno=errors.ERR_SMP_CHECK_FAILED) except exceptions.CryptoError as ce: self.smpRequestCallback(constants.SMP_CALLBACK_ERROR, self.remoteNick, '', ce.errno)
def __getDecryptedPayload(self, message): if self.isEncrypted: payload = message.getEncryptedPayloadAsBinaryString() encryptedMessageNumber = message.getMessageNumAsBinaryString() # Check the HMAC if not self.__verifyHmac(message.hmac, payload): self.errorCallback(message.sourceNick, errors.ERR_BAD_HMAC) raise exceptions.CryptoError(errno=errors.BAD_HMAC) try: # Check the message number messageNumber = int( self.crypto.aesDecrypt(encryptedMessageNumber)) # If the message number is less than what we're expecting, the message is being replayed if self.incomingMessageNum > messageNumber: raise exceptions.ProtocolError( errno=errors.ERR_MESSAGE_REPLAY) # If the message number is greater than what we're expecting, messages are being deleted elif self.incomingMessageNum < messageNumber: raise exceptions.ProtocolError( errno=errors.ERR_MESSAGE_DELETION) self.incomingMessageNum += 1 # Decrypt the payload payload = self.crypto.aesDecrypt(payload) except exceptions.CryptoError as ce: self.errorCallback(message.sourceNick, errors.ERR_BAD_DECRYPT) raise ce else: payload = message.payload return payload
def aesDecrypt(self, message): try: cipher = self.__aesGetCipher(self.DECRYPT) decMessage = cipher.update(message) return decMessage + cipher.final() except M2Crypto.EVP.EVPError as evpe: raise exceptions.CryptoError(str(evpe))
def rsaEncrypt(self, message): self.__checkRemoteKeypair() try: return self.remoteKeypair.public_encrypt( message, M2Crypto.RSA.pkcs1_oaep_padding) except M2Crypto.RSA.RSAError as rsae: raise exceptions.CryptoError(str(rsae))
def rsaDecrypt(self, message): self.__checkLocalKeypair() try: return self.localKeypair.private_decrypt( message, M2Crypto.RSA.pkcs1_oaep_padding) except M2Crypto.RSA.RSAError as rsae: raise exceptions.CryptoError(str(rsae))
def readLocalKeypairFromFile(self, file, passphrase): self._keypairPassphrase = passphrase try: self.localKeypair = M2Crypto.RSA.load_key( file, self.__passphraseCallback) except M2Crypto.RSA.RSAError as rsae: raise exceptions.CryptoError(str(rsae))
def setRemotePubKey(self, pubKey): if type(pubKey) is str: bio = M2Crypto.BIO.MemoryBuffer(pubKey) self.remoteKeypair = M2Crypto.RSA.load_pub_key_bio(bio) elif type(pubKey) is M2Crypto.RSA: self.remoteKeypair = pubKey else: raise exceptions.CryptoError("Public key is not a string or RSA key object.")
def step3(self, buffer): (g2b, g3b, pb, qb, c3, d3, c4, d4, c5, d5, d6) = unpackList(buffer) if not self.isValidArgument(g2b) or not self.isValidArgument(g3b) or \ not self.isValidArgument(pb) or not self.isValidArgument(qb): raise exceptions.CryptoError("Invalid g2b/g3b/pb/qb values", errors.ERR_SMP_CHECK_FAILED) if not self.checkLogProof('3', g2b, c3, d3): raise exceptions.CryptoError("Proof 3 check failed", errors.ERR_SMP_CHECK_FAILED) if not self.checkLogProof('4', g3b, c4, d4): raise exceptions.CryptoError("Proof 4 check failed", errors.ERR_SMP_CHECK_FAILED) self.g2b = g2b self.g3b = g3b self.ga2 = pow(self.g2b, self.x2, self.mod) self.ga3 = pow(self.g3b, self.x3, self.mod) if not self.checkCoordsProof('5', c5, d5, d6, self.ga2, self.ga3, pb, qb): raise exceptions.CryptoError("Proof 5 check failed", errors.ERR_SMP_CHECK_FAILED) s = createRandomExponent() self.qb = qb self.pb = pb self.pa = pow(self.ga3, s, self.mod) self.qa = mulm(pow(self.gen, s, self.mod), pow(self.ga2, self.secret, self.mod), self.mod) (c6, d7, d8) = self.createCoordsProof('6', self.ga2, self.ga3, s) inv = self.invm(qb) self.ra = pow(mulm(self.qa, inv, self.mod), self.x3, self.mod) (c7, d9) = self.createEqualLogsProof('7', self.qa, inv, self.x3) # Sends pa, qa, ra, c6, d7, d8, c7, d9 return packList(self.pa, self.qa, self.ra, c6, d7, d8, c7, d9)
def step2(self, buffer): (g2a, g3a, c1, d1, c2, d2) = unpackList(buffer) if not self.isValidArgument(g2a) or not self.isValidArgument(g3a): raise exceptions.CryptoError("Invalid g2a/g3a values", errors.ERR_SMP_CHECK_FAILED) if not self.checkLogProof('1', g2a, c1, d1): raise exceptions.CryptoError("Proof 1 check failed", errors.ERR_SMP_CHECK_FAILED) if not self.checkLogProof('2', g3a, c2, d2): raise exceptions.CryptoError("Proof 2 check failed", errors.ERR_SMP_CHECK_FAILED) self.g2a = g2a self.g3a = g3a self.x2 = createRandomExponent() self.x3 = createRandomExponent() r = createRandomExponent() self.g2 = pow(self.gen, self.x2, self.mod) self.g3 = pow(self.gen, self.x3, self.mod) (c3, d3) = self.createLogProof('3', self.x2) (c4, d4) = self.createLogProof('4', self.x3) self.gb2 = pow(self.g2a, self.x2, self.mod) self.gb3 = pow(self.g3a, self.x3, self.mod) self.pb = pow(self.gb3, r, self.mod) self.qb = mulm(pow(self.gen, r, self.mod), pow(self.gb2, self.secret, self.mod), self.mod) (c5, d5, d6) = self.createCoordsProof('5', self.gb2, self.gb3, r) # Sends g2b, g3b, pb, qb, all the c's and d's return packList(self.g2, self.g3, self.pb, self.qb, c3, d3, c4, d4, c5, d5, d6)
def generateAESKey(self, aesMode=constants.DEFAULT_AES_MODE): self.aesMode = aesMode # Generate the AES key and IV bitsString = aesMode[4:7] if bitsString == '128': self.aesBytes = 16 elif bitsString == '192': self.aesBytes = 24 elif bitsString == '256': self.aesBytes = 32 else: raise exceptions.CryptoError("Invalid AES mode") self.aesKey = M2Crypto.Rand.rand_bytes(self.aesBytes) self.aesIv = M2Crypto.Rand.rand_bytes(self.aesBytes) self.aesSalt = M2Crypto.Rand.rand_bytes(8)
def __checkSMP(self): if not self.smp.match: raise exceptions.CryptoError(errno=errors.ERR_SMP_MATCH_FAILED) return True
def __checkRemoteKeypair(self): if self.remoteKeypair is None: raise exceptions.CryptoError("Remote public key not set.")
def __checkLocalKeypair(self): if self.localKeypair is None: raise exceptions.CryptoError("Local keypair not set.")