def try_skipped_keys(self, hcrypt, hnonce, mcrypt, mnonce): for mk, hkr in self.skipped_HK_MK.items(): try: nacl.crypto_secretbox_open(hcrypt, hnonce, hkr) except: continue try: msg = nacl.crypto_secretbox_open(mcrypt, mnonce, mk) except: continue del self.skipped_HK_MK[mk] return msg
def decrypt(self, cipher, nonce): if self.in_k == (b'\0' * nacl.crypto_scalarmult_curve25519_BYTES): # use pk crypto to decrypt the packet return nacl.crypto_box_open(cipher, nonce, self.peer_id.cp, self.me_id.cs) else: # decrypt using chained keys try: return nacl.crypto_secretbox_open(cipher, nonce, self.in_k) except ValueError: # with previous key in case a prev send failed to be delivered return nacl.crypto_secretbox_open(cipher, nonce, self.in_prev)
def data_received(self, data): if verbose: print('Data received: ', data) try: data = pysodium.crypto_sign_open(data, self.handler.getserverkey()) except ValueError: raise ValueError('invalid signature.\nabort') if data!=b'ok' and (data[:-42] == b'fail' or len(data)!=sphinxlib.DECAF_255_SER_BYTES+42): raise ValueError('fail') if not self.b: self.cb() return rwd=sphinxlib.finish(self.pwd, self.b, data[:sphinxlib.DECAF_255_SER_BYTES]) if self.handler.namesite is not None: if self.handler.namesite['name'].encode() not in self.handler.list(self.handler.namesite['site']): self.handler.cacheuser(self.handler.namesite) rule = data[sphinxlib.DECAF_255_SER_BYTES:] if len(rule)!=42: raise ValueError('fail') rk = pysodium.crypto_generichash(self.handler.getkey(),self.handler.getsalt()) rule = pysodium.crypto_secretbox_open(rule[24:], rule[:24],rk) rule = struct.unpack(">H",rule)[0] size = (rule & 0x7f) rule = {c for i,c in enumerate(('u','l','s','d')) if (rule >> 7) & (1 << i)} self.cb(bin2pass.derive(rwd,rule,size).decode())
def decrypt(pkt, pwd=None, k=None, retries=3): # decrypts a message symmetrically using crypto_secretbox # pkt is a (nonce, ciphertext) tuple # k specifies an encryption key, which if not supplied, is derived from # pwd which is queried from the user, if also not specified. clearpwd = (pwd is None) cleark = (k is None) cnt = 0 res = None while cnt < retries: if not k: if not pwd: pwd = getpass.getpass('\nPassphrase for decrypting: ') k = scrypt.hash(pwd, scrypt_salt)[:nacl.crypto_secretbox_KEYBYTES] if clearpwd: clearmem(pwd) pwd = None try: res = nacl.crypto_secretbox_open(pkt[1], pkt[0], k) except ValueError: cnt += 1 if cleark: clearmem(k) k = None continue break if cleark and k: clearmem(k) k = None if res: return res
def decrypt(pkt, pwd=None, k=None, retries=3): # decrypts a message symmetrically using crypto_secretbox # pkt is a (nonce, ciphertext) tuple # k specifies an encryption key, which if not supplied, is derived from # pwd which is queried from the user, if also not specified. cleark = (pwd is None) clearpwd = (k is None) cnt=0 res = None while cnt<retries: if not k: if not pwd: pwd = getpass.getpass('\nPassphrase for decrypting: ') k = scrypt.hash(pwd, scrypt_salt)[:nacl.crypto_secretbox_KEYBYTES] if clearpwd: clearmem(pwd) pwd = None try: res = nacl.crypto_secretbox_open(pkt[1], pkt[0], k) except ValueError: cnt += 1 if cleark: clearmem(k) k = None continue break if cleark: clearmem(k) if res: return res
def decrypt_with_user_pw(self, filename, pw_for): with open(filename, 'rb') as fd: nonce = fd.read(nacl.crypto_secretbox_NONCEBYTES) prompt = 'Passphrase for decrypting {0} for {1}: '.format( pw_for, self.name) k = scrypt.hash(getpass.getpass(prompt), pbp.scrypt_salt)[:nacl.crypto_secretbox_KEYBYTES] return nacl.crypto_secretbox_open(fd.read(), nonce, k)
def decrypt_blob(blob): # todo implement padding sk = get_sealkey() nonce = blob[:pysodium.crypto_secretbox_NONCEBYTES] blob = blob[pysodium.crypto_secretbox_NONCEBYTES:] res = pysodium.crypto_secretbox_open(blob, nonce, sk) clearmem(sk) return res
def __decrypt(self, encrypted): keyFile = open('logo', 'r') key = base64.b64decode(keyFile.read()) keyFile.close() decoded = base64.b64decode(encrypted) nonce = decoded[:pysodium.crypto_secretbox_NONCEBYTES] ciph = decoded[pysodium.crypto_secretbox_NONCEBYTES:] return pysodium.crypto_secretbox_open(ciph, nonce, key).decode()
def open(self, nut): '''decrypt and verify the integrity of a nut returned by a client returns the original nut passed to seal ''' box = urlsafe_b64decode(nut) nonce = box[:na.crypto_secretbox_NONCEBYTES] ct = box[na.crypto_secretbox_NONCEBYTES:] pt = na.crypto_secretbox_open(ct, nonce, self.__key) return Nut(*self.NUTBOX.unpack(pt))
def scrypt_decrypt(data, password): buf = io.BytesIO(data) memlimit = int.from_bytes(buf.read(4), "little") opslimit = int.from_bytes(buf.read(4), "little") salt = buf.read(pysodium.crypto_pwhash_scryptsalsa208sha256_SALTBYTES) if isinstance(password, str): password = password.encode("utf-8") key = pysodium.crypto_pwhash_scryptsalsa208sha256(pysodium.crypto_secretbox_KEYBYTES, password, salt, memlimit, opslimit) nonce = buf.read(pysodium.crypto_secretbox_NONCEBYTES) cyphertext = buf.read() return pysodium.crypto_secretbox_open(cyphertext, nonce, key)
def decrypt_message(bytes_, key, pubkeyhash): version, nonce, encrypted = outer_pack.unpack(bytes_) decrypted = pysodium.crypto_secretbox_open(encrypted, nonce, key) decrypted_record = parse_innerbox(decrypted) if not validate_pubkey(decrypted_record.pubkey, pubkeyhash): raise PubkeyError() if version != decrypted_record.inner_ver: # The version on the outside doesn't match the version that the other # end signed! raise SignatureError() return decrypted_record
def decode(self, jdata): """ Decode message using libsodium :param str jdata: jdata to load :return: the Encoded message """ ckmsg = self.loads(jdata) return Message.loads( pysodium.crypto_secretbox_open( base64.b64decode(ckmsg["data"]), base64.b64decode(ckmsg["nonce"]), base64.b64decode(self.secretbox_key)).decode('utf-8'))
def session_input (_inbound_key, _inbound_nonce, _encrypted) : pysodium.sodium_increment (_inbound_nonce) log ("[8408f904]", "[crypto][input]", "using nonce `%s`;", _inbound_nonce.encode ("b64")) log ("[62fc5bf5]", "[crypto][input]", "decoding packet (encrypted) `%s`...", _encrypted.encode ("b64")) _packet = pysodium.crypto_secretbox_open (_encrypted, _inbound_nonce, _inbound_key) log ("[7eeb53a0]", "[crypto][input]", "decoded packet (plain) `%s`;", _packet.encode ("b64")) return _packet
def decrypt(pkt, pwd=None, basedir=None, k=None): # symmetric cleark = (pwd is None) clearpwd = (k is None) if not k: if not pwd: pwd = getpass.getpass('Passphrase for decrypting: ') k = scrypt.hash(pwd, scrypt_salt)[:nacl.crypto_secretbox_KEYBYTES] if clearpwd: clearmem(pwd) res = nacl.crypto_secretbox_open(pkt[1], pkt[0], k) if cleark: clearmem(k) return res
def unlock_private_key(private_key): private_key = base64.b64decode(private_key) if private_key[0] == b'y': sbytes = pysodium.crypto_pwhash_SALTBYTES nbytes = pysodium.crypto_box_NONCEBYTES salt = private_key[1:sbytes+1] nonce = private_key[sbytes+1: sbytes+nbytes+1] cyphertext = private_key[sbytes+nbytes+1:] key = hash_password(getpass.getpass(), salt) private_key = pysodium.crypto_secretbox_open(cyphertext, nonce, key) return private_key return private_key[1:]
def unlock_private_key(private_key_b64: str) -> bytes: private_key: bytes = base64.b64decode(private_key_b64) if private_key[0] == b'y': sbytes: int = pysodium.crypto_pwhash_SALTBYTES nbytes: int = pysodium.crypto_box_NONCEBYTES salt: bytes = private_key[1:sbytes + 1] nonce: bytes = private_key[sbytes + 1:sbytes + nbytes + 1] cyphertext: bytes = private_key[sbytes + nbytes + 1:] key: bytes = hash_password(getpass.getpass(), salt) private_key = pysodium.crypto_secretbox_open(cyphertext, nonce, key) return private_key else: return private_key[1:]
def decrypt_keys(self, topic, msgval=None): if (isinstance(topic,(bytes,bytearray))): self._logger.debug("passed a topic in bytes (should be string)") topic = topic.decode('utf-8') # # msgval should be a msgpacked chain. # The public key in the array is a set of public key(s) to combine with our # encryption key to get the secret to decrypt the key. If we do not # have an encryption key for the topic, we cannot do it until we have one. # The next item is then the pair of random values for generating the shared # secret, followed by the actual key message. # try: with self.__allowdenylist_lock: pk,pkprint = process_chain(msgval,topic,'key-encrypt',allowlist=self.__allowlist,denylist=self.__denylist) if (len(pk) < 5): if not (pkprint is None): raise ProcessChainError("Unexpected number of chain elements:", pkprint) else: raise ValueError("Unexpected number of chain elements!") random0 = pk[3][0] random1 = pk[3][1] nonce = pk[4][0:pysodium.crypto_secretbox_NONCEBYTES] msg = pk[4][pysodium.crypto_secretbox_NONCEBYTES:] eks = self.__cryptokey.use_epk(topic, 'decrypt_keys', pk[2], clear=False) for ck in eks: # Construct candidate shared secrets as sha256(topic || random0 || random1 || our_private*their_public) ss = pysodium.crypto_hash_sha256(topic.encode('utf-8') + random0 + random1 + ck)[0:pysodium.crypto_secretbox_KEYBYTES] # decrypt and return key try: msg = msgpack.unpackb(pysodium.crypto_secretbox_open(msg,nonce,ss),raw=True) rvs = {} for i in range(0,len(msg),2): rvs[msg[i]] = msg[i+1] if len(rvs) < 1 or 2*len(rvs) != len(msg): raise ValueError except: pass else: # clear the esk/epk we just used self.__cryptokey.use_epk(topic, 'decrypt_keys', []) return rvs raise ValueError except Exception as e: self._logger.warning("".join(format_exception_shim(e))) pass return None
def from_encoded_key(cls, key, passphrase=''): """ Creates a key object from a base58 encoded key. :param key: a public or secret key in base58 encoding :param passphrase: the passphrase used if the key provided is an encrypted private key """ key = scrub_input(key) curve = key[:2] # "sp", "p2" "ed" if curve not in [b'sp', b'p2', b'ed']: raise ValueError("Invalid prefix for a key encoding.") if not len(key) in [54, 55, 88, 98]: raise ValueError("Invalid length for a key encoding.") encrypted = (key[2:3] == b'e') public_or_secret = key[3:5] if encrypted else key[2:4] if public_or_secret not in [b'pk', b'sk']: raise Exception("Invalid prefix for a key encoding.") key = base58_decode(key) is_secret = (public_or_secret == b'sk') if not is_secret: return cls.from_public_point(key, curve) if encrypted: if not passphrase: raise ValueError( "Encrypted key provided without a passphrase.") if isinstance(passphrase, str): passphrase = passphrase.encode() assert isinstance( passphrase, bytes ), f'expected bytes or str, got {type(passphrase).__name__}' salt, encrypted_sk = key[:8], key[8:] encryption_key = hashlib.pbkdf2_hmac(hash_name="sha512", password=passphrase, salt=salt, iterations=32768, dklen=32) key = pysodium.crypto_secretbox_open(c=encrypted_sk, nonce=b'\000' * 24, k=encryption_key) del passphrase return cls.from_secret_exponent(key, curve)
def from_encoded_key( cls, key: Union[str, bytes], passphrase: PassphraseInput = None, ) -> 'Key': """Creates a key object from a base58 encoded key. :param key: a public or secret key in base58 encoding :param passphrase: the passphrase used if the key provided is an encrypted private key, if not set value from from PYTEZOS_PASSPHRASE env variable will be used or promted dynamically """ encoded_key = scrub_input(key) curve = encoded_key[:2] # "sp", "p2" "ed" if curve not in [b'sp', b'p2', b'ed']: raise ValueError("Invalid prefix for a key encoding.") if not len(encoded_key) in [54, 55, 88, 98]: raise ValueError("Invalid length for a key encoding.") encrypted = encoded_key[2:3] == b'e' public_or_secret = encoded_key[3:5] if encrypted else encoded_key[2:4] if public_or_secret not in [b'pk', b'sk']: raise Exception("Invalid prefix for a key encoding.") encoded_key = base58_decode(encoded_key) is_secret = public_or_secret == b'sk' if not is_secret: return cls.from_public_point(encoded_key, curve) if encrypted: passphrase = get_passphrase(passphrase) salt, encrypted_sk = encoded_key[:8], encoded_key[8:] encryption_key = hashlib.pbkdf2_hmac(hash_name="sha512", password=passphrase, salt=salt, iterations=32768, dklen=32) encoded_key = pysodium.crypto_secretbox_open( c=encrypted_sk, nonce=b'\000' * 24, k=encryption_key, ) del passphrase return cls.from_secret_exponent(encoded_key, curve)
def test_destructure_decrypt_decode_verbose(self): """ Strictly verify the content and behaviour of the serializer, and how the encryption functions are used. """ encrypted = self.obj.dumps(SESSION).encode('utf-8') dec = urlsafe_b64decode(encrypted) key = crypto_generichash(app.secret_key, outlen=crypto_secretbox_KEYBYTES) n = dec[:crypto_secretbox_NONCEBYTES] c = dec[crypto_secretbox_NONCEBYTES:] m = crypto_secretbox_open(c, n, key) session = self.obj.serializer.loads(m) assert session[self.obj.timestamp_key] del session[self.obj.timestamp_key] assert SESSION == session
def decrypt_with_user_pw(self, filename, pw_for): with file(filename) as fd: nonce = fd.read(nacl.crypto_secretbox_NONCEBYTES) prompt = 'Passphrase for decrypting {0} for {1}: '.format(pw_for, self.name) k = scrypt.hash(getpass.getpass(prompt), pbp.scrypt_salt)[:nacl.crypto_secretbox_KEYBYTES] return nacl.crypto_secretbox_open(fd.read(), nonce, k)
def decrypt(self, pkt): peer, key = self.keydecrypt(pkt[1]) if key: return peer, nacl.crypto_secretbox_open(pkt[2], pkt[0], key)
def run_server(): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((server_ip, server_port)) log('[INFO] Listening on '+server_ip+':'+str(server_port)) # NONCE(24) + MAC(16) + MAGIC(8) + SIGNPUB(32) + SIG(64) + COUNTER(14) + LEN(2) + REST PROTO_MIN_SIZE = 160 magic_bin = '42f9708e2f1369d9'.decode('hex') # chosen by fair die server_ip_bin = socket.inet_aton(server_ip) # FIXME: lock state file for duration of the program counter = read_counter() while True: try: client_ip, client_port = (None, None) cdata, (client_ip, client_port) = sock.recvfrom(1024) if len(cdata) < PROTO_MIN_SIZE: # normal: a UDP scan would cause this log('[INFO] small packet', client_ip, client_port) continue pkt_nonce = cdata[:pysodium.crypto_secretbox_NONCEBYTES] try: plain = pysodium.crypto_secretbox_open(cdata[pysodium.crypto_secretbox_NONCEBYTES:], pkt_nonce, server_private_key) except: # normal-ish: any big enough packet to the port will cause # this, but unless knockd happens to run on a common UDP # port there's not much reason to see such a big packet log('[INFO] incorrect ciphertext', client_ip, client_port) continue pkt_magic = plain[:8] plain = plain[8:] if pkt_magic != magic_bin: # unrecognised protocol version log('[WARN] unrecognised version magic', client_ip, client_port, pkt_magic.encode('hex')) continue pkt_sign_pub = plain[:32] plain = plain[32:] if pkt_sign_pub not in client_sign_keys: log('[WARN] unrecognised client sign key', client_ip, client_port, pkt_sign_pub.encode('hex')) continue pkt_sig = plain[:64] plain = plain[64:] pkt_counter_bin = plain[:14] pkt_counter = int(pkt_counter_bin.encode('hex'), 16) plain = plain[14:] # check counter early so we don't need to verify replays if pkt_counter <= counter: log('[POSSIBLE_REPLAY] bad counter', client_ip, client_port) continue try: pysodium.crypto_sign_verify_detached(pkt_sig, (pkt_nonce + magic_bin + pkt_sign_pub + pkt_counter_bin + plain + server_private_key + server_ip_bin), pkt_sign_pub) except: # shenanigans, the data isn't signed by that user log('[SEVERE] bad signature', client_ip, client_port) continue pkt_data_len_bin = plain[:2] pkt_data_len = int(pkt_data_len_bin.encode('hex'), 16) plain = plain[2:] pkt_data = plain[:pkt_data_len] # Cool, write that counter ASAP so the packet can't be used again counter = pkt_counter write_counter(counter) log('[INFO] valid knock', client_ip, client_port) # NB. do *not* trust that client_ip is the originator (beyond # port knocking functionality). A person who can perform # packet captures can race the packet from their own IP subprocess.Popen([knocked_command, client_ip, pkt_data]) except KeyboardInterrupt: break except Exception as e: log('[ERROR] packet exception', client_ip, client_port, e)
def decrypt(self, m): n = m[:crypto_secretbox_NONCEBYTES] c = m[crypto_secretbox_NONCEBYTES:] return crypto_secretbox_open(c, n, self.key)
def recv(self, msg): """ as per https://github.com/trevp/axolotl/wiki/newversion (Nov 19, 2013 · 41 revisions) Receiving messages ------------------- Local variables: MK : message key Np : Purported message number PNp : Purported previous message number CKp : Purported new chain key DHp : Purported new DHr RKp : Purported new root key NHKp, HKp : Purported new header keys if (plaintext = try_skipped_header_and_message_keys()): return plaintext if Dec(HKr, header): Np = read() CKp, MK = stage_skipped_header_and_message_keys(HKr, Nr, Np, CKr) if not Dec(MK, ciphertext): raise undecryptable if bobs_first_message: DHRr = read() RK = HASH(RK || ECDH(DHRs, DHRr)) HKs = NHKs NHKs, CKs = KDF(RK) erase(DHRs) bobs_first_message = False else: if not Dec(NHKr, header): raise undecryptable() Np, PNp, DHRp = read() stage_skipped_header_and_message_keys(HKr, Nr, PNp, CKr) RKp = HASH(RK || ECDH(DHRs, DHRr)) HKp = NHKr NHKp, CKp = KDF(RKp) CKp, MK = stage_skipped_header_and_message_keys(HKp, 0, Np, CKp) if not Dec(MK, ciphertext): raise undecryptable() RK = RKp HKr = HKp NHKr = NHKp DHRr = DHRp RK = HASH(RK || ECDH(DHRs, DHRr)) HKs = NHKs NHKs, CKs = KDF(RK) erase(DHRs) commit_skipped_header_and_message_keys() Nr = Np + 1 CKr = CKp return read() """ hnonce = msg[:nacl.crypto_secretbox_NONCEBYTES] i = nacl.crypto_secretbox_NONCEBYTES mnonce = msg[i:i+nacl.crypto_secretbox_NONCEBYTES] i += nacl.crypto_secretbox_NONCEBYTES hcrypt = msg[i:i + nacl.crypto_secretbox_MACBYTES + 4 + 4 + nacl.crypto_scalarmult_curve25519_BYTES] i += nacl.crypto_secretbox_MACBYTES + 4 + 4 + nacl.crypto_scalarmult_curve25519_BYTES mcrypt = msg[i:] ret = self.try_skipped_keys(hcrypt, hnonce, mcrypt, mnonce) if ret: return ret headers = None try: headers = nacl.crypto_secretbox_open(hcrypt, hnonce, self.HKr) except: pass if headers: Np = struct.unpack('>I',headers[:4])[0] CKp, MK = self.stage_skipped_keys(self.HKr, self.Nr, Np, self.CKr) msg = nacl.crypto_secretbox_open(mcrypt, mnonce, MK) if self.bobs1stmsg: self.DHRr = headers[8:] self.RK = nacl.crypto_generichash(self.RK, nacl.crypto_scalarmult_curve25519(self.DHRs.sk,self.DHRr), KEY_SIZE) self.HKs = self.NHKs if self.isalice: self.NHKs = nacl.crypto_generichash(self.RK, "NHKs", KEY_SIZE) self.CKs = nacl.crypto_generichash(self.RK, "CKs", KEY_SIZE) else: self.NHKs = nacl.crypto_generichash(self.RK, "NHKr", KEY_SIZE) self.CKs = nacl.crypto_generichash(self.RK, "CKr", KEY_SIZE) self.DHRs.clear() self.DHRs = None self.bobs1stmsg = False else: headers = nacl.crypto_secretbox_open(hcrypt, hnonce, self.NHKr) #unpack header fields Np = struct.unpack('>I',headers[:4])[0] PNp = struct.unpack('>I',headers[4:8])[0] DHRp = headers[8:] self.stage_skipped_keys(self.HKr, self.Nr, PNp, self.CKr) RKp = nacl.crypto_generichash(self.RK, nacl.crypto_scalarmult_curve25519(self.DHRs.sk,self.DHRr), KEY_SIZE) HKp = self.NHKr if self.isalice: NHKp = nacl.crypto_generichash(RKp, "NHKr", KEY_SIZE) CKp = nacl.crypto_generichash(RKp, "CKr", KEY_SIZE) else: NHKp = nacl.crypto_generichash(RKp, "NHKs", KEY_SIZE) CKp = nacl.crypto_generichash(RKp, "CKs", KEY_SIZE) CKp, MK = self.stage_skipped_keys(HKp, 0, Np, CKp) msg = nacl.crypto_secretbox_open(mcrypt, mnonce, MK) self.RK = RKp self.HKr = HKp self.NHKr = NHKp self.DHRr = DHRp self.RK = nacl.crypto_generichash(self.RK, nacl.crypto_scalarmult_curve25519(self.DHRs.sk,self.DHRr), KEY_SIZE) self.HKs = self.NHKs if self.isalice: self.NHKs = nacl.crypto_generichash(self.RK, "NHKs", KEY_SIZE) self.CKs = nacl.crypto_generichash(self.RK, "CKs", KEY_SIZE) else: self.NHKs = nacl.crypto_generichash(self.RK, "NHKr", KEY_SIZE) self.CKs = nacl.crypto_generichash(self.RK, "CKr", KEY_SIZE) self.DHRs.clear() self.DHRs = None # commit_skipped_header_and_message_keys() : Commits any skipped-over message keys from the # staging area to persistent storage (along with their associated header keys). self.skipped_HK_MK.update(self.staged_HK_MK) self.staged_HK_MK = {} self.Nr = Np + 1 self.CKr = CKp return msg
def recv(self, msg): """ as per https://github.com/trevp/axolotl/wiki/newversion (Nov 19, 2013 · 41 revisions) Receiving messages ------------------- Local variables: MK : message key Np : Purported message number PNp : Purported previous message number CKp : Purported new chain key DHp : Purported new DHr RKp : Purported new root key NHKp, HKp : Purported new header keys if (plaintext = try_skipped_header_and_message_keys()): return plaintext if Dec(HKr, header): Np = read() CKp, MK = stage_skipped_header_and_message_keys(HKr, Nr, Np, CKr) if not Dec(MK, ciphertext): raise undecryptable if bobs_first_message: DHRr = read() RK = HASH(RK || ECDH(DHRs, DHRr)) HKs = NHKs NHKs, CKs = KDF(RK) erase(DHRs) bobs_first_message = False else: if not Dec(NHKr, header): raise undecryptable() Np, PNp, DHRp = read() stage_skipped_header_and_message_keys(HKr, Nr, PNp, CKr) RKp = HASH(RK || ECDH(DHRs, DHRr)) HKp = NHKr NHKp, CKp = KDF(RKp) CKp, MK = stage_skipped_header_and_message_keys(HKp, 0, Np, CKp) if not Dec(MK, ciphertext): raise undecryptable() RK = RKp HKr = HKp NHKr = NHKp DHRr = DHRp RK = HASH(RK || ECDH(DHRs, DHRr)) HKs = NHKs NHKs, CKs = KDF(RK) erase(DHRs) commit_skipped_header_and_message_keys() Nr = Np + 1 CKr = CKp return read() """ hnonce = msg[:nacl.crypto_secretbox_NONCEBYTES] i = nacl.crypto_secretbox_NONCEBYTES mnonce = msg[i:i + nacl.crypto_secretbox_NONCEBYTES] i += nacl.crypto_secretbox_NONCEBYTES hcrypt = msg[i:i + nacl.crypto_secretbox_MACBYTES + 4 + 4 + nacl.crypto_scalarmult_curve25519_BYTES] i += nacl.crypto_secretbox_MACBYTES + 4 + 4 + nacl.crypto_scalarmult_curve25519_BYTES mcrypt = msg[i:] ret = self.try_skipped_keys(hcrypt, hnonce, mcrypt, mnonce) if ret: return ret headers = None try: headers = nacl.crypto_secretbox_open(hcrypt, hnonce, self.HKr) except: pass if headers: Np = struct.unpack('>I', headers[:4])[0] CKp, MK = self.stage_skipped_keys(self.HKr, self.Nr, Np, self.CKr) msg = nacl.crypto_secretbox_open(mcrypt, mnonce, MK) if self.bobs1stmsg: self.DHRr = headers[8:] self.RK = nacl.crypto_generichash( self.RK, nacl.crypto_scalarmult_curve25519(self.DHRs.sk, self.DHRr), KEY_SIZE) self.HKs = self.NHKs if self.isalice: self.NHKs = nacl.crypto_generichash( self.RK, "NHKs", KEY_SIZE) self.CKs = nacl.crypto_generichash(self.RK, "CKs", KEY_SIZE) else: self.NHKs = nacl.crypto_generichash( self.RK, "NHKr", KEY_SIZE) self.CKs = nacl.crypto_generichash(self.RK, "CKr", KEY_SIZE) self.DHRs.clear() self.DHRs = None self.bobs1stmsg = False else: headers = nacl.crypto_secretbox_open(hcrypt, hnonce, self.NHKr) #unpack header fields Np = struct.unpack('>I', headers[:4])[0] PNp = struct.unpack('>I', headers[4:8])[0] DHRp = headers[8:] self.stage_skipped_keys(self.HKr, self.Nr, PNp, self.CKr) RKp = nacl.crypto_generichash( self.RK, nacl.crypto_scalarmult_curve25519(self.DHRs.sk, self.DHRr), KEY_SIZE) HKp = self.NHKr if self.isalice: NHKp = nacl.crypto_generichash(RKp, "NHKr", KEY_SIZE) CKp = nacl.crypto_generichash(RKp, "CKr", KEY_SIZE) else: NHKp = nacl.crypto_generichash(RKp, "NHKs", KEY_SIZE) CKp = nacl.crypto_generichash(RKp, "CKs", KEY_SIZE) CKp, MK = self.stage_skipped_keys(HKp, 0, Np, CKp) msg = nacl.crypto_secretbox_open(mcrypt, mnonce, MK) self.RK = RKp self.HKr = HKp self.NHKr = NHKp self.DHRr = DHRp self.RK = nacl.crypto_generichash( self.RK, nacl.crypto_scalarmult_curve25519(self.DHRs.sk, self.DHRr), KEY_SIZE) self.HKs = self.NHKs if self.isalice: self.NHKs = nacl.crypto_generichash(self.RK, "NHKs", KEY_SIZE) self.CKs = nacl.crypto_generichash(self.RK, "CKs", KEY_SIZE) else: self.NHKs = nacl.crypto_generichash(self.RK, "NHKr", KEY_SIZE) self.CKs = nacl.crypto_generichash(self.RK, "CKr", KEY_SIZE) self.DHRs.clear() self.DHRs = None # commit_skipped_header_and_message_keys() : Commits any skipped-over message keys from the # staging area to persistent storage (along with their associated header keys). self.skipped_HK_MK.update(self.staged_HK_MK) self.staged_HK_MK = {} self.Nr = Np + 1 self.CKr = CKp return msg
def decrypt(self, pkt): peer, key = self.keydecrypt(pkt[1]) if key: message = nacl.crypto_secretbox_open(pkt[2], pkt[0], key) return peer, message.decode('utf-8')
import json import binascii from PIL import Image from pyzbar.pyzbar import decode import pysodium backup_password = '******' data = decode(Image.open('backup_qr.png')) res = json.loads(data[0].data) salt = binascii.unhexlify(res['salt']) nonce_and_ciphertext = binascii.unhexlify(res['seed']) nonce = nonce_and_ciphertext[0:pysodium.crypto_secretbox_NONCEBYTES] ciphertext = nonce_and_ciphertext[pysodium.crypto_secretbox_NONCEBYTES:] pwhash = pysodium.crypto_pwhash( pysodium.crypto_auth_KEYBYTES, str.encode(backup_password), salt, pysodium.crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE, pysodium.crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE) print(pysodium.crypto_secretbox_open(ciphertext, nonce, pwhash))
def __decrypt(self, encrypted): key = base64.b64decode(os.environ["ENCRYPTION_KEY"]) decoded = base64.b64decode(encrypted) nonce = decoded[:pysodium.crypto_secretbox_NONCEBYTES] ciph = decoded[pysodium.crypto_secretbox_NONCEBYTES:] return pysodium.crypto_secretbox_open(ciph, nonce, key).decode()
def decrypt(self, pkt): source = None peer, key = self.keydecrypt(pkt[1]) if key: return peer, nacl.crypto_secretbox_open(pkt[2], pkt[0], key)
def test_crypto_secretbox_open(self): k = pysodium.randombytes(pysodium.crypto_secretbox_KEYBYTES) n = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) c = pysodium.crypto_secretbox(b"howdy", n, k) pysodium.crypto_secretbox_open(c, n, k)
def deserialize(self, topic, bytes_): if (isinstance(topic,(bytes,bytearray))): self._parent._logger.debug("passed a topic in bytes (should be string)") topic = topic.decode('utf-8') if bytes_ is None: return None root = self._parent.get_root(topic) if len(bytes_) < 1 or bytes_[0] != 1: return KafkaCryptoMessage.fromBytes(bytes_,deser=self,topic=topic) try: msg = msgpack.unpackb(bytes_[1:],raw=True) if (len(msg) != 3): raise KafkaCryptoSerializeError("Malformed Message!") except Exception as e: self._parent._logger.debug("".join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__))) return KafkaCryptoMessage.fromBytes(bytes_,deser=self,topic=topic) ki = msg[0] salt = msg[1] msg = msg[2] self._parent._lock.acquire() i = 1 initial_waiter = False try: while ((not (root in self._parent._cgens.keys()) or not (ki in self._parent._cgens[root].keys())) and i>0): if (not (root in self._parent._cwaits.keys()) or not (ki in self._parent._cwaits[root].keys())): self._parent._logger.debug("Setting initial wait for root=%s, key index=%s.", root, ki) initial_waiter = True # first time we see a topic/key index pair, we wait the initial interval for key exchange i = self._parent.DESER_INITIAL_WAIT_INTERVALS if not (root in self._parent._cwaits.keys()): self._parent._cwaits[root] = {} self._parent._cwaits[root][ki] = i elif initial_waiter: self._parent._cwaits[root][ki] -= 1 elif (root in self._parent._cwaits.keys()) and (ki in self._parent._cwaits[root].keys()): i = self._parent._cwaits[root][ki] else: i = self.MAX_WAIT_INTERVALS ntp = (root+self._parent.TOPIC_SUFFIX_KEYS) if not (ntp in self._parent._tps): self._parent._tps[ntp] = TopicPartition(ntp,0) self._parent._tps_offsets[ntp] = 0 self._parent._tps_updated = True else: if not (root in self._parent._subs_needed): self._parent._subs_needed.append(root) i=i-1 if (i > 0): self._parent._lock.release() sleep(self.WAIT_INTERVAL) self._parent._lock.acquire() if not (root in self._parent._cgens.keys()) or not (ki in self._parent._cgens[root].keys()): self._parent._logger.debug("No decryption key found for root=%s, key index=%s. Returning encrypted message.", root, ki) raise ValueError gen = self._parent._cgens[root][ki][self._kv] key,nonce = gen.generate(salt=salt) msg = KafkaCryptoMessage(pysodium.crypto_secretbox_open(msg,nonce,key),ipt=True) except: return KafkaCryptoMessage.fromBytes(bytes_,deser=self,topic=topic) finally: self._parent._lock.release() return msg
def unwrap_opaque(self, crypto_opaque): try: return pysodium.crypto_secretbox_open(crypto_opaque[pysodium.crypto_secretbox_NONCEBYTES:],crypto_opaque[0:pysodium.crypto_secretbox_NONCEBYTES], self.__ek) except: return None