Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General encryption #75

Merged
merged 22 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
968ef53
Working on exposing onion request encryption functions
mpretty-cyro Nov 23, 2023
8e6a31c
Progressed the onion request prepare and decrypt functions
mpretty-cyro Nov 27, 2023
de56efd
Got the onion requests working via the C interface
mpretty-cyro Nov 28, 2023
10c073a
Updated the onion request interface to be builder-based
mpretty-cyro Nov 29, 2023
973e78d
Exposed required crypto functions, started on SessionBlindingProtocol
mpretty-cyro Dec 4, 2023
01a1f46
Got SessionBlindingProtocol for blind15 working, blind25 still WIP
mpretty-cyro Dec 5, 2023
d1c0ed0
Exposed hash & random generation, ONS, PN & blind25 message decryption
mpretty-cyro Dec 6, 2023
4d3a3f2
Added some error checking to the hash generation
mpretty-cyro Dec 7, 2023
bb99bf5
Fixed mistake with sessionId to blindedId comparison, tweaks to docs
mpretty-cyro Dec 7, 2023
b8db49d
Fixed some bugs and started working on unit tests
mpretty-cyro Dec 8, 2023
6e3ec74
Fixed the broken tests
mpretty-cyro Dec 11, 2023
daca300
Started adding unit tests for new crypto functions
mpretty-cyro Dec 11, 2023
5c64ae8
Added more unit tests
mpretty-cyro Dec 12, 2023
cf4f833
Added some missing includes and fixed a build error
mpretty-cyro Dec 12, 2023
efe8cc9
More import fixes
mpretty-cyro Dec 12, 2023
2e2a79a
Formatting
mpretty-cyro Dec 13, 2023
fb38375
25 blinding fixes and improvements
jagerman Jan 9, 2024
1d16662
Updated decrypt_from_blinded_recipient to support outbox messages
mpretty-cyro Jan 10, 2024
0be33f0
Updated comment and formatting
mpretty-cyro Jan 10, 2024
41ad0e1
Fixed a ResponseParser bug and fallback to AES_GCM for legacy PN server
mpretty-cyro Jan 25, 2024
056bbd6
Merge remote-tracking branch 'upstream/dev' into general-encryption
mpretty-cyro Jan 25, 2024
c7b7dea
Formatting
mpretty-cyro Jan 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/build*/
/compile_commands.json
/.cache/
/.vscode/
116 changes: 116 additions & 0 deletions include/session/blinding.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>

#include "export.h"

/// API: crypto/session_blind15_key_pair
///
/// This function attempts to generate a blind15 key pair.
///
/// Inputs:
/// - `ed25519_seckey` -- [in] the Ed25519 private key of the sender (64 bytes).
/// - `server_pk` -- [in] the public key of the open group server to generate the
/// blinded id for (32 bytes).
/// - `blinded_pk_out` -- [out] pointer to a buffer of at least 32 bytes where the blinded_pk will
/// be written if generation was successful.
/// - `blinded_sk_out` -- [out] pointer to a buffer of at least 32 bytes where the blinded_sk will
/// be written if generation was successful.
///
/// Outputs:
/// - `bool` -- True if the key was successfully generated, false if generation failed.
LIBSESSION_EXPORT bool session_blind15_key_pair(
const unsigned char* ed25519_seckey, /* 64 bytes */
const unsigned char* server_pk, /* 32 bytes */
unsigned char* blinded_pk_out, /* 32 byte output buffer */
unsigned char* blinded_sk_out /* 32 byte output buffer */);

/// API: crypto/session_blind25_key_pair
///
/// This function attempts to generate a blind25 key pair.
///
/// Inputs:
/// - `ed25519_seckey` -- [in] the Ed25519 private key of the sender (64 bytes).
/// - `server_pk` -- [in] the public key of the open group server to generate the
/// blinded id for (32 bytes).
/// - `blinded_pk_out` -- [out] pointer to a buffer of at least 32 bytes where the blinded_pk will
/// be written if generation was successful.
/// - `blinded_sk_out` -- [out] pointer to a buffer of at least 32 bytes where the blinded_sk will
/// be written if generation was successful.
///
/// Outputs:
/// - `bool` -- True if the key was successfully generated, false if generation failed.
LIBSESSION_EXPORT bool session_blind25_key_pair(
const unsigned char* ed25519_seckey, /* 64 bytes */
const unsigned char* server_pk, /* 32 bytes */
unsigned char* blinded_pk_out, /* 32 byte output buffer */
unsigned char* blinded_sk_out /* 32 byte output buffer */);

