def encrypt_blob(blob): # todo implement padding sk = get_sealkey() nonce = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) ct = pysodium.crypto_secretbox(blob, nonce, sk) clearmem(sk) return nonce + ct
def create(self, cb, pwd, user, host, char_classes, size=0): if set(char_classes) - {'u', 'l', 's', 'd'}: raise ValueError("error: rules can only contain ulsd.") try: size = int(size) except: raise ValueError("error: size has to be integer.") self.namesite = {'name': user, 'site': host} rules = sum(1 << i for i, c in enumerate(('u', 'l', 's', 'd')) if c in char_classes) # pack rule rule = struct.pack('>H', (rules << 7) | (size & 0x7f)) # encrypt rule sk = self.getkey() rk = pysodium.crypto_generichash(sk, self.getsalt()) nonce = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) rule = nonce + pysodium.crypto_secretbox(rule, nonce, rk) b, c = sphinxlib.challenge(pwd) message = b''.join([ CREATE, self.getid(host, user), c, rule, pysodium.crypto_sign_sk_to_pk(sk) ]) self.doSphinx(message, b, pwd, cb)
def seal(self, nut): '''encrypt a nut and prepare for sending to a client ''' message = self.NUTBOX.pack(*nut) nonce = next(self.nonce) box = nonce + na.crypto_secretbox(message, nonce, self.__key) return urlsafe_b64encode(box)
def serialize(self, topic, value): if (isinstance(topic,(bytes,bytearray))): self._parent._logger.debug("passed a topic in bytes (should be string)") topic = topic.decode('utf-8') if value is None: return None if (isinstance(value,(KafkaCryptoMessage,))): if (value.isCleartext(retry=False)): value = value.getMessage(retry=False) else: # already serialized and encrypted return bytes(value) if (not isinstance(value,(bytes,bytearray))): raise KafkaCryptoSerializeError("Passed value is not bytes or a KafkaCryptoMessage") root = self._parent.get_root(topic) self._parent._lock.acquire() try: # # Slow path: if we don't already have a generator for this topic, # we have to make one. # if not (root in self._parent._cur_pgens.keys()): self._parent.get_producer(root) # Use generator (new or existing) keyidx = self._parent._cur_pgens[root] pgen = self._parent._pgens[root][keyidx] gen = pgen[self._kv] salt = gen.salt() key,nonce = gen.generate() msg = b'\x01' + msgpack.packb([keyidx,salt,pysodium.crypto_secretbox(value,nonce,key)], use_bin_type=True) except Exception as e: self._parent._logger.warning("".join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__))) finally: self._parent._lock.release() return msg
def savesecretekey(self, ext, key): fname = get_sk_filename(self.basedir, self.name, ext) k = pbp.getkey(nacl.crypto_secretbox_KEYBYTES, empty=True, text="Master" if ext == "mk" else "Subkey") nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) with open(fname, "w") as fd: fd.write(nonce) fd.write(nacl.crypto_secretbox(key, nonce, k))
def secret_key(self, passphrase=None, ed25519_seed=True): """ Creates base58 encoded private key representation :param passphrase: encryption phrase for the private key :param ed25519_seed: encode seed rather than full key for ed25519 curve (True by default) :return: the secret key associated with this key, if available """ if not self.secret_exponent: raise ValueError("Secret key not known.") if self.curve == b'ed' and ed25519_seed: key = pysodium.crypto_sign_sk_to_seed(self.secret_exponent) else: key = self.secret_exponent if passphrase: if not ed25519_seed: raise NotImplementedError salt = pysodium.randombytes(8) encryption_key = hashlib.pbkdf2_hmac( hash_name="sha512", password=scrub_input(passphrase), salt=salt, iterations=32768, dklen=32) encrypted_sk = pysodium.crypto_secretbox(msg=key, nonce=b'\000' * 24, k=encryption_key) key = salt + encrypted_sk # we have to combine salt and encrypted key in order to decrypt later prefix = self.curve + b'esk' else: prefix = self.curve + b'sk' return base58_encode(key, prefix).decode()
def savesecretekey(self, ext, key): fname = get_sk_filename(self.basedir, self.name, ext) k = pbp.getkey(nacl.crypto_secretbox_KEYBYTES, empty=True, text='Master' if ext == 'mk' else 'Subkey') nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) with open(fname, 'wb') as fd: fd.write(nonce) fd.write(nacl.crypto_secretbox(key, nonce, k))
def savesecretekey(self, ext, key): fname = get_sk_filename(self.basedir, self.name, ext) k = getkey(nacl.crypto_secretbox_KEYBYTES, empty=True, text='Master' if ext == 'mk' else 'Subkey') nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) with open(fname,'wb') as fd: fd.write(nonce) fd.write(nacl.crypto_secretbox(key, nonce, k))
def encrypt(msg, pwd=None, k=None): # symmetric nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) cleark = (k is None) if not k: k = getkey(nacl.crypto_secretbox_KEYBYTES, pwd=pwd) ciphertext = nacl.crypto_secretbox(msg, nonce, k) if cleark: clearmem(k) return (nonce, ciphertext)
def encrypt_message(identity, payload): version = 1 nonce = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) pubkeyhash, encryption_key = expand_handle(identity.handle) if not validate_pubkey(identity.pk, pubkeyhash): raise PubkeyError() decrypted = generate_innerbox(identity.pk, identity.sk, payload, version) encrypted = pysodium.crypto_secretbox(decrypted, nonce, encryption_key) return outer_pack.pack(version, nonce, encrypted)
def encrypt(self,plain): if self.out_k == (b'\0' * nacl.crypto_scalarmult_curve25519_BYTES): # encrypt using public key nonce = nacl.randombytes(nacl.crypto_box_NONCEBYTES) cipher= nacl.crypto_box(plain, nonce, self.peer_id.cp, self.me_id.cs) else: # encrypt using chaining mode nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) cipher = nacl.crypto_secretbox(plain, nonce, self.out_k) return cipher, nonce
def encrypt_keys(self, keyidxs, keys, 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 the public key to send the key to, using a # common DH-derived key between that public key and our private encryption key. # Then there is at least one more additional item, random bytes: # (3) random bytes # Currently items after this are ignored, and reserved for future use. # try: with self.__allowdenylist_lock: pk,_ = process_chain(msgval,topic,'key-encrypt-request',allowlist=self.__allowlist,denylist=self.__denylist) # Construct shared secret as sha256(topic || random0 || random1 || our_private*their_public) epk = self.__cryptokey.get_epk(topic, 'encrypt_keys') pks = [pk[2]] eks = self.__cryptokey.use_epk(topic, 'encrypt_keys',pks) ek = eks[0] eks[0] = epk random0 = pk[3] random1 = pysodium.randombytes(self.__randombytes) ss = pysodium.crypto_hash_sha256(topic.encode('utf-8') + random0 + random1 + ek)[0:pysodium.crypto_secretbox_KEYBYTES] nonce = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) # encrypt keys and key indexes (MAC appended, nonce prepended) msg = [] for i in range(0,len(keyidxs)): msg.append(keyidxs[i]) msg.append(keys[i]) msg = msgpack.packb(msg, use_bin_type=True) msg = nonce + pysodium.crypto_secretbox(msg,nonce,ss) # this is then put in a msgpack array with the appropriate max_age, poison, and public key(s) poison = msgpack.packb([['topics',[topic]],['usages',['key-encrypt']]], use_bin_type=True) msg = msgpack.packb([time()+self.__maxage,poison,eks,[random0,random1],msg], use_bin_type=True) # and signed with our signing key msg = self.__cryptokey.sign_spk(msg) # and finally put as last member of a msgpacked array chaining to ROT with self.__spk_chain_lock: tchain = self.__spk_chain.copy() if (len(tchain) == 0): poison = msgpack.packb([['topics',[topic]],['usages',['key-encrypt']],['pathlen',1]], use_bin_type=True) lastcert = msgpack.packb([time()+self.__maxage,poison,self.__cryptokey.get_spk()], use_bin_type=True) _,tempsk = pysodium.crypto_sign_seed_keypair(unhexlify(b'4c194f7de97c67626cc43fbdaf93dffbc4735352b37370072697d44254e1bc6c')) tchain.append(pysodium.crypto_sign(lastcert,tempsk)) provision = msgpack.packb([msgpack.packb([0,b'\x90',self.__cryptokey.get_spk()]),self.__cryptokey.sign_spk(lastcert)], use_bin_type=True) self._logger.warning("Current signing chain is empty. Use %s to provision access and then remove temporary root of trust from allowedlist.", provision.hex()) tchain.append(msg) msg = msgpack.packb(tchain, use_bin_type=True) except Exception as e: self._logger.warning("".join(format_exception_shim(e))) return None return msg
def encrypt(msg, pwd=None, k=None): # encrypts a message symmetrically using crypto_secretbox # k specifies an encryption key, which if not supplied, is derived from # pwd which is queried from the user, if also not specified. # returns a (nonce, ciphertext) tuple nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) cleark = (k is None) if not k: k = getkey(nacl.crypto_secretbox_KEYBYTES, pwd=pwd) ciphertext = nacl.crypto_secretbox(msg, nonce, k) if cleark: clearmem(k) return (nonce, ciphertext)
def encrypt(self, plain): if self.out_k == (b'\0' * nacl.crypto_scalarmult_curve25519_BYTES): # encrypt using public key nonce = nacl.randombytes(nacl.crypto_box_NONCEBYTES) cipher = nacl.crypto_box(plain, nonce, self.peer_id.cp, self.me_id.cs) else: # encrypt using chaining mode nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) cipher = nacl.crypto_secretbox(plain, nonce, self.out_k) return cipher, nonce
def session_output (_outbound_key, _outbound_nonce, _packet) : pysodium.sodium_increment (_outbound_nonce) log ("[7a9b17ef]", "[crypto][output]", "using nonce `%s`;", _outbound_nonce.encode ("b64")) log ("[04a30b0d]", "[crypto][output]", "encoding packet (plain) `%s`...", _packet.encode ("b64")) _encrypted = pysodium.crypto_secretbox (_packet, _outbound_nonce, _outbound_key) log ("[06c3b67d]", "[crypto][output]", "encoded packet (encrypted) `%s`;", _encrypted.encode ("b64")) return _encrypted
def send(self, msg): """ as per https://github.com/trevp/axolotl/wiki/newversion (Nov 19, 2013 · 41 revisions) Sending messages ----------------- Local variables: MK : message key if DHRs == <none>: DHRs = generateECDH() MK = HASH(CKs || "0") msg = Enc(HKs, Ns || PNs || DHRs) || Enc(MK, plaintext) Ns = Ns + 1 CKs = HASH(CKs || "1") return msg """ if self.DHRs == None: self.DHRs = Key().new() self.PNs = self.Ns # wtf: not in spec, but seems needed self.Ns = 0 # wtf: not in spec, but seems needed mk = nacl.crypto_generichash(self.CKs, 'MK', nacl.crypto_secretbox_KEYBYTES) hnonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) mnonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) msg = ''.join((hnonce, mnonce, nacl.crypto_secretbox( ''.join((struct.pack('>I',self.Ns), struct.pack('>I',self.PNs), self.DHRs.pk)), hnonce, self.HKs), nacl.crypto_secretbox(msg, mnonce, mk))) clearmem(mk) mk = None self.Ns += 1 self.CKs = nacl.crypto_generichash(self.CKs, "CK", nacl.crypto_secretbox_KEYBYTES) return msg
def send(self, msg): """ as per https://github.com/trevp/axolotl/wiki/newversion (Nov 19, 2013 · 41 revisions) Sending messages ----------------- Local variables: MK : message key if DHRs == <none>: DHRs = generateECDH() MK = HASH(CKs || "0") msg = Enc(HKs, Ns || PNs || DHRs) || Enc(MK, plaintext) Ns = Ns + 1 CKs = HASH(CKs || "1") return msg """ if self.DHRs == None: self.DHRs = Key().new() self.PNs = self.Ns # wtf: not in spec, but seems needed self.Ns = 0 # wtf: not in spec, but seems needed mk = nacl.crypto_generichash(self.CKs, 'MK', nacl.crypto_secretbox_KEYBYTES) hnonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) mnonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) msg = ''.join( (hnonce, mnonce, nacl.crypto_secretbox( ''.join((struct.pack('>I', self.Ns), struct.pack('>I', self.PNs), self.DHRs.pk)), hnonce, self.HKs), nacl.crypto_secretbox(msg, mnonce, mk))) clearmem(mk) mk = None self.Ns += 1 self.CKs = nacl.crypto_generichash(self.CKs, "CK", nacl.crypto_secretbox_KEYBYTES) return msg
def encode(self, kmsg): """ Encode message using libsodium :param kser.schemas.Message kmsg: Kafka message :return: the Encoded message """ nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) return self.dumps( dict(nonce=base64.encodebytes(nonce).strip(), data=base64.encodebytes( pysodium.crypto_secretbox( bytes(kmsg.MARSHMALLOW_SCHEMA.dumps(kmsg), 'utf-8'), nonce, base64.b64decode(self.secretbox_key))).strip()))
def make_keypair(): public_key, private_key = pysodium.crypto_sign_keypair() print 'Do you wish to encrypt the private key under a password? (y/n)' answer = raw_input().lower() if answer not in ['y', 'n']: raise SystemExit('Invalid answer') if answer == 'y': salt = pysodium.randombytes(pysodium.crypto_pwhash_SALTBYTES) key = hash_password(prompt_for_new_password(), salt) nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) cyphertext = pysodium.crypto_secretbox(private_key, nonce, key) private_key = b'y' + salt + nonce + cyphertext else: private_key = b'n' + private_key return base64.b64encode(private_key), base64.b64encode(public_key)
def encrypt(plaintext, password): """Encrypts the given plaintext using libsodium secretbox, key is generated using scryptsalsa208sha256 with a random salt and nonce (we can not guarantee the incrementing anyway). Note that any str objects are assumed to be in utf-8.""" salt = pysodium.randombytes(pysodium.crypto_pwhash_scryptsalsa208sha256_SALTBYTES) memlimit = pysodium.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE opslimit = pysodium.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE if isinstance(password, str): password = password.encode("utf-8") key = pysodium.crypto_pwhash_scryptsalsa208sha256(pysodium.crypto_secretbox_KEYBYTES, password, salt, memlimit, opslimit) nonce = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) if isinstance(plaintext, str): plaintext = plaintext.encode("utf-8") cyphertext = pysodium.crypto_secretbox(plaintext, nonce, key) data = (1).to_bytes(1, "little") data += memlimit.to_bytes(4, "little") data += opslimit.to_bytes(4, "little") data += salt data += nonce data += cyphertext return base64.b64encode(data)
def secret_key( self, passphrase: PassphraseInput = None, ed25519_seed: bool = True, ): """Creates base58 encoded private key representation. :param passphrase: encryption phrase for the private key :param ed25519_seed: encode seed rather than full key for ed25519 curve (True by default) :returns: the secret key associated with this key, if available """ if not self.secret_exponent: raise ValueError("Secret key is undefined") if self.curve == b'ed' and ed25519_seed: key = pysodium.crypto_sign_sk_to_seed(self.secret_exponent) else: key = self.secret_exponent if passphrase: if not ed25519_seed: raise NotImplementedError if isinstance(passphrase, str): passphrase = passphrase.encode() assert isinstance( passphrase, bytes ), f'expected bytes or str, got {type(passphrase).__name__}' salt = pysodium.randombytes(8) encryption_key = hashlib.pbkdf2_hmac( hash_name="sha512", password=passphrase, salt=salt, iterations=32768, dklen=32, ) encrypted_sk = pysodium.crypto_secretbox(msg=key, nonce=b'\000' * 24, k=encryption_key) key = salt + encrypted_sk # we have to combine salt and encrypted key in order to decrypt later prefix = self.curve + b'esk' else: prefix = self.curve + b'sk' return base58_encode(key, prefix).decode()
def encrypt(msg, pwd=None, k=None, nonce=None): # encrypts a message symmetrically using crypto_secretbox # k specifies an encryption key, which if not supplied, is derived from # pwd which is queried from the user, if also not specified. # returns a (nonce, ciphertext) tuple if nonce == None: nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) clearpwd = (pwd is None) cleark = (k is None) if not k: k = getkey(nacl.crypto_secretbox_KEYBYTES, pwd=pwd) ciphertext = nacl.crypto_secretbox(msg, nonce, k) if cleark and k: clearmem(k) k = None if clearpwd and pwd: clearmem(pwd) pwd = None return (nonce, ciphertext)
def make_keypair() -> Tuple[bytes, bytes]: public_key, private_key = pysodium.crypto_sign_keypair() print('Do you wish to encrypt the private key under a password? (y/n)') answer: str while True: answer = input('>').lower() if answer not in ['y', 'n']: print('Invalid answer') else: break if answer == 'y': salt: bytes = pysodium.randombytes(pysodium.crypto_pwhash_SALTBYTES) key: bytes = hash_password(prompt_for_new_password(), salt) nonce: bytes = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES) cyphertext: bytes = pysodium.crypto_secretbox(private_key, nonce, key) private_key = b'y' + salt + nonce + cyphertext else: private_key = b'n' + private_key return base64.b64encode(private_key), base64.b64encode(public_key)
def run_client(): # FIXME: lock state file for duration of the program counter = read_counter() write_counter(counter + 1) log('[INFO] knock '+server_ip+':'+str(server_port)+' '+client_sign_public_key.encode('hex')) # NONCE(24) + MAC(16) + MAGIC(8) + SIGNPUB(32) + SIG(64) + COUNTER(14) + LEN(2) + REST PROTO_MIN_SIZE = 160 arg = sys.argv[2] if len(sys.argv) > 2 else b'' if PROTO_MIN_SIZE + len(arg) > 1024: log('[ERROR] argument too long') sys.exit(1) padded_min_size = PROTO_MIN_SIZE + roundup(len(arg), 16) padding = '\x00' * ((roundup(len(arg), 16) - len(arg)) + (16 * random.randint(0, (1024 - padded_min_size) / 16))) nonce = saferandom(pysodium.crypto_secretbox_NONCEBYTES) magic_bin = '42f9708e2f1369d9'.decode('hex') # chosen by fair die counter_bin = hex(counter)[2:].zfill(28).decode('hex') data_len_bin = '0000'.decode('hex') server_ip_bin = socket.inet_aton(server_ip) sig = pysodium.crypto_sign_detached((nonce + magic_bin + client_sign_public_key + counter_bin + data_len_bin + arg + padding + server_private_key + server_ip_bin), client_sign_private_key) cdata = nonce + pysodium.crypto_secretbox((magic_bin + client_sign_public_key + sig + counter_bin + data_len_bin + arg + padding), nonce, server_private_key) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(cdata, (server_ip, server_port)) log('[INFO] sent '+str(len(cdata)))
def encrypt(self, m): n = randombytes(crypto_secretbox_NONCEBYTES) c = crypto_secretbox(m, n, self.key) m = n + c return m
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 wrap_opaque(self, crypto_opaque): nonce = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) return nonce+pysodium.crypto_secretbox(crypto_opaque,nonce,self.__ek)
def __encrypt(self, pwd, nonce, key): return base64.b64encode(pysodium.crypto_secretbox(pwd.encode(), nonce, key))
def encrypt(self, msg, recipients=None): mk = nacl.randombytes(nacl.crypto_secretbox_KEYBYTES) c = self.keyencrypt(mk, recipients) nonce = nacl.randombytes(nacl.crypto_secretbox_NONCEBYTES) return (nonce, c, nacl.crypto_secretbox(msg, nonce, mk))
def __encrypt(self, pwd): key = base64.b64decode(os.environ["ENCRYPTION_KEY"]) nonce = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) encrypted = nonce + pysodium.crypto_secretbox(pwd.encode(), nonce, key) return base64.b64encode(encrypted).decode()
m.update(chr(0xFE)) m.update(str(endorsementKey)) digest = m.digest() publicKey = PublicKey(bytes(ATTESTATION), raw=True) signature = publicKey.ecdsa_deserialize(bytes(endorsementSignature)) if not publicKey.ecdsa_verify(bytes(digest), signature, raw=True): raise Exception("Attestation key signature not verified") m = hashlib.sha256() m.update(str(ephemeralPublic)) m.update(CODEHASH) digest = m.digest() publicKey = PublicKey(bytes(endorsementKey), raw=True) signature = publicKey.ecdsa_deserialize(bytes(codeSignature)) if not publicKey.ecdsa_verify(bytes(digest), signature, raw=True): raise Exception("Endorsement not verified") ephemeralPublicKey = PublicKey(bytes(ephemeralPublic), raw=True) privateKey = PrivateKey() secret = ephemeralPublicKey.ecdh(bytes(privateKey.serialize().decode('hex'))) nonce = os.urandom(pysodium.crypto_secretbox_NONCEBYTES) sealed = pysodium.crypto_secretbox(str(SECRET), str(nonce), str(secret)) result = str(blob) + str( privateKey.pubkey.serialize(compressed=False)) + str(nonce) + str(sealed) print result.encode('hex')