Beispiel #1
0
    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        Re-encrypt.
        """
        # Derive the key from the passphrase.
        derived = util.derive_passphrase(self.passphrase)

        # Generate two random nonces.
        nonce1 = random(SecretBox.NONCE_SIZE)
        nonce2 = random(SecretBox.NONCE_SIZE)

        sign_box = SecretBox(derived)
        enc_box = SecretBox(derived)

        s_p = self.sign.encode()
        e_p = self.encrypt.encode()

        s_e = sign_box.encrypt(s_p, nonce1)
        e_e = enc_box.encrypt(e_p, nonce2)

        # Update `self.key`.
        self.key._private_key_raw = e_e.ciphertext
        self.key._private_signing_key_raw = s_e.ciphertext

        # Bit of a mixed up name.
        self.key._private_nonce = e_e.nonce
        self.key._private_signing_nonce = s_e.nonce

        if exc_type is not None:
            raise exc_type(exc_val)
Beispiel #2
0
def randrange(n):
    a = (n.bit_length() + 7) // 8  # number of bytes to store n
    b = 8 * a - n.bit_length()  # number of shifts to have good bit number
    r = int.from_bytes(random(a), byteorder='big') >> b
    while r >= n:
        r = int.from_bytes(random(a), byteorder='big') >> b
    return r
Beispiel #3
0
def keystore_seal(private_key, password, address, name=""):
    # password
    salt = nacl_utils.random(argon2id.SALTBYTES)
    mem = argon2id.MEMLIMIT_MODERATE
    ops = argon2id.OPSLIMIT_MODERATE
    key = argon2id.kdf(secret.SecretBox.KEY_SIZE, password.encode(), salt, opslimit=ops, memlimit=mem)
    # ciphertext
    box = secret.SecretBox(key)
    nonce = nacl_utils.random(secret.SecretBox.NONCE_SIZE)
    sk = private_key.encode(encoder=RawEncoder) + private_key.verify_key.encode(encoder=RawEncoder)
    ciphertext = box.encrypt(sk, nonce=nonce).ciphertext
    # build the keystore
    k = {
        "public_key": address,
        "crypto": {
            "secret_type": "ed25519",
            "symmetric_alg": "xsalsa20-poly1305",
            "ciphertext": bytes.hex(ciphertext),
            "cipher_params": {
                "nonce": bytes.hex(nonce)
            },
            "kdf": "argon2id",
            "kdf_params": {
                "memlimit_kib": round(mem / 1024),
                "opslimit": ops,
                "salt": bytes.hex(salt),
                "parallelism": 1  # pynacl 1.3.0 doesnt support this parameter
            }
        },
        "id": str(uuid.uuid4()),
        "name": name,
        "version": 1
    }
    return k
Beispiel #4
0
def keystore_seal(secret_key,
                  password,
                  name="",
                  secret_type=SECRET_TYPE_SLIP0010):
    """
    Seal a keystore

    :param secret_key: the secret key to store in the keystore
    :param password: the keystore password
    :param name: the optional name of the keystore
    :param secret_type: type of the secret to store (default: ed25519-slip0010-masterkey)
    """
    # password
    salt = nacl_utils.random(argon2id.SALTBYTES)
    mem = argon2id.MEMLIMIT_MODERATE
    ops = argon2id.OPSLIMIT_MODERATE
    key = argon2id.kdf(secret.SecretBox.KEY_SIZE,
                       password.encode(),
                       salt,
                       opslimit=ops,
                       memlimit=mem)
    # ciphertext
    box = secret.SecretBox(key)
    nonce = nacl_utils.random(secret.SecretBox.NONCE_SIZE)
    if isinstance(secret_key, SigningKey):
        sk = secret_key.encode() + secret_key.verify_key.encode()
    else:
        sk = secret_key.encode('utf-8')
    ciphertext = box.encrypt(sk, nonce=nonce).ciphertext
    # build the keystore
    k = {
        "crypto": {
            "secret_type": secret_type,
            "symmetric_alg": "xsalsa20-poly1305",
            "ciphertext": bytes.hex(ciphertext),
            "cipher_params": {
                "nonce": bytes.hex(nonce)
            },
            "kdf": "argon2id",
            "kdf_params": {
                "memlimit_kib": round(mem / 1024),
                "opslimit": ops,
                "salt": bytes.hex(salt),
                "parallelism": 1  # pynacl 1.3.0 doesn't support this parameter
            }
        },
        "id": str(uuid.uuid4()),
        "name": name,
        "version": 1
    }
    return k
Beispiel #5
0
    def create_default(cls, enable_auth_key=False):
        """ Create default settings for encryption key derivation from password.

        original source: https://pynacl.readthedocs.io/en/stable/password_hashing/#key-derivation
        :param bool enable_auth_key: generate a key for full data signatures via HMAC
        :rtype: DerivedKeySetup
        """
        return cls(ops=pwhash.argon2i.OPSLIMIT_SENSITIVE,
                   mem=pwhash.argon2i.MEMLIMIT_SENSITIVE,
                   construct='argon2i',
                   salt_key_enc=utils.random(pwhash.argon2i.SALTBYTES),
                   salt_key_sig=utils.random(pwhash.argon2i.SALTBYTES)
                   if enable_auth_key else b'',
                   key_size_enc=secret.SecretBox.KEY_SIZE,
                   key_size_sig=64 if enable_auth_key else 0)
Beispiel #6
0
        def encode(self, is_originating, uri, args=None, kwargs=None):
            """
            Encrypt the given WAMP URI, args and kwargs into an EncodedPayload instance, or None
            if the URI should not be encrypted.
            """
            assert (type(is_originating) == bool)
            assert (type(uri) == six.text_type)
            assert (args is None or type(args) in (list, tuple))
            assert (kwargs is None or type(kwargs) == dict)

            box = self._get_box(is_originating, uri)

            if not box:
                # if we didn't find a crypto box, then return None, which
                # signals that the payload travel unencrypted (normal)
                return None

            payload = {u'uri': uri, u'args': args, u'kwargs': kwargs}
            nonce = random(Box.NONCE_SIZE)
            payload_ser = _json_dumps(payload).encode('utf8')

            payload_encr = box.encrypt(payload_ser, nonce, encoder=RawEncoder)

            # above returns an instance of http://pynacl.readthedocs.io/en/latest/utils/#nacl.utils.EncryptedMessage
            # which is a bytes _subclass_! hence we apply bytes() to get at the underlying plain
            # bytes "scalar", which is the concatenation of `payload_encr.nonce + payload_encr.ciphertext`
            payload_bytes = bytes(payload_encr)
            payload_key = None

            return EncodedPayload(payload_bytes,
                                  u'cryptobox',
                                  u'json',
                                  enc_key=payload_key)
Beispiel #7
0
 def _encrypt_data(self, key, data):
     assert isinstance(key, type(b"")), type(key)
     assert isinstance(data, type(b"")), type(data)
     assert len(key) == SecretBox.KEY_SIZE, len(key)
     box = SecretBox(key)
     nonce = utils.random(SecretBox.NONCE_SIZE)
     return box.encrypt(data, nonce)
Beispiel #8
0
        def encrypt(self, is_originator, uri, args=None, kwargs=None):
            """
            Encrypt the given WAMP URI, args and kwargs into an EncryptedPayload instance, or None
            if the URI should not be encrypted.
            """
            assert (type(uri) == six.text_type)
            assert (type(is_originator) == bool)
            assert (args is None or type(args) in (list, tuple))
            assert (kwargs is None or type(kwargs) == dict)

            box = self._get_box(is_originator, uri)

            if not box:
                return

            payload = {u'uri': uri, u'args': args, u'kwargs': kwargs}
            nonce = random(Box.NONCE_SIZE)
            payload_ser = json.dumps(payload)
            payload_encr = box.encrypt(payload_ser,
                                       nonce,
                                       encoder=Base64Encoder)
            payload_bytes = payload_encr.encode().decode('ascii')
            payload_key = None

            return EncryptedPayload(u'cryptobox', payload_key, u'json',
                                    payload_bytes)
Beispiel #9
0
def step4_api2():
    hkdf_salt = random(32)
    nodeid = do_priv("get_nodeid")
    to_server_key = get_subkey("to_server", hkdf_salt)
    ciphertext = SecretBox(to_server_key).encrypt(nodeid.encode())

    try:
        with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s:
            s.settimeout(5)
            s.connect((bootstrap_ipv6, 1337))

            assert(len(hkdf_salt) < 256)
            s.sendall(len(hkdf_salt).to_bytes(1, byteorder='big') + hkdf_salt)
            assert(len(ciphertext) < 256)
            s.sendall(len(ciphertext).to_bytes(1, byteorder='big') + ciphertext)

            num_bytes = int.from_bytes(s.recv(1), byteorder='big')
            resp=b''
            while len(resp) < num_bytes:
                resp += s.recv(num_bytes - len(resp))
    except (OSError, socket.timeout):
        abort(404, "Not found")

    from_server_key = get_subkey("from_server", hkdf_salt)
    global network_id
    network_id = SecretBox(from_server_key).decrypt(resp).decode()

    #XXX Do we need to leave networks with overlapping IP space? Better to warn?
    do_priv("leaveall private")
    do_priv("join %s" % network_id)

    return "ok"
Beispiel #10
0
    def test_encrypt_key_with_path_tuple(self):
        key = random(32)
        path = b'/foo/bar'

        enc_keys = self.client.encrypt_key(key, path=path)
        self.assertEqual(3, len(enc_keys))
        self.assertTrue(key not in enc_keys)
Beispiel #11
0
    def test_build_header_prealpha(self):
        enc_keys = [random(148), random(148), random(148)]
        version = 100
        header, length = self.client._build_header(enc_keys, version=version)

        self.assertEqual(len(header), length)
        try:
            msgpack.loads(header)
        except Exception as E:
            self.fail("Failed to unpack header:\n{}".format(E))

        self.assertIn((3).to_bytes(4, byteorder='big'), header)
        for key in enc_keys:
            self.assertIn(key, header)

        self.assertIn(version.to_bytes(4, byteorder='big'), header)
Beispiel #12
0
    def encrypt(self, plaintext, nonce=None, encoder=encoding.RawEncoder):
        """
        Encrypts the plaintext message using the given `nonce` (or generates
        one randomly if omitted) and returns the ciphertext encoded with the
        encoder.

        .. warning:: It is **VITALLY** important that the nonce is a nonce,
            i.e. it is a number used only once for any given key. If you fail
            to do this, you compromise the privacy of the messages encrypted.

        :param plaintext: [:class:`bytes`] The plaintext message to encrypt
        :param nonce: [:class:`bytes`] The nonce to use in the encryption
        :param encoder: The encoder to use to encode the ciphertext
        :rtype: [:class:`nacl.utils.EncryptedMessage`]
        """
        if nonce is None:
            nonce = random(self.NONCE_SIZE)

        if len(nonce) != self.NONCE_SIZE:
            raise ValueError("The nonce must be exactly %s bytes long" % self.NONCE_SIZE)

        ciphertext = nacl.bindings.crypto_box_afternm(plaintext, nonce, self._shared_key)

        encoded_nonce = encoder.encode(nonce)
        encoded_ciphertext = encoder.encode(ciphertext)

        return EncryptedMessage._from_parts(encoded_nonce, encoded_ciphertext, encoder.encode(nonce + ciphertext))
Beispiel #13
0
def pwashtest():
    password = b"password"
    message = b"This is a message for Bob's eyes only"

    kdf = pwhash.argon2i.kdf
    salt = b'\xa3\x95\\\xec\x1cFpr8\xb7\x92\x7f\x18%)\x88'
    ops = pwhash.argon2i.OPSLIMIT_SENSITIVE
    mem = pwhash.argon2i.MEMLIMIT_SENSITIVE

    Alices_key = kdf(secret.SecretBox.KEY_SIZE,
                     password,
                     salt,
                     opslimit=ops,
                     memlimit=mem)
    Alices_box = secret.SecretBox(Alices_key)
    nonce = utils.random(secret.SecretBox.NONCE_SIZE)
    print(salt)

    encrypted = Alices_box.encrypt(message, nonce)

    # now Alice must send to Bob both the encrypted message
    # and the KDF parameters: salt, opslimit and memlimit;
    # using the same kdf mechanism, parameters **and password**
    # Bob is able to derive the correct key to decrypt the message

    Bobs_key = kdf(secret.SecretBox.KEY_SIZE,
                   password,
                   salt,
                   opslimit=ops,
                   memlimit=mem)

    Bobs_box = secret.SecretBox(Bobs_key)
    received = Bobs_box.decrypt(encrypted)
    print(received.decode('utf-8'))
Beispiel #14
0
    def encrypt(self, plaintext, nonce=None, aad=None, encoder=RawEncoder):
        """
        Encrypts the plaintext message using the given `nonce` (or generates
        one randomly if omitted) and returns the ciphertext encoded with the
        encoder.
        .. warning:: It is **VITALLY** important that the nonce is a nonce,
            i.e. it is a number used only once for any given key. If you fail
            to do this, you compromise the privacy of the messages encrypted.
            Give your nonces a different prefix, or have one side use an odd
            counter and one an even counter. Just make sure they are different.
        :param plaintext: [:class:`bytes`] The plaintext message to encrypt
        :param nonce: [:class:`bytes`] The nonce to use in the encryption
        :param encoder: The encoder to use to encode the ciphertext
        :rtype: [:class:`nacl.utils.EncryptedMessage`]
        """
        if nonce is None:
            nonce = random(self.NONCE_SIZE)

        exc.ensure(
            isinstance(plaintext, bytes) or isinstance(plaintext, bytearray),
            "Plaintext type must be bytes or bytearray",
            raising=exc.TypeError,
        )

        ciphertext = nacl.bindings.crypto_aead_xchacha20poly1305_ietf_encrypt(
            plaintext if isinstance(plaintext, bytes) else bytes(plaintext), aad, nonce, self._key
        )

        encoded_nonce = encoder.encode(nonce)
        encoded_ciphertext = encoder.encode(ciphertext)

        return EncryptedMessage._from_parts(
            encoded_nonce, encoded_ciphertext, encoder.encode(nonce + ciphertext)
        )
Beispiel #15
0
 def _encrypt_data(self, key, data):
     assert isinstance(key, type(b"")), type(key)
     assert isinstance(data, type(b"")), type(data)
     if len(key) != SecretBox.KEY_SIZE: raise UsageError
     box = SecretBox(key)
     nonce = utils.random(SecretBox.NONCE_SIZE)
     return box.encrypt(data, nonce)
Beispiel #16
0
def send():  # event is passed by binders.
    msg = my_msg.get()
    my_msg.set("")  # Clears input field.
    r = post('http://127.0.0.1:5000/qkuser/A', json={"receiver": "B"})
    print(r.json())
    data = r.json()
    print("Symmetric key retrieved for B: " + data['status'])
    qkey = data['status']
    nonce = utils.random(secret.SecretBox.NONCE_SIZE)

    print("Nonce")
    print(nonce)
    print("Message")
    print(msg)
    ctext = cipher.encrypt(msg, qkey, nonce)
    print("Ciphertext")
    print(ctext)
    print("Qkey")
    print(qkey)

    texttosend = str(ctext) + "###" + base64.encodebytes(nonce).decode("utf-8")
    client_socket.send(bytes(texttosend, "utf8"))
    if msg == "{quit}":
        client_socket.close()
        top.quit()
Beispiel #17
0
 def _encrypt_data(self, key, data):
     assert isinstance(key, type(b"")), type(key)
     assert isinstance(data, type(b"")), type(data)
     assert len(key) == SecretBox.KEY_SIZE, len(key)
     box = SecretBox(key)
     nonce = utils.random(SecretBox.NONCE_SIZE)
     return box.encrypt(data, nonce)
Beispiel #18
0
    def setUpClass(cls):
        cls.public_ip = '123.45.67.89'
        cls.port = 12345
        cls.own_addr = (cls.public_ip, cls.port)
        cls.addr1 = ('132.54.76.98', 54321)
        cls.addr2 = ('231.76.45.89', 15243)
        cls.privkey1_hex = '71d1054068b224a4d9013104881dc7f46c6fec9a618f4574ae21059723e6c4f8'
        cls.privkey1 = public.PrivateKey(cls.privkey1_hex,
                                         encoder=encoding.HexEncoder)
        cls.pubkey1 = cls.privkey1.public_key
        cls.pubkey1_bytes = cls.pubkey1.encode(encoder=encoding.RawEncoder)

        cls.privkey2_hex = '4c107b7844368d0fb608f3d91ae194f2d62c7ff91b713e5b05c279e8b7fc61b3'
        cls.privkey2 = public.PrivateKey(cls.privkey2_hex,
                                         encoder=encoding.HexEncoder)
        cls.pubkey2 = cls.privkey2.public_key
        cls.pubkey2_bytes = cls.pubkey2.encode(encoder=encoding.RawEncoder)

        cls.remote_crypto_box = public.Box(cls.privkey2, cls.pubkey1)
        cls.nonce = utils.random(cls.remote_crypto_box.NONCE_SIZE)

        cls.local_crypto_box = public.Box(cls.privkey1, cls.pubkey2)

        cls.privkey3_hex = '40246691a4362a220606dd302b03e992b5b5fe21026377fa56c9fe3f5afbcbd0'
        cls.privkey3 = public.PrivateKey(cls.privkey3_hex,
                                         encoder=encoding.HexEncoder)
        cls.pubkey3 = cls.privkey3.public_key
        cls.pubkey3_bytes = cls.pubkey3.encode(encoder=encoding.RawEncoder)

        cls.other_crypto_box = public.Box(cls.privkey3, cls.pubkey1)
Beispiel #19
0
    def __init__(self, cfg: Config, password: str) -> None:
        self.l = DBLogger(self, cfg)

        kdf = pwhash.argon2i.kdf
        salt = utils.random(pwhash.argon2i.SALTBYTES)
        ops = pwhash.argon2i.OPSLIMIT_SENSITIVE
        mem = pwhash.argon2i.MEMLIMIT_SENSITIVE

        self.l.info(
            "Deriving wallet encryption key, might take a couple seconds")
        self.key = kdf(secret.SecretBox.KEY_SIZE, password, salt,
                                 opslimit=ops, memlimit=mem)
        self.box = secret.SecretBox(Alices_key)

        self._uxto_storage = SqliteUXTOStorage(cfg)

        self._chain = BlockChain(
                SqliteBlockChainStorage(cfg),
                SqliteTransactionStorage(cfg),
                self._uxto_storage,
                cfg)

        self._conn = sqlite3.connect(cfg.wallet_path())
        self._conn.execute(CREATE_TABLE_SQL)
        self._conn.commit()
Beispiel #20
0
    def generate_key(self, password, salt):
        # generate key that will be used to encrypt inner box
        userKey = utils.random(secret.SecretBox.KEY_SIZE)

        # generate key that will be used to encrypt outer box
        key = pwhash.kdf_scryptsalsa208sha256(
            secret.SecretBox.KEY_SIZE,
            password,
            salt,
            opslimit=pwhash.SCRYPT_OPSLIMIT_INTERACTIVE,
            memlimit=pwhash.SCRYPT_MEMLIMIT_INTERACTIVE)
        nonce = utils.random(secret.SecretBox.NONCE_SIZE)

        box = secret.SecretBox(key)
        encrypted = box.encrypt(userKey, nonce)
        return encrypted
Beispiel #21
0
def encrypt_data(key, plaintext):
    assert isinstance(key, type(b"")), type(key)
    assert isinstance(plaintext, type(b"")), type(plaintext)
    assert len(key) == SecretBox.KEY_SIZE, len(key)
    box = SecretBox(key)
    nonce = utils.random(SecretBox.NONCE_SIZE)
    return box.encrypt(plaintext, nonce)
Beispiel #22
0
    def generate(cls):
        """
        Generates a random :class:`~nacl.public.PrivateKey` object

        :rtype: :class:`~nacl.public.PrivateKey`
        """
        return cls(random(PrivateKey.SIZE), encoder=encoding.RawEncoder)
Beispiel #23
0
def encrypt(file, privkey, recipients):
    # ignores privkey and recipients for now
    key = random(SecretBox.KEY_SIZE)
    box = SecretBox(key)
    enc = box.encrypt(file.encode("utf-8"))
    jsondata = json.dumps({"version":"0.1","key":base64.b64encode(key).decode("utf-8")})
    return jsondata.encode("utf-8")+_separator+enc
Beispiel #24
0
 def create_keys(self, location):
     # create the server key  and stores in a local file.
     server_key = utils.random(secret.SecretBox.KEY_SIZE)
     with open(location, "a") as f:
         f.write("SECRET=")
         f.write(base64.encodebytes(server_key).decode('ascii'))
     return server_key
Beispiel #25
0
    async def make_box(self, secret_key: bytes = None) -> Tuple[SecretBox, bytes]:
        if not secret_key:
            # If a secret key isn't provided then create a random one
            secret_key = random(self.secret_size)

        # Return a tuple with the instance of SecretBox and the secret key itself
        return SecretBox(secret_key), secret_key
Beispiel #26
0
    def test_when_encrypting_with_a_key_the_decrypter_works_when_using_the_shared_key(
            self):
        nonce = random(SecretBox.NONCE_SIZE)
        shared_key = random(SecretBox.KEY_SIZE)
        box = SecretBox(shared_key)
        plaintext = 'The ship has arrived at the port'
        encrypted_msg = box.encrypt(bytes(plaintext, 'utf-8'), nonce)
        nonce_str = b64encode(encrypted_msg.nonce).decode("utf-8")
        encrypted_msg_str = b64encode(encrypted_msg.ciphertext).decode("utf-8")
        message = f'{nonce_str}:{encrypted_msg_str}'

        decrypter = util.create_decrypter(shared_key)
        decrypted_text = decrypter(message)

        self.assertNotEqual(plaintext, encrypted_msg.ciphertext)
        self.assertEqual(plaintext, decrypted_text)
def encrypt_data(key, plaintext):
    assert isinstance(key, type(b"")), type(key)
    assert isinstance(plaintext, type(b"")), type(plaintext)
    assert len(key) == SecretBox.KEY_SIZE, len(key)
    box = SecretBox(key)
    nonce = utils.random(SecretBox.NONCE_SIZE)
    return box.encrypt(plaintext, nonce)
Beispiel #28
0
    def encrypt(self, plaintext, nonce=None, encoder=encoding.RawEncoder):
        """
        Encrypts the plaintext message using the given `nonce` (or generates
        one randomly if omitted) and returns the ciphertext encoded with the
        encoder.

        .. warning:: It is **VITALLY** important that the nonce is a nonce,
            i.e. it is a number used only once for any given key. If you fail
            to do this, you compromise the privacy of the messages encrypted.
            Give your nonces a different prefix, or have one side use an odd
            counter and one an even counter. Just make sure they are different.

        :param plaintext: [:class:`bytes`] The plaintext message to encrypt
        :param nonce: [:class:`bytes`] The nonce to use in the encryption
        :param encoder: The encoder to use to encode the ciphertext
        :rtype: [:class:`nacl.utils.EncryptedMessage`]
        """
        if nonce is None:
            nonce = random(self.NONCE_SIZE)

        if len(nonce) != self.NONCE_SIZE:
            raise exc.ValueError(
                "The nonce must be exactly %s bytes long" % self.NONCE_SIZE, )

        ciphertext = nacl.bindings.crypto_secretbox(plaintext, nonce,
                                                    self._key)

        encoded_nonce = encoder.encode(nonce)
        encoded_ciphertext = encoder.encode(ciphertext)

        return EncryptedMessage._from_parts(
            encoded_nonce,
            encoded_ciphertext,
            encoder.encode(nonce + ciphertext),
        )
Beispiel #29
0
        def encrypt(self, is_originator, uri, args=None, kwargs=None):
            """
            Encrypt the given WAMP URI, args and kwargs into an EncryptedPayload instance, or None
            if the URI should not be encrypted.
            """
            assert(type(uri) == six.text_type)
            assert(type(is_originator) == bool)
            assert(args is None or type(args) in (list, tuple))
            assert(kwargs is None or type(kwargs) == dict)

            box = self._get_box(is_originator, uri)

            if not box:
                return

            payload = {
                u'uri': uri,
                u'args': args,
                u'kwargs': kwargs
            }
            nonce = random(Box.NONCE_SIZE)
            payload_ser = json.dumps(payload)
            payload_encr = box.encrypt(payload_ser, nonce, encoder=Base64Encoder)
            payload_bytes = payload_encr.encode().decode('ascii')
            payload_key = None

            return EncryptedPayload(u'cryptobox', payload_key, u'json', payload_bytes)
Beispiel #30
0
def store(secret):
    while True:
        try:
            # Again, mkdir is an atomic operation on POSIX file systems.
            # Two concurrent requests cannot store data into the same
            # directory.
            sid = generate_sid()
            mkdir(join(DATA, sid))
            break
        except FileExistsError:
            continue

    key_bytes = random(SecretBox.KEY_SIZE)
    box = SecretBox(key_bytes)

    with open(join(DATA, sid, 'secret'), 'wb') as fp:
        fp.write(box.encrypt(secret.encode('UTF-8')))

    # Turn key into base64 and remove padding, because it has the
    # potential of confusing users. ("Is this part of the URL?")
    key = str(b64encode(key_bytes), 'ASCII')
    key = key.replace('/', '_')
    key = key.rstrip('=')

    return sid, key
 def _encrypt_data(self, key, data):
     assert isinstance(key, type(b"")), type(key)
     assert isinstance(data, type(b"")), type(data)
     if len(key) != SecretBox.KEY_SIZE: raise UsageError
     box = SecretBox(key)
     nonce = utils.random(SecretBox.NONCE_SIZE)
     return box.encrypt(data, nonce)
Beispiel #32
0
        def encode(self, is_originating, uri, args=None, kwargs=None):
            """
            Encrypt the given WAMP URI, args and kwargs into an EncodedPayload instance, or None
            if the URI should not be encrypted.
            """
            assert(type(is_originating) == bool)
            assert(type(uri) == six.text_type)
            assert(args is None or type(args) in (list, tuple))
            assert(kwargs is None or type(kwargs) == dict)

            box = self._get_box(is_originating, uri)

            if not box:
                # if we didn't find a crypto box, then return None, which
                # signals that the payload travel unencrypted (normal)
                return None

            payload = {
                u'uri': uri,
                u'args': args,
                u'kwargs': kwargs
            }
            nonce = random(Box.NONCE_SIZE)
            payload_ser = _json_dumps(payload).encode('utf8')

            payload_encr = box.encrypt(payload_ser, nonce, encoder=RawEncoder)

            # above returns an instance of http://pynacl.readthedocs.io/en/latest/utils/#nacl.utils.EncryptedMessage
            # which is a bytes _subclass_! hence we apply bytes() to get at the underlying plain
            # bytes "scalar", which is the concatenation of `payload_encr.nonce + payload_encr.ciphertext`
            payload_bytes = bytes(payload_encr)
            payload_key = None

            return EncodedPayload(payload_bytes, u'cryptobox', u'json', enc_key=payload_key)
Beispiel #33
0
    def generate(cls):
        """
        Generates a random :class:`~nacl.public.PrivateKey` object

        :rtype: :class:`~nacl.public.PrivateKey`
        """
        return cls(random(PrivateKey.SIZE), encoder=encoding.RawEncoder)
Beispiel #34
0
    def test_decrypt_key_no_path(self):
        key = random(32)

        enc_key = self.client.encrypt_key(key)
        self.assertNotEqual(key, enc_key)

        dec_key = self.client.decrypt_key(enc_key)
        self.assertEqual(key, dec_key)
Beispiel #35
0
    def newKey(self):
        """Generate a new encryption key.

        Returns:
            (str): encryption key
        """
        key = random(SecretBox.KEY_SIZE)
        return binascii.hexlify(key).decode("utf-8")
Beispiel #36
0
    def encrypt_payload(self, symKey, payload):
        # payload = payload.encode()
        nonce = utils.random(secret.SecretBox.NONCE_SIZE)

        box = secret.SecretBox(symKey)
        encrypted = box.encrypt(payload, nonce)

        return encrypted
Beispiel #37
0
    def setUpClass(self):
        self.my_app.db = MotorClient(**MONGODB_HOST)[MONGODB_DBNAME]

        self.my_app.executor = ThreadPoolExecutor(WORKERS)

        self.my_app.whitelist = WHITELIST

        self.my_app.hmac_key = random(size=APP_SECRETKEY_SIZE)
Beispiel #38
0
    def test_when_encrypting_with_a_key_the_decrypter_fails_when_not_using_the_shared_key(
            self):
        nonce = random(SecretBox.NONCE_SIZE)
        shared_key = random(SecretBox.KEY_SIZE)
        box = SecretBox(shared_key)
        plaintext = b'The ship has arrived at the port'
        encrypted_msg = box.encrypt(plaintext, nonce)
        nonce_str = b64encode(encrypted_msg.nonce).decode("utf-8")
        encrypted_msg_str = b64encode(encrypted_msg.ciphertext).decode("utf-8")
        message = f'{nonce_str}:{encrypted_msg_str}'

        incorrect_key = random(SecretBox.KEY_SIZE)
        decrypter = util.create_decrypter(incorrect_key)
        with self.assertRaises(Exception):
            decrypter(message)

        self.assertNotEqual(plaintext, encrypted_msg.ciphertext)
Beispiel #39
0
 def create_key(self, key_id=None):
     key = random(SecretBox.KEY_SIZE)
     if not key_id:
         h = sha256(key, HexEncoder)
         key_id = h.decode('utf-8')[:16]
     self.keys[key_id] = key
     log_debug("Key {} was created.".format(key_id))
     self.save_key(key_id)
     return key_id
Beispiel #40
0
 def _encrypt(self, plaintext):
     plaintext = plaintext.encode('utf-8')
     nonce = random(SecretBox.NONCE_SIZE)
     encrypted = self.box.encrypt(plaintext, nonce)
     ciphertext = encrypted.ciphertext
     return dict(
         salt=self.salt.encode('hex'), iterations=self.iterations,
         nonce=nonce.encode('hex'), ciphertext=ciphertext.encode('hex')
     )
Beispiel #41
0
    def generate(cls):
        """
        Generates a random :class:`~nacl.signing.SigningKey` object.

        :rtype: :class:`~nacl.signing.SigningKey`
        """
        return cls(
            random(nacl.bindings.crypto_sign_SEEDBYTES),
            encoder=encoding.RawEncoder,
        )
    def dumps(self, session_state):
        """Encrypt session state.

        :type session_state: :class:`dict` / picklable mapping
        :param session_state: the session state to be encrypted.

        :rtype: bytes
        :returns: the encrypted session state
        """
        pickled = pickle.dumps(session_state)
        nonce = random(SecretBox.NONCE_SIZE)
        return urlsafe_b64encode(self.box.encrypt(pickled, nonce))
    def dumps(self, session_state):
        """Encrypt session state.

        :type session_state: :class:`dict` / picklable mapping
        :param session_state: the session state to be encrypted.

        :rtype: bytes
        :returns: the encrypted session state
        """
        cstruct = self.serializer.dumps(session_state)
        nonce = random(SecretBox.NONCE_SIZE)
        fstruct = self.box.encrypt(cstruct, nonce)
        return urlsafe_b64encode(fstruct).rstrip(b'=')
Beispiel #44
0
 def _encrypt_data(self, key, data):
     # Without predefined roles, we can't derive predictably unique keys
     # for each side, so we use the same key for both. We use random
     # nonces to keep the messages distinct, and we automatically ignore
     # reflections.
     # TODO: HKDF(side, nonce, key) ?? include 'side' to prevent
     # reflections, since we no longer compare messages
     assert isinstance(key, type(b"")), type(key)
     assert isinstance(data, type(b"")), type(data)
     assert len(key) == SecretBox.KEY_SIZE, len(key)
     box = SecretBox(key)
     nonce = utils.random(SecretBox.NONCE_SIZE)
     return box.encrypt(data, nonce)
Beispiel #45
0
    def __init__(self, passphrase, salt=None, iterations=None):
        passphrase = passphrase.encode('utf-8')
        if salt is None:
            salt = random(16)
            iterations = self.ITERATIONS
        else:
            salt = salt.decode('hex')

        key = PBKDF2(passphrase, salt, 32, iterations)

        self.salt = salt
        self.iterations = iterations
        self.box = SecretBox(key)
Beispiel #46
0
def generate_secret(as_hex=True):
    """Generate a random, 32-byte secret.

    :type as_hex: boolean
    :param as_hex: If true, convert the secret to hex.

    :rtype: bytes
    :returns: the secret (perhaps converted to hex).
    """
    secret = random(SecretBox.KEY_SIZE)
    if as_hex:
        secret = binascii.hexlify(secret)
    return secret
Beispiel #47
0
 def _gen_equivalent_raw_keys_couple(self):
     rwk1 = bytearray(random(crypto_box_SECRETKEYBYTES))
     rwk2 = bytearray(rwk1)
     # mask rwk1 bits
     rwk1[0] &= 248
     rwk1[31] &= 127
     rwk1[31] |= 64
     # set rwk2 bits
     rwk2[0] |= 7
     rwk2[31] |= 128
     rwk2[31] &= 191
     sk1 = PrivateKey(bytes(rwk1))
     sk2 = PrivateKey(bytes(rwk2))
     return sk1, sk2
    def __init__(self, passphrase, salt=None, iterations=None):
        warn(("CoinOp no longer uses libsodium - you should only see this "
              "message in migration utilities."), DeprecationWarning)
        passphrase = passphrase.encode('utf-8')
        if salt is None:
            salt = random(16)
            iterations = self.ITERATIONS
        else:
            salt = salt.decode('hex')

        key = PBKDF2(passphrase, salt, 32, iterations)

        self.salt = salt
        self.iterations = iterations
        self.box = SecretBox(key)
Beispiel #49
0
    def __init__(
        self,
        proto,
        handler,
        own_addr,
        dest_addr,
        relay_addr=None,
        private_key=None
    ):
        """
        Create a new connection and register it with the protocol.

        Args:
            proto: Handler to underlying protocol.
            handler: Upstream recipient of received messages and
                handler of other events. Should minimally implement
                `receive_message` and `handle_shutdown`.
            own_addr: Tuple of local host address (ip, port).
            dest_addr: Tuple of remote host address (ip, port).
            relay_addr: Tuple of relay host address (ip, port).
            private_key: A private key for Curve25519, as a
                hex-encoded public.PrivateKey. The instance will
                automatically generate a new such key if one is not
                provided.

        If a relay address is specified, all outgoing packets are
        sent to that adddress, but the packets contain the address
        of their final destination. This is used for routing.
        """
        super(CryptoConnection, self).__init__(
            proto, handler, own_addr, dest_addr, relay_addr
        )

        if private_key is None:
            self._private_key = public.PrivateKey.generate()
        else:
            self._private_key = public.PrivateKey(
                private_key,
                encoder=encoding.HexEncoder
            )
        self._public_key = self._private_key.public_key
        self._crypto_box = None
        self._remote_public_key = None

        self._left_nonce_bytes = utils.random(public.Box.NONCE_SIZE // 2)
Beispiel #50
0
def encrypt(value, signingPrivateKey, realPublicKey):
    """encrypt and sign a value, and base64-encode the result

    :param value: a secret
    :type value: string
    :param signingPrivateKey: base64 encoded NaCl private key
    :type signingPrivateKey: string
    :param realPublicKey: base64 encoded NaCl private key
    :type realPublicKey: string
    :rtype: string
    """
    signingPrivateKey = npublic.PrivateKey(base64.decodestring(signingPrivateKey))
    realPublicKey = npublic.PublicKey(base64.decodestring(realPublicKey))
    box = npublic.Box(signingPrivateKey, realPublicKey)
    nonce = nutils.random(npublic.Box.NONCE_SIZE)
    encrypted = box.encrypt(value, nonce)
    encoded = base64.encodestring(encrypted)
    oneline = "".join(encoded.splitlines())
    return oneline
    def setUpClass(cls):
        cls.public_ip = '123.45.67.89'
        cls.port = 12345
        cls.own_addr = (cls.public_ip, cls.port)
        cls.addr1 = ('132.54.76.98', 54321)
        cls.addr2 = ('231.76.45.89', 15243)
        cls.privkey1_hex = '71d1054068b224a4d9013104881dc7f46c6fec9a618f4574ae21059723e6c4f8'
        cls.privkey1 = public.PrivateKey(
            cls.privkey1_hex,
            encoder=encoding.HexEncoder
        )
        cls.pubkey1 = cls.privkey1.public_key
        cls.pubkey1_bytes = cls.pubkey1.encode(encoder=encoding.RawEncoder)
        
        cls.privkey2_hex = '4c107b7844368d0fb608f3d91ae194f2d62c7ff91b713e5b05c279e8b7fc61b3'
        cls.privkey2 = public.PrivateKey(
            cls.privkey2_hex,
            encoder=encoding.HexEncoder
        )
        cls.pubkey2 = cls.privkey2.public_key
        cls.pubkey2_bytes = cls.pubkey2.encode(encoder=encoding.RawEncoder)

        cls.remote_crypto_box = public.Box(cls.privkey2, cls.pubkey1)
        cls.nonce = utils.random(cls.remote_crypto_box.NONCE_SIZE)

        cls.local_crypto_box = public.Box(cls.privkey1, cls.pubkey2)

        cls.privkey3_hex = '40246691a4362a220606dd302b03e992b5b5fe21026377fa56c9fe3f5afbcbd0'
        cls.privkey3 = public.PrivateKey(
            cls.privkey3_hex,
            encoder=encoding.HexEncoder
        )
        cls.pubkey3 = cls.privkey3.public_key
        cls.pubkey3_bytes = cls.pubkey3.encode(encoder=encoding.RawEncoder)

        cls.other_crypto_box = public.Box(cls.privkey3, cls.pubkey1)
Beispiel #52
0
 def keypair(cls):
     pri = random(cls.PRIVATE_KEY_SIZE)
     pub = cls.public_key(pri)
     return pri, pub
Beispiel #53
0
 def _encrypt_data(self, key, data):
     assert len(key) == SecretBox.KEY_SIZE
     box = SecretBox(key)
     nonce = utils.random(SecretBox.NONCE_SIZE)
     return box.encrypt(data, nonce)
Beispiel #54
0
 def generate(cls):
     return cls(random(PrivateKey.SIZE), encoder=encoding.RawEncoder)
Beispiel #55
0
    def generate(cls, email: str, name: str, passphrase: str) -> typing.Tuple['Key', 'Key']:
        """
        Generate a new public/private key pair.

        This handles encipherment of the private keys.

        :param email: The email for the initial User ID.
        :param name: The name for the initial User ID.
        :param passphrase: The passphrase to encrypt the private key with.
        :return: A tuple containing a public and a private key.
        """
        privatekey = public.PrivateKey.generate()
        publickey = privatekey.public_key
        assert isinstance(privatekey, public.PrivateKey)
        assert isinstance(publickey, public.PublicKey)

        pub, priv = publickey.encode(), privatekey.encode()

        # Generate the signing key seed.
        seed = random(32)
        # Create the signing private key, temporary usage to extract the verify key.
        s_privatekey = signing.SigningKey(seed)
        s_publickey = s_privatekey.verify_key

        s_pub = s_publickey.encode()

        # Encrypt both private keys.
        key = derive_passphrase(passphrase.encode())
        # Use a random nonce, for now.
        nonce1 = random(SecretBox.NONCE_SIZE)
        nonce2 = random(SecretBox.NONCE_SIZE)

        # Encrypt both.
        sbox1 = SecretBox(key)
        sbox2 = SecretBox(key)

        priv = sbox1.encrypt(priv, nonce1)
        # Don't encrypt the s_privatekey; encrypt the seed.
        s_priv = sbox2.encrypt(seed, nonce2)

        # Create a pair of Keys.
        public_key = Key(public_key=pub, public_signing_key=s_pub)
        private_key = Key(private_key=priv.ciphertext, private_signing_seed=s_priv.ciphertext,
                          private_nonce=priv.nonce, private_signing_nonce=s_priv.nonce)

        del privatekey, priv, s_privatekey, s_priv
        # Force a GC collect.
        gc.collect()

        # Create the requested User ID.
        u = UserID(0, email, name)
        # We only add the user ID to the public key.
        public_key.userid = u

        # Generate the self-signature.
        to_hash = u.get_hash()
        # Sign the message using the private key.
        signature = private_key.sign_raw(passphrase, to_hash)
        public_key.self_signature = signature

        verified = public_key.verify_self_signature()
        if not verified:
            raise exc.BadSignature("The self-signature was invalid.")

        return public_key, private_key
Beispiel #56
0
def init(server, username, keydir, action, message, recipients):
    """ SHSM CLI client. """

    global serverurl
    serverurl = server

    if action == "register":
        master_signing_key = SigningKey.generate()
        device_signing_key = SigningKey.generate()
        device_private_key = PrivateKey.generate()

        enc_master_verify_key = master_signing_key.verify_key.encode(encoder=HexEncoder)
        register(username, enc_master_verify_key)

        # TODO: make sure keydir exists

        save_key(master_signing_key.encode(encoder=HexEncoder), keydir + "/master_signing_key")
        save_key(device_signing_key.encode(encoder=HexEncoder), keydir + "/device_signing_key")
        save_key(device_private_key.encode(encoder=HexEncoder), keydir + "/device_private_key")

    else:
        try:
            master_signing_key = SigningKey(load_key(keydir + "/master_signing_key"), encoder=HexEncoder)
            device_signing_key = SigningKey(load_key(keydir + "/device_signing_key"), encoder=HexEncoder)
            device_private_key = PrivateKey(load_key(keydir + "/device_private_key"), encoder=HexEncoder)
        except TypeError:
            print "bad key, exiting."
            exit()

        if action == "add-device":

            enc_device_verify_key = device_signing_key.verify_key.encode(encoder=HexEncoder)
            enc_signed_device_verify_key = b64encode(master_signing_key.sign(enc_device_verify_key))

            enc_device_public_key = device_private_key.public_key.encode(encoder=HexEncoder)
            enc_signed_device_public_key = b64encode(master_signing_key.sign(enc_device_public_key))

            add_device(username, enc_signed_device_verify_key, enc_signed_device_public_key)

        if action == "send-message":

            ephemeral_key = PrivateKey.generate()
            enc_ephemeral_public_key = b64encode(
                device_signing_key.sign(ephemeral_key.public_key.encode(encoder=HexEncoder))
            )

            # TODO:: should sign binary text, no? b"bob"
            destination_usernames = recipients.split(",")
            enc_dest_usernames = b64encode(
                device_signing_key.sign(json.dumps({"destination_usernames": destination_usernames}))
            )
            symmetric_key = random(SecretBox.KEY_SIZE)
            symmetric_box = SecretBox(symmetric_key)
            nonce = random(SecretBox.NONCE_SIZE)
            msg_manifest = {}
            msg_manifest["recipients"] = {}
            msg_manifest["msg"] = b64encode(symmetric_box.encrypt(str(message), nonce))

            for dest_user in destination_usernames:
                msg_manifest["recipients"][dest_user] = {}

                for recipient_key in get_recipient_keys(
                    device_signing_key.verify_key.encode(encoder=HexEncoder),
                    b64encode(device_signing_key.sign(str(dest_user))),
                ):

                    # TODO:: should sign binary text, no?
                    crypt_box = Box(ephemeral_key, recipient_key)
                    nonce = random(Box.NONCE_SIZE)
                    crypt_key = b64encode(crypt_box.encrypt(symmetric_key, nonce))
                    dest_key = recipient_key.encode(encoder=HexEncoder)
                    msg_manifest["recipients"][dest_user][dest_key] = crypt_key

            enc_signed_crypt_msg = b64encode(device_signing_key.sign(json.dumps(msg_manifest)))

            send_message(
                device_signing_key.verify_key.encode(encoder=HexEncoder),
                enc_dest_usernames,
                enc_signed_crypt_msg,
                enc_ephemeral_public_key,
            )

        if action == "get-messages":

            enc_device_verify_key = device_signing_key.verify_key.encode(encoder=HexEncoder)
            enc_signed_device_verify_key = b64encode(device_signing_key.sign(enc_device_verify_key))
            messages = get_messages(enc_device_verify_key, enc_signed_device_verify_key)

            for message_public_key in messages["messages"].keys():
                try:
                    crypto_box = Box(device_private_key, PublicKey(b64decode(message_public_key), encoder=HexEncoder))
                except TypeError:
                    print "not a valid public key"
                    exit()
                packed_msg = json.loads(messages["messages"][message_public_key])
                msg_manifest = json.loads(b64decode(packed_msg["message_manifest"]))
                dest_pub_key = device_private_key.public_key.encode(encoder=HexEncoder)
                symmetric_key = crypto_box.decrypt(b64decode(msg_manifest["recipients"][username][dest_pub_key]))
                symmetric_box = SecretBox(symmetric_key)
                print ("From: %s\nMessage: %s") % (
                    packed_msg["reply_to"],
                    symmetric_box.decrypt(b64decode(msg_manifest["msg"])),
                )
Beispiel #57
0
 def get_fake_key(self):
     return random(SecretBox.KEY_SIZE)
Beispiel #58
0
def test_generate_private_key_from_random_seed():
    PrivateKey.from_seed(random(PrivateKey.SEED_SIZE))
Beispiel #59
0
 def test_sk_and_pk_hashes_are_different(self):
     sk = PrivateKey(random(crypto_box_SECRETKEYBYTES))
     assert hash(sk) != hash(sk.public_key)
Beispiel #60
0
 def create_node(name):
     secret = random(32)
     # FIXME: set blockchain/network correctly
     tree = bip32.Wallet.from_master_secret(secret, netcode='XTN')
     return tree