/// API: crypto/session_blind15_sign
///
/// This function attempts to generate a signature for a message using a blind15 private key.
///
/// Inputs:
/// - `ed25519_seckey` -- [in] the Ed25519 private key of the sender (64 bytes).
/// - `server_pk` -- [in] the public key of the open group server to generate the
/// blinded id for (32 bytes).
/// - `msg` -- [in] Pointer to a data buffer containing the message to generate a signature for.
/// - `msg_len` -- [in] Length of `msg`
/// - `blinded_sig_out` -- [out] pointer to a buffer of at least 64 bytes where the signature will
/// be written if generation was successful.
///
/// Outputs:
/// - `bool` -- True if the signature was successfully generated, false if generation failed.
LIBSESSION_EXPORT bool session_blind15_sign(
const unsigned char* ed25519_seckey, /* 64 bytes */
const unsigned char* server_pk, /* 32 bytes */
const unsigned char* msg,
size_t msg_len,
unsigned char* blinded_sig_out /* 64 byte output buffer */);

/// API: crypto/session_blind25_sign
///
/// This function attempts to generate a signature for a message using a blind25 private key.
///
/// Inputs:
/// - `ed25519_seckey` -- [in] the Ed25519 private key of the sender (64 bytes).
/// - `server_pk` -- [in] the public key of the open group server to generate the
/// blinded id for (32 bytes).
/// - `msg` -- [in] Pointer to a data buffer containing the message to generate a signature for.
/// - `msg_len` -- [in] Length of `msg`
/// - `blinded_sig_out` -- [out] pointer to a buffer of at least 64 bytes where the signature will
/// be written if generation was successful.
///
/// Outputs:
/// - `bool` -- True if the signature was successfully generated, false if generation failed.
LIBSESSION_EXPORT bool session_blind25_sign(
const unsigned char* ed25519_seckey, /* 64 bytes */
const unsigned char* server_pk, /* 32 bytes */
const unsigned char* msg,
size_t msg_len,
unsigned char* blinded_sig_out /* 64 byte output buffer */);

/// API: crypto/session_blind25_sign
///
/// This function attempts to generate a signature for a message using a blind25 private key.
///
/// Inputs:
/// - `session_id` -- [in] the session_id to compare (66 bytes with a 05 prefix).
/// - `blinded_id` -- [in] the blinded_id to compare, can be either 15 or 25 blinded (66 bytes).
/// - `server_pk` -- [in] the public key of the open group server to the blinded id came from (64
/// bytes).
///
/// Outputs:
/// - `bool` -- True if the session_id matches the blinded_id, false if not.
LIBSESSION_EXPORT bool session_id_matches_blinded_id(
const char* session_id, /* 66 bytes */
const char* blinded_id, /* 66 bytes */
const char* server_pk /* 64 bytes */);

