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

Implement SECP256K1 with AES-GCM 256 #7

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ target_include_directories(${PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/lib/ccrush/include
)

target_compile_definitions(${PROJECT_NAME}
PUBLIC CONFIG_CECIES_USE_SALT=1
)

get_target_property(${PROJECT_NAME}_DEPS_TARGETS ${PROJECT_NAME} LINK_LIBRARIES)

if (${${PROJECT_NAME}_ENABLE_EXAMPLES})
Expand Down
10 changes: 9 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,12 @@ target_include_directories(cecies_example_02 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/.

add_executable(cecies_example_03 ${CMAKE_CURRENT_LIST_DIR}/example03.c)
target_link_libraries(cecies_example_03 PRIVATE cecies)
target_include_directories(cecies_example_03 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../lib/mbedtls/include)
target_include_directories(cecies_example_03 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../lib/mbedtls/include)

add_executable(cecies_example_04 ${CMAKE_CURRENT_LIST_DIR}/example04.c)
target_link_libraries(cecies_example_04 PRIVATE cecies)
target_include_directories(cecies_example_04 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../lib/mbedtls/include)

add_executable(cecies_example_05 ${CMAKE_CURRENT_LIST_DIR}/example05.c)
target_link_libraries(cecies_example_05 PRIVATE cecies)
target_include_directories(cecies_example_05 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../lib/mbedtls/include)
59 changes: 59 additions & 0 deletions examples/example04.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright 2020 Raphael Beck

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <cecies/keygen.h>
#include <mbedtls/platform_util.h>

/*
* This example shows how to generate CECIES keypairs.
* The results are written into a cecies_SECP256K1_keypair struct instance
* and are basically the private key, which is a bignum (known in MbedTLS as an mbedtls_mpi)
* written as a binary array (BIG endian) and exported as hex string into cecies_curve448_keypair.private_key
* and the public key, which is a point on the curve (mbedtls_ecp_point) and also exported into cecies_SECP256K1_keypair.public_key as a hex string.
*/

int main(int argc, char* argv[])
{
cecies_enable_fprintf(); // Allow fprintf in case errors occur and need to be fprintf'ed.
printf("\n---- CECIES ----\n-- Example 04 --\n\n");

const char* additional_entropy = argc > 1 ? argv[1] : NULL;
const size_t additional_entropy_length = additional_entropy ? strlen(additional_entropy) : 0;

if (additional_entropy != NULL)
{
printf("Using additional entropy string \"%s\"\n", additional_entropy);
}

cecies_SECP256K1_keypair keypair;

int r = cecies_generate_secp256k1_keypair(&keypair, (unsigned char*)additional_entropy, additional_entropy_length);

if (r != 0)
{
printf("\nCECIES example key-pair generation failed! cecies_generate_SECP256K1_keypair returned %d\n", r);
return r;
}

printf("\nSuccessfully generated CECIES key-pair (SECP256K1)\n\nPrivate key: %s\n\nPublic key: %s\n\n", keypair.private_key.hexstring, keypair.public_key.hexstring);

mbedtls_platform_zeroize(&keypair, sizeof(keypair));
cecies_disable_fprintf();
return r;
}
67 changes: 67 additions & 0 deletions examples/example05.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@

/*
Copyright 2020 Raphael Beck

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <cecies/util.h>
#include <cecies/encrypt.h>
#include <cecies/decrypt.h>

/*
* This is the example test string to encrypt and decrypt.
*/
static const char TEST_STRING[] = "Doctor Freeman. I realize this moment may not be the most convenient for a heart-to-heart, but I had to wait until your friends were otherwise occupied. Hm. There was a time they cared nothing for Miss Vance... When their only experience of humanity was a crowbar coming at them down a steel corridor.";

static const cecies_SECP256K1_pub_key TEST_PUBLIC_KEY = { .hexstring = "049ff6a73c7ac3ef7972ee0ac53223c91b1f1bc461fd503565ae455c1b9f1d50c70c02891fdbd3cdd995831a53f9d6f14f4bf866d1f6cb62b08506660e537a5c8e" };
static const cecies_SECP256K1_priv_key TEST_PRIVATE_KEY = { .hexstring = "142743f6471061101916ed63896254a2bd078b12c56bd4acdbebfe4ce1472aa1" };

int main(void)
{
int s = 1;

// sizeof(TEST_STRING) instead of strlen(TEST_STRING) because we also want to encrypt the NUL-terminator character along. Never forget the NUL-terminator in C-strings!
const size_t TEST_STRING_LENGTH = sizeof(TEST_STRING);

printf("\n---- CECIES ----\n-- Example 05 --\n\n");
printf("Encrypting the following string:\n\n%s\n\n", TEST_STRING);

uint8_t* encrypted_string;
size_t encrypted_string_length;

s = cecies_secp256k1_encrypt((uint8_t*)TEST_STRING, TEST_STRING_LENGTH, 0, TEST_PUBLIC_KEY, &encrypted_string, &encrypted_string_length, 1);

if (s != 0)
{
printf("Encryption failed! \"cecies_SECP256K1_encrypt\" returned: %d\n", s);
return s;
}

printf("Encrypted string >>> base64:\n\n%s\n\nStatus code: %d\n\n", encrypted_string, s);

size_t decrypted_string_length;
char* decrypted_string;

s = cecies_secp256k1_decrypt(encrypted_string, encrypted_string_length, 1, TEST_PRIVATE_KEY, (uint8_t**)&decrypted_string, &decrypted_string_length);

printf("Decrypted string:\n\n%s\n\nStatus code: %d\n\n", decrypted_string, s);

cecies_free(encrypted_string);
cecies_free(decrypted_string);

return s;
}
3 changes: 3 additions & 0 deletions include/cecies/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ extern "C" {
*/
#define CECIES_X448_KEY_SIZE 56

#define SECP256K1_PRIV_KEY_SIZE 32
#define SECP256K1_PUB_KEY_SIZE 65

/*
* Some error codes:
*/
Expand Down
2 changes: 2 additions & 0 deletions include/cecies/decrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ CECIES_API int cecies_curve25519_decrypt(const uint8_t* encrypted_data, size_t e
*/
CECIES_API int cecies_curve448_decrypt(const uint8_t* encrypted_data, size_t encrypted_data_length, int encrypted_data_base64, cecies_curve448_key private_key, uint8_t** output, size_t* output_length);

CECIES_API int cecies_secp256k1_decrypt(const uint8_t* encrypted_data, size_t encrypted_data_length, int encrypted_data_base64, cecies_SECP256K1_priv_key private_key, uint8_t** output, size_t* output_length);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
2 changes: 2 additions & 0 deletions include/cecies/encrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ CECIES_API int cecies_curve25519_encrypt(const uint8_t* data, size_t data_length
*/
CECIES_API int cecies_curve448_encrypt(const uint8_t* data, size_t data_length, int compress, cecies_curve448_key public_key, uint8_t** output, size_t* output_length, int output_base64);

CECIES_API int cecies_secp256k1_encrypt(const uint8_t* data, size_t data_length, int compress, cecies_SECP256K1_pub_key public_key, uint8_t** output, size_t* output_length, int output_base64);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
2 changes: 2 additions & 0 deletions include/cecies/keygen.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ CECIES_API int cecies_generate_curve25519_keypair(cecies_curve25519_keypair* out
*/
CECIES_API int cecies_generate_curve448_keypair(cecies_curve448_keypair* output, const uint8_t* additional_entropy, size_t additional_entropy_length);

CECIES_API int cecies_generate_secp256k1_keypair(cecies_SECP256K1_keypair * output, const uint8_t* additional_entropy, size_t additional_entropy_length);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
44 changes: 44 additions & 0 deletions include/cecies/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ extern "C" {
#define CECIES_API
#endif



/**
* Contains a Curve25519 key, encoded as a NUL-terminated hex-string.
*/
Expand All @@ -50,6 +52,30 @@ typedef struct cecies_curve25519_key
char hexstring[64 + 1];
} cecies_curve25519_key;

/**
* Contains a Curve key, encoded as a NUL-terminated hex-string.
*/
typedef struct cecies_SECP256K1_priv_key
{
/**
* Hex-encoded string of a 32-byte SECP256K1 key. <p>
* The 65th character is the NUL-terminator.
*/
char hexstring[64 + 1];
} cecies_SECP256K1_priv_key;

/**
* Contains a Curve key, encoded as a NUL-terminated hex-string.
*/
typedef struct cecies_SECP256K1_pub_key
{
/**
* Hex-encoded string of a 65-byte SECP256K1 key. <p>
* The 65th character is the NUL-terminator.
*/
char hexstring[130 + 1];
} cecies_SECP256K1_pub_key;

/**
* Contains a stack-allocated cecies_curve25519_key keypair.
*/
Expand All @@ -68,6 +94,24 @@ typedef struct cecies_curve25519_keypair
cecies_curve25519_key private_key;
} cecies_curve25519_keypair;

/**
* Contains a stack-allocated cecies_curve25519_key keypair.
*/
typedef struct cecies_SECP256K1_keypair
{
/**
* The public key (formatted as a hex string). <p>
* 130 bytes of hex string + 1 NUL-terminator.
*/
cecies_SECP256K1_pub_key public_key;

/**
* The private key (formatted as a hex string). <p>
* 64 bytes of hex string + 1 NUL-terminator.
*/
cecies_SECP256K1_priv_key private_key;
} cecies_SECP256K1_keypair;

/**
* Contains a Curve448 key, encoded as a NUL-terminated hex-string.
*/
Expand Down
24 changes: 21 additions & 3 deletions include/cecies/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,23 @@ extern "C" {
*/
#define CECIES_MAX(x, y) (((x) > (y)) ? (x) : (y))

#define CECIES_IV_LEN 16
#define CECIES_TAG_LEN 16

#if (CONFIG_CECIES_USE_SALT)
#define CECIES_SALT_LEN 32
#else
#define CECIES_SALT_LEN 0
#endif // CONFIG_CECIES_USE_SALT

#define CECIES_ENCRYPTED_OUTPUT_START 0

#define CECIES_EPH_POS(eph_len) CECIES_ENCRYPTED_OUTPUT_START
#define CECIES_IV_POS(eph_len) (eph_len)
#define CECIES_TAG_POS(eph_len) (CECIES_IV_POS(eph_len) + CECIES_IV_LEN)
#define CECIES_SALT_POS(eph_len) (CECIES_TAG_POS(eph_len) + CECIES_TAG_LEN)
#define CECIES_CIPHER_TEXT_POS(eph_len) (CECIES_SALT_POS(eph_len) + CECIES_SALT_LEN)

/**
* Calculates the length of an AES-CBC ciphertext given a specific plaintext data length (in bytes).
* @param plaintext_length The amount of bytes to encrypt.
Expand Down Expand Up @@ -74,8 +91,8 @@ static inline size_t cecies_calc_compression_bound(const size_t data_length)
*/
static inline size_t cecies_calc_output_buffer_needed_size(const size_t input_buffer_length, const size_t key_size)
{
// 1 2 3 4 5
return 16 + 32 + key_size + 16 + input_buffer_length;
// 1 2 3 4 5
return CECIES_IV_LEN + CECIES_SALT_LEN + key_size + CECIES_TAG_LEN + input_buffer_length;

// 1: IV (AES initialization vector)
// 2: Salt (for HKDF)
Expand Down Expand Up @@ -122,7 +139,8 @@ static inline size_t cecies_calc_base64_length(const size_t data_length)
* @param output Where to write the converted binary data into.
* @param output_size Size of the output buffer (make sure to allocate at least <c>(hexstr_length / 2) + 1</c> bytes!).
* @param output_length [OPTIONAL] Where to write the output array length into. This is always gonna be <c>hexstr_length / 2</c>, but you can still choose to write it out just to be sure. If you want to omit this: no problem.. just pass <c>NULL</c>!
* @return <c>0</c> if conversion succeeded. <c>1</c> if one or more required arguments were <c>NULL</c> or invalid. <c>2</c> if the hexadecimal string is in an invalid format (e.g. not divisible by 2). <c>3</c> if output buffer size was insufficient (needs to be at least <c>(hexstr_length / 2) + 1</c> bytes).
* @return <c>0</c> if conversion succeeded. <c>1</c> if one or more required arguments were <c>NULL</c> or invalid. <c>2</c> if the hexadecimal string is in an invalid format (e.g. not divisible by 2). <c>3</c> if output buffer size was insufficient
* (needs to be at least <c>(hexstr_length / 2) + 1</c> bytes).
*/
CECIES_API int cecies_hexstr2bin(const char* hexstr, size_t hexstr_length, uint8_t* output, size_t output_size, size_t* output_length);

Expand Down
Loading