def proof_equal_logs(self, v): r = bytes_to_long(RNG.read(192)) temp1 = pow(self.g1, r, DH1536_MODULUS) temp2 = pow(self.qab, r, DH1536_MODULUS) cb = SHA256(struct.pack(b'B', v) + pack_mpi(temp1) + pack_mpi(temp2)) c = bytes_to_long(cb) temp1 = self.x3 * c % SM_ORDER d = (r - temp1) % SM_ORDER return c, d
def gotSecret(self, secret, question=None, appdata=None): ourFP = self.crypto.ctx.user.getPrivkey().fingerprint() if self.state == 1: # first secret -> SMP1TLV combSecret = SHA256(b'\1' + ourFP + self.crypto.theirPubkey.fingerprint() + self.crypto.sessionId + secret) self.secret = bytes_to_long(combSecret) self.x2 = randrange(2, DH_MAX) self.x3 = randrange(2, DH_MAX) msg = [pow(self.g1, self.x2, DH_MODULUS)] msg += proof_known_log(self.g1, self.x2, 1) msg.append(pow(self.g1, self.x3, DH_MODULUS)) msg += proof_known_log(self.g1, self.x3, 2) self.prog = SMPPROG_OK self.state = 2 if question is None: self.sendTLV(proto.SMP1TLV(msg), appdata=appdata) else: self.sendTLV(proto.SMP1QTLV(question, msg), appdata=appdata) if self.state == 0: # response secret -> SMP2TLV combSecret = SHA256(b'\1' + self.crypto.theirPubkey.fingerprint() + ourFP + self.crypto.sessionId + secret) self.secret = bytes_to_long(combSecret) msg = [pow(self.g1, self.x2, DH_MODULUS)] msg += proof_known_log(self.g1, self.x2, 3) msg.append(pow(self.g1, self.x3, DH_MODULUS)) msg += proof_known_log(self.g1, self.x3, 4) r = randrange(2, DH_MAX) self.p = pow(self.g3, r, DH_MODULUS) msg.append(self.p) qb1 = pow(self.g1, r, DH_MODULUS) qb2 = pow(self.g2, self.secret, DH_MODULUS) self.q = qb1 * qb2 % DH_MODULUS msg.append(self.q) msg += self.proof_equal_coords(r, 5) self.state = 3 self.sendTLV(proto.SMP2TLV(msg), appdata=appdata)
def gotSecret(self, secret, question=None, appdata=None): ourFP = self.crypto.ctx.user.getPrivkey().fingerprint() if self.state == 1: # first secret -> SMP1TLV combSecret = HASH(b'\1' + ourFP + self.crypto.theirPubkey.fingerprint() + self.crypto.sessionId + secret) self.secret = bytes_to_long(combSecret) self.x2 = random.randrange(2, DH_MAX) self.x3 = random.randrange(2, DH_MAX) msg = [pow(self.g1, self.x2, DH_MODULUS)] msg += proof_known_log(self.g1, self.x2, 1) msg.append(pow(self.g1, self.x3, DH_MODULUS)) msg += proof_known_log(self.g1, self.x3, 2) self.prog = SMPPROG_OK self.state = 2 if question is None: self.sendTLV(proto.SMP1TLV(msg), appdata=appdata) else: self.sendTLV(proto.SMP1QTLV(question, msg), appdata=appdata) if self.state == 0: # response secret -> SMP2TLV combSecret = HASH(b'\1' + self.crypto.theirPubkey.fingerprint() + ourFP + self.crypto.sessionId + secret) self.secret = bytes_to_long(combSecret) msg = [pow(self.g1, self.x2, DH_MODULUS)] msg += proof_known_log(self.g1, self.x2, 3) msg.append(pow(self.g1, self.x3, DH_MODULUS)) msg += proof_known_log(self.g1, self.x3, 4) r = random.randrange(2, DH_MAX) self.p = pow(self.g3, r, DH_MODULUS) msg.append(self.p) qb1 = pow(self.g1, r, DH_MODULUS) qb2 = pow(self.g2, self.secret, DH_MODULUS) self.q = qb1 * qb2 % DH_MODULUS msg.append(self.q) msg += self.proof_equal_coords(r, 5) self.state = 3 self.sendTLV(proto.SMP2TLV(msg), appdata=appdata)
def parse(filename): """parse the otr.private_key S-Expression and return an OTR dict""" with open(filename, 'r') as f: data = ''.join(line for line in f.readlines()) sexplist = parse_sexp(data) keydict = dict() for sexpkey in sexplist: if sexpkey[0] == "account": key = dict() name = '' for element in sexpkey: # 'name' must be the first element in the sexp or BOOM! if element[0] == "name": if element[1].find('/') > -1: name, resource = element[1].split('/') else: name = element[1].strip() resource = '' key = dict() key['name'] = name.strip() key['resource'] = resource.strip() elif element[0] == "protocol": key['protocol'] = element[1] elif element[0] == "private-key": if element[1][0] == 'dsa': key['type'] = 'dsa' for num in element[1][1:6]: key[num[0]] = num[1] keytuple = (key['y'], key['g'], key['p'], key['q'], key['x']) key['dsakey'] = DSAKey(keytuple, private=True) key['fingerprint'] = '{0:040x}'.format(bytes_to_long(key['dsakey'].fingerprint())) keydict[name] = key return keydict
def handleDHKey(self, msg): if self.state == STATE_AWAITING_DHKEY: self.gy = bytes_to_long(msg.gy) # check 2 <= g**y <= p-2 if not check_group(self.gy): logger.error("Invalid g**y received: %r", self.gy) return self.createAuthKeys() aesxb = self.calculatePubkeyAuth(self.enc_c, self.mac_m1) self.state = STATE_AWAITING_SIG self.lastmsg = proto.RevealSig(self.r, aesxb, b"") self.lastmsg.mac = SHA256HMAC160(self.mac_m2, self.lastmsg.getMacedData()) return self.lastmsg elif self.state == STATE_AWAITING_SIG: logger.info("received DHKey while not awaiting DHKEY") if msg.gy == self.gy: logger.info("resending revealsig") return self.lastmsg else: logger.info("bad state for DHKey")
def proof_equal_coords(self, r, v): r1 = bytes_to_long(RNG.read(192)) r2 = bytes_to_long(RNG.read(192)) temp2 = pow(self.g1, r1, DH1536_MODULUS) \ * pow(self.g2, r2, DH1536_MODULUS) % DH1536_MODULUS temp1 = pow(self.g3, r1, DH1536_MODULUS) cb = SHA256(struct.pack(b'B', v) + pack_mpi(temp1) + pack_mpi(temp2)) c = bytes_to_long(cb) temp1 = r * c % SM_ORDER d1 = (r1-temp1) % SM_ORDER temp1 = self.secret * c % SM_ORDER d2 = (r2 - temp1) % SM_ORDER return c, d1, d2
def handleDHKey(self, msg): if self.state == STATE_AWAITING_DHKEY: self.gy = bytes_to_long(msg.gy) # check 2 <= g**y <= p-2 if not check_group(self.gy): logger.error('Invalid g**y received: %r', self.gy) return self.createAuthKeys() aesxb = self.calculatePubkeyAuth(self.enc_c, self.mac_m1) self.state = STATE_AWAITING_SIG self.lastmsg = proto.RevealSig(self.r, aesxb, b'') self.lastmsg.mac = SHA256HMAC160(self.mac_m2, self.lastmsg.getMacedData()) return self.lastmsg elif self.state == STATE_AWAITING_SIG: logger.info('received DHKey while not awaiting DHKEY') if msg.gy == self.gy: logger.info('resending revealsig') return self.lastmsg else: logger.info('bad state for DHKey')
def handleDHKey(self, msg): if self.state == STATE_AWAITING_DHKEY: self.gy = bytes_to_long(msg.gy) # check 2 <= g**y <= p-2 if not check_group(self.gy): logger.error('Invalid g**y received: %r', self.gy) return # Création de toutes les clés self.createAuthKeys() aesxb = self.calculatePubkeyAuth(self.enc_c, self.mac_m1) self.state = STATE_AWAITING_SIG self.lastmsg = proto.RevealSig(self.r, aesxb, b'') self.lastmsg.mac = SHA256HMAC160(self.mac_m2, self.lastmsg.getMacedData()) # Message envoyé : (r, AES(Xb), MAC(AES(XB))) return self.lastmsg elif self.state == STATE_AWAITING_SIG: logger.info('received DHKey while not awaiting DHKEY') if msg.gy == self.gy: logger.info('resending revealsig') return self.lastmsg else: logger.info('bad state for DHKey')
def proof_equal_logs(self, v): r = randrange(2, DH_MAX) temp1 = pow(self.g1, r, DH_MODULUS) temp2 = pow(self.qab, r, DH_MODULUS) cb = SHA256(struct.pack(b'B', v) + pack_mpi(temp1) + pack_mpi(temp2)) c = bytes_to_long(cb) temp1 = self.x3 * c % SM_ORDER d = (r - temp1) % SM_ORDER return c, d
def handleDataMessage(self, msg): if self.saneKeyIds(msg) is False: raise InvalidParameterError sesskey = self.sessionkeys[self.ourKeyid - msg.rkeyid] \ [self.theirKeyid - msg.skeyid] logger.debug('sesskeys: {0!r}, our={1}, r={2}, their={3}, s={4}' \ .format(self.sessionkeys, self.ourKeyid, msg.rkeyid, self.theirKeyid, msg.skeyid)) if msg.mac != SHA1HMAC(sesskey.rcvmac, msg.getMacedData()): logger.error('HMACs don\'t match') raise InvalidParameterError sesskey.rcvmacused = True newCtrPrefix = bytes_to_long(msg.ctr) if newCtrPrefix <= sesskey.rcvctr.prefix: logger.error('CTR must increase (old %r, new %r)', sesskey.rcvctr.prefix, newCtrPrefix) raise InvalidParameterError sesskey.rcvctr.prefix = newCtrPrefix logger.debug('handle: enc={0!r} mac={1!r} ctr={2!r}' \ .format(sesskey.rcvenc, sesskey.rcvmac, sesskey.rcvctr)) plaintextData = AESCTR(sesskey.rcvenc, sesskey.rcvctr) \ .decrypt(msg.encmsg) if b'\0' in plaintextData: plaintext, tlvData = plaintextData.split(b'\0', 1) tlvs = proto.TLV.parse(tlvData) else: plaintext = plaintextData tlvs = [] if msg.rkeyid == self.ourKeyid: self.rotateDHKeys() if msg.skeyid == self.theirKeyid: self.rotateYKeys(bytes_to_long(msg.dhy)) return plaintext, tlvs
def proof_equal_logs(self, v): r = random.randrange(2, DH_MAX) temp1 = pow(self.g1, r, DH_MODULUS) temp2 = pow(self.qab, r, DH_MODULUS) cb = HASH(struct.pack(b'B', v) + pack_mpi(temp1) + pack_mpi(temp2)) c = bytes_to_long(cb) temp1 = self.x3 * c % SM_ORDER d = (r - temp1) % SM_ORDER return c, d
def proof_equal_coords(self, r, v): r1 = random.randrange(2, DH_MAX) r2 = random.randrange(2, DH_MAX) temp2 = pow(self.g1, r1, DH_MODULUS) * pow(self.g2, r2, DH_MODULUS) % DH_MODULUS temp1 = pow(self.g3, r1, DH_MODULUS) cb = SHA256(struct.pack(b"B", v) + pack_mpi(temp1) + pack_mpi(temp2)) c = bytes_to_long(cb) temp1 = r * c % SM_ORDER d1 = (r1 - temp1) % SM_ORDER temp1 = self.secret * c % SM_ORDER d2 = (r2 - temp1) % SM_ORDER return c, d1, d2
def proof_equal_coords(self, r, v): r1 = randrange(2, DH_MAX) r2 = randrange(2, DH_MAX) temp2 = pow(self.g1, r1, DH_MODULUS) \ * pow(self.g2, r2, DH_MODULUS) % DH_MODULUS temp1 = pow(self.g3, r1, DH_MODULUS) cb = SHA256(struct.pack(b'B', v) + pack_mpi(temp1) + pack_mpi(temp2)) c = bytes_to_long(cb) temp1 = r * c % SM_ORDER d1 = (r1-temp1) % SM_ORDER temp1 = self.secret * c % SM_ORDER d2 = (r2 - temp1) % SM_ORDER return c, d1, d2
def fingerprint(key): '''generate the human readable form of the fingerprint as used in OTR''' return '{0:040x}'.format(bytes_to_long(DSAKey(key).fingerprint()))
def cfingerprint(self): return '{0:040x}'.format(bytes_to_long(self.fingerprint()))
def verify(self, data, sig): r, s = bytes_to_long(sig[:20]), bytes_to_long(sig[20:]) return self.pub.verify(data, (r, s))
def __hash__(self): return bytes_to_long(self.fingerprint())
def proof_known_log(g, x, v): r = bytes_to_long(RNG.read(192)) c = bytes_to_long(SHA256(struct.pack(b'B', v) + pack_mpi(pow(g, r, DH1536_MODULUS)))) temp = x * c % SM_ORDER return c, (r-temp) % SM_ORDER
def sign(self, data): # 2 <= K <= q = 160bit = 20 byte K = bytes_to_long(RNG.read(19)) + 2 r, s = self.priv.sign(data, K) return long_to_bytes(r) + long_to_bytes(s)
def proof_known_log(g, x, v): r = randrange(2, DH_MAX) c = bytes_to_long(SHA256(struct.pack(b'B', v) + pack_mpi(pow(g, r, DH_MODULUS)))) temp = x * c % SM_ORDER return c, (r-temp) % SM_ORDER
def proof_known_log(g, x, v): r = random.randrange(2, DH_MAX) c = bytes_to_long(HASH(struct.pack(b'B', v) + pack_mpi(pow(g, r, DH_MODULUS)))) temp = x * c % SM_ORDER return c, (r-temp) % SM_ORDER
def handle(self, tlv, appdata=None): logger.debug('handling TLV {0.__class__.__name__}'.format(tlv)) self.prog = SMPPROG_CHEATED if isinstance(tlv, proto.SMPABORTTLV): self.state = 1 return is1qTlv = isinstance(tlv, proto.SMP1QTLV) if isinstance(tlv, proto.SMP1TLV) or is1qTlv: if self.state != 1: self.abort(appdata=appdata) return msg = tlv.mpis if not check_group(msg[0]) or not check_group(msg[3]) \ or not check_exp(msg[2]) or not check_exp(msg[5]) \ or not check_known_log(msg[1], msg[2], self.g1, msg[0], 1) \ or not check_known_log(msg[4], msg[5], self.g1, msg[3], 2): logger.error('invalid SMP1TLV received') self.abort(appdata=appdata) return self.questionReceived = is1qTlv self.g3o = msg[3] self.x2 = bytes_to_long(RNG.read(192)) self.x3 = bytes_to_long(RNG.read(192)) self.g2 = pow(msg[0], self.x2, DH1536_MODULUS) self.g3 = pow(msg[3], self.x3, DH1536_MODULUS) self.prog = SMPPROG_OK self.state = 0 return if isinstance(tlv, proto.SMP2TLV): if self.state != 2: self.abort(appdata=appdata) return msg = tlv.mpis mp = msg[6] mq = msg[7] if not check_group(msg[0]) or not check_group(msg[3]) \ or not check_group(msg[6]) or not check_group(msg[7]) \ or not check_exp(msg[2]) or not check_exp(msg[5]) \ or not check_exp(msg[9]) or not check_exp(msg[10]) \ or not check_known_log(msg[1], msg[2], self.g1, msg[0], 3) \ or not check_known_log(msg[4], msg[5], self.g1, msg[3], 4): logger.error('invalid SMP2TLV received') self.abort(appdata=appdata) return self.g3o = msg[3] self.g2 = pow(msg[0], self.x2, DH1536_MODULUS) self.g3 = pow(msg[3], self.x3, DH1536_MODULUS) if not self.check_equal_coords(msg[6:11], 5): logger.error('invalid SMP2TLV received') self.abort(appdata=appdata) return r = bytes_to_long(RNG.read(192)) self.p = pow(self.g3, r, DH1536_MODULUS) msg = [self.p] qa1 = pow(self.g1, r, DH1536_MODULUS) qa2 = pow(self.g2, self.secret, DH1536_MODULUS) self.q = qa1*qa2 % DH1536_MODULUS msg.append(self.q) msg += self.proof_equal_coords(r, 6) inv = invMod(mp) self.pab = self.p * inv % DH1536_MODULUS inv = invMod(mq) self.qab = self.q * inv % DH1536_MODULUS msg.append(pow(self.qab, self.x3, DH1536_MODULUS)) msg += self.proof_equal_logs(7) self.state = 4 self.prog = SMPPROG_OK self.sendTLV(proto.SMP3TLV(msg), appdata=appdata) return if isinstance(tlv, proto.SMP3TLV): if self.state != 3: self.abort(appdata=appdata) return msg = tlv.mpis if not check_group(msg[0]) or not check_group(msg[1]) \ or not check_group(msg[5]) or not check_exp(msg[3]) \ or not check_exp(msg[4]) or not check_exp(msg[7]) \ or not self.check_equal_coords(msg[:5], 6): logger.error('invalid SMP3TLV received') self.abort(appdata=appdata) return inv = invMod(self.p) self.pab = msg[0] * inv % DH1536_MODULUS inv = invMod(self.q) self.qab = msg[1] * inv % DH1536_MODULUS if not self.check_equal_logs(msg[5:8], 7): logger.error('invalid SMP3TLV received') self.abort(appdata=appdata) return md = msg[5] msg = [pow(self.qab, self.x3, DH1536_MODULUS)] msg += self.proof_equal_logs(8) rab = pow(md, self.x3, DH1536_MODULUS) self.prog = SMPPROG_SUCCEEDED if self.pab == rab else SMPPROG_FAILED if self.prog != SMPPROG_SUCCEEDED: logger.error('secrets don\'t match') self.abort(appdata=appdata) self.crypto.ctx.setCurrentTrust('') return logger.info('secrets matched') if not self.questionReceived: self.crypto.ctx.setCurrentTrust('smp') self.state = 1 self.sendTLV(proto.SMP4TLV(msg), appdata=appdata) return if isinstance(tlv, proto.SMP4TLV): if self.state != 4: self.abort(appdata=appdata) return msg = tlv.mpis if not check_group(msg[0]) or not check_exp(msg[2]) \ or not self.check_equal_logs(msg[:3], 8): logger.error('invalid SMP4TLV received') self.abort(appdata=appdata) return rab = pow(msg[0], self.x3, DH1536_MODULUS) self.prog = SMPPROG_SUCCEEDED if self.pab == rab else SMPPROG_FAILED if self.prog != SMPPROG_SUCCEEDED: logger.error('secrets don\'t match') self.abort(appdata=appdata) self.crypto.ctx.setCurrentTrust('') return logger.info('secrets matched') self.crypto.ctx.setCurrentTrust('smp') self.state = 1 return
def __init__(self): self.priv = bytes_to_long(RNG.read(40)) self.pub = pow(self.gen, self.priv, self.prime)