#ifdef __cplusplus
}
#endif
94 changes: 91 additions & 3 deletions include/session/blinding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,25 @@ namespace session {
///
/// This (R, S) signature is then Ed25519-verifiable using pubkey kA.

/// Returns the blinding factor for 15 blinding. Typically this isn't used directly, but is
/// exposed for debugging/testing. Takes server pk in bytes, not hex.
uc32 blind15_factor(ustring_view server_pk);

/// Returns the blinding factor for 25 blinding. Typically this isn't used directly, but is
/// exposed for debugging/testing. Takes session id and pk in bytes, not hex. session id can
/// be 05-prefixed (33 bytes) or unprefixed (32 bytes).
std::array<unsigned char, 32> blind25_factor(ustring_view session_id, ustring_view server_pk);
/// exposed for debugging/testing. Takes session id and server pk in bytes, not hex. session
/// id can be 05-prefixed (33 bytes) or unprefixed (32 bytes).
uc32 blind25_factor(ustring_view session_id, ustring_view server_pk);

/// Computes the two possible 15-blinded ids from a session id and server pubkey. Values accepted
/// and returned are hex-encoded.
std::array<std::string, 2> blind15_id(std::string_view session_id, std::string_view server_pk);

/// Similar to the above, but takes the session id and pubkey as byte values instead of hex, and
/// returns a single 33-byte value (instead of a 66-digit hex value). Unlike the string version,
/// session_id here may be passed unprefixed (i.e. 32 bytes instead of 33 with the 05 prefix). Only
/// the *positive* possible ID is returned: the alternative can be computed by flipping the highest
/// bit of byte 32, i.e.: `result[32] ^= 0x80`.
ustring blind15_id(ustring_view session_id, ustring_view server_pk);

/// Computes the 25-blinded id from a session id and server pubkey. Values accepted and
/// returned are hex-encoded.
Expand All @@ -69,6 +84,70 @@ std::string blind25_id(std::string_view session_id, std::string_view server_pk);
/// be passed unprefixed (i.e. 32 bytes instead of 33 with the 05 prefix).
ustring blind25_id(ustring_view session_id, ustring_view server_pk);

/// Computes the 15-blinded id from a 32-byte Ed25519 pubkey, i.e. from the known underlying Ed25519
/// pubkey behind a (X25519) Session ID. Unlike blind15_id, knowing the true Ed25519 pubkey allows
/// thie method to compute the correct sign and so using this does not require considering that the
/// resulting blinded ID might need to have a sign flipped.
///
/// If the `session_id` is a non-null pointer then it must point at an empty string to be populated
/// with the session_id associated with `ed_pubkey`. This is here for consistency with
/// `blinded25_id_from_ed`, but unlike the 25 version, this value is not read if non-empty, and is
/// not an optimization (that is: it is purely for convenience and is no more efficient to use this
/// than it is to compute it yourself).
ustring blinded15_id_from_ed(
ustring_view ed_pubkey, ustring_view server_pk, ustring* session_id = nullptr);

/// Computes the 25-blinded id from a 32-byte Ed25519 pubkey, i.e. from the known underlying Ed25519
/// pubkey behind a (X25519) Session ID. This will be the same as blind25_id (if given the X25519
/// pubkey that the Ed25519 converts to), but is more efficient when the Ed25519 pubkey is already
/// known.
///
/// The session_id argument is provided to optimize input or output of the session ID derived from
/// the Ed25519 pubkey: if already computed, this argument can be a pointer to a 33-byte string
/// containing the precomputed value (to avoid needing to compute it again). If unknown but needed
/// then a pointer to an empty string can be given to computed and stored the value here. Otherwise
/// (if omitted or nullptr) then the value will temporarily computed within the function.
ustring blinded25_id_from_ed(
ustring_view ed_pubkey, ustring_view server_pk, ustring* session_id = nullptr);

/// Computes a 15-blinded key pair.
///
/// Takes the Ed25519 secret key (64 bytes, or 32-byte seed) and the server pubkey (in hex (64
/// digits) or bytes (32 bytes)). Returns the blinded public key and private key (NOT a seed).
///
/// Can optionally also return the blinding factor, k, by providing a pointer to a uc32 (or
/// cleared_uc32); if non-nullptr then k will be written to it.
///
/// It is recommended to pass the full 64-byte libsodium-style secret key for `ed25519_sk` (i.e.
/// seed + appended pubkey) as with just the 32-byte seed the public key has to be recomputed.
std::pair<uc32, cleared_uc32> blind15_key_pair(
ustring_view ed25519_sk, ustring_view server_pk, uc32* k = nullptr);

/// Computes a 25-blinded key pair.
///
/// Takes the Ed25519 secret key (64 bytes, or 32-byte seed) and the server pubkey (in hex (64
/// digits) or bytes (32 bytes)). Returns the blinded public key and private key (NOT a seed).
///
/// Can optionally also return the blinding factor, k', by providing a pointer to a uc32 (or
/// cleared_uc32); if non-nullptr then k' will be written to it, where k' = ±k. Here, `k'` can be
/// negative to cancel out a negative in the true pubkey, which the remote client will always assume
/// is not present when it does a Session ID -> Ed25519 conversion for blinding purposes.
///
/// It is recommended to pass the full 64-byte libsodium-style secret key for `ed25519_sk` (i.e.
/// seed + appended pubkey) as with just the 32-byte seed the public key has to be recomputed.
std::pair<uc32, cleared_uc32> blind25_key_pair(
ustring_view ed25519_sk, ustring_view server_pk, uc32* k_prime = nullptr);

/// Computes a verifiable 15-blinded signature that validates with the blinded pubkey that would
/// be returned from blind15_key_pair().
///
/// Takes the Ed25519 secret key (64 bytes, or 32-byte seed) and the server pubkey (in hex (64
/// digits) or bytes (32 bytes)). Returns the 64-byte signature.
///
/// It is recommended to pass the full 64-byte libsodium-style secret key for `ed25519_sk` (i.e.
/// seed + appended pubkey) as with just the 32-byte seed the public key has to be recomputed.
ustring blind15_sign(ustring_view ed25519_sk, std::string_view server_pk_in, ustring_view message);

/// Computes a verifiable 25-blinded signature that validates with the blinded pubkey that would
/// be returned from blind25_id().
///
Expand All @@ -79,4 +158,13 @@ ustring blind25_id(ustring_view session_id, ustring_view server_pk);
/// seed + appended pubkey) as with just the 32-byte seed the public key has to be recomputed.
ustring blind25_sign(ustring_view ed25519_sk, std::string_view server_pk, ustring_view message);

/// Takes in a standard session_id and returns a flag indicating whether it matches the given
/// blinded_id for a given server_pk.
///
/// Takes either a 15 or 25 blinded_id (66 bytes) and the server pubkey (64 bytes).
///
/// Returns a flag indicating whether the session_id matches the blinded_id.
bool session_id_matches_blinded_id(
std::string_view session_id, std::string_view blinded_id, std::string_view server_pk);

} // namespace session
61 changes: 61 additions & 0 deletions include/session/curve25519.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>

#include "export.h"

/// API: crypto/session_curve25519_key_pair
///
/// Generates a random curve25519 key pair.
///
/// Inputs:
/// - `curve25519_pk_out` -- [out] pointer to a buffer of 32 bytes where the public key will be
/// written.
/// - `curve25519_sk_out` -- [out] pointer to a buffer of 32 bytes where the private key will be
/// written.
///
/// Outputs:
/// - `bool` -- True if the seed was successfully retrieved, false if failed.
LIBSESSION_EXPORT bool session_curve25519_key_pair(
unsigned char* curve25519_pk_out, /* 32 byte output buffer */
unsigned char* curve25519_sk_out /* 32 byte output buffer */);

/// API: crypto/session_to_curve25519_pubkey
///
/// Generates a curve25519 public key for an ed25519 public key.
///
/// Inputs:
/// - `ed25519_pubkey` -- the ed25519 public key (32 bytes).
/// - `curve25519_pk_out` -- [out] pointer to a buffer of 32 bytes where the public key will be
/// written.
///
/// Outputs:
/// - `bool` -- True if the public key was successfully generated, false if failed.
LIBSESSION_EXPORT bool session_to_curve25519_pubkey(
const unsigned char* ed25519_pubkey, /* 32 bytes */
unsigned char* curve25519_pk_out /* 32 byte output buffer */);

/// API: crypto/session_to_curve25519_seckey
///
/// Generates a curve25519 secret key given given either a libsodium-style secret key, 64
/// bytes. Can also be passed as a 32-byte seed.
///
/// Inputs:
/// - `ed25519_seckey` -- [in] the libsodium-style secret key, 64 bytes. Can also be
/// passed as a 32-byte seed.
/// - `curve25519_sk_out` -- [out] pointer to a buffer of 32 bytes where the secret key will be
/// written.
///
/// Outputs:
/// - `bool` -- True if the secret key was successfully generated, false if failed.
LIBSESSION_EXPORT bool session_to_curve25519_seckey(
const unsigned char* ed25519_seckey, /* 64 bytes */
unsigned char* curve25519_sk_out /* 32 byte output buffer */);

#ifdef __cplusplus
}
#endif
35 changes: 35 additions & 0 deletions include/session/curve25519.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <array>

#include "types.hpp"

namespace session::curve25519 {

/// Generates a random curve25519 key pair
std::pair<std::array<unsigned char, 32>, std::array<unsigned char, 64>> curve25519_key_pair();

/// API: curve25519/to_curve25519_pubkey
///
/// Generates a curve25519 public key for an ed25519 public key.
///
/// Inputs:
/// - `ed25519_pubkey` -- the ed25519 public key.
///
/// Outputs:
/// - The curve25519 public key
std::array<unsigned char, 32> to_curve25519_pubkey(ustring_view ed25519_pubkey);

/// API: curve25519/to_curve25519_seckey
///
/// Generates a curve25519 secret key given given a libsodium-style secret key, 64
/// bytes.
///
/// Inputs:
/// - `ed25519_seckey` -- the libsodium-style secret key, 64 bytes.
///
/// Outputs:
/// - The curve25519 secret key
std::array<unsigned char, 32> to_curve25519_seckey(ustring_view ed25519_seckey);

} // namespace session::curve25519
Loading