Skip to content
Merged
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
16 changes: 14 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# Version 0.12.0 - 14 January, 2024

- Fixes https://github.com/open-quantum-safe/liboqs-cpp/issues/21. The API that
NIST has introduced in [FIPS 204](https://csrc.nist.gov/pubs/fips/204/final)
for ML-DSA includes a context string of length >= 0. Added new API for
signing with a context string:
- `bytes Signature::sign_with_ctx_str(const bytes& message,
const bytes& context) const`
- `bool Signature::verify_with_ctx_str(const bytes& message,
const bytes& signature, const bytes& context, const bytes& public_key) const`

# Version 0.10.0 - March 27, 2024

- Replaced CHANGES by
Expand Down Expand Up @@ -25,6 +36,7 @@
- Minimalistic Docker support
- Removed AppVeyor and CircleCI, all continuous integration is now done via
GitHub actions
- Changed header files extension from `.h` to `.hpp`

# Version 0.7.2 - September 1, 2022

Expand Down Expand Up @@ -67,7 +79,7 @@

# Version 0.2.0 - October 8, 2019

- Minor changes to accomodate for liboqs API changes
- Minor changes to accommodate for liboqs API changes

# Version 0.1.2 - July 9, 2019

Expand All @@ -77,7 +89,7 @@

# Version 0.1.1 - May 29, 2019

- Minor API change in `oqs_cpp.h`: `Signature::alg_details_::length_signature`
- Minor API change: `Signature::alg_details_::length_signature`
is replaced by `Signature::alg_details_::max_length_signature`

# Version 0.1.0 - April 23, 2019
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.15)
set(LIBOQS_CPP_VERSION_NUM 0.10.0)
set(LIBOQS_CPP_VERSION_NUM 0.12.0)
set(LIBOQS_CPP_VERSION_STR "${LIBOQS_CPP_VERSION_NUM}")
project(
liboqs-cpp
Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = liboqs-cpp
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 0.10.0
PROJECT_NUMBER = 0.12.0

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019-2024 Open Quantum Safe
Copyright (c) 2019-2025 Open Quantum Safe

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
8 changes: 4 additions & 4 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# liboqs-cpp version 0.10.0
# liboqs-cpp version 0.12.0

---

Expand All @@ -24,13 +24,13 @@ See in particular limitations on intended use.

## Release notes

This release of liboqs-cpp was released on March 27, 2024. Its release page
This release of liboqs-cpp was released on January 14, 2024. Its release page
on GitHub is
https://github.com/open-quantum-safe/liboqs-cpp/releases/tag/0.10.0.
https://github.com/open-quantum-safe/liboqs-cpp/releases/tag/0.12.0.

---

## What's New

This is the 14th release of liboqs-cpp. For a list of changes see
This is the 15th release of liboqs-cpp. For a list of changes see
[CHANGES.md](https://github.com/open-quantum-safe/liboqs-cpp/blob/main/CHANGES.md).
58 changes: 56 additions & 2 deletions include/oqs_cpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ class KeyEncapsulation {
std::shared_ptr<C::OQS_KEM> kem_{nullptr, [](C::OQS_KEM* p) {
C::OQS_KEM_free(p);
}}; ///< liboqs smart pointer to C::OQS_KEM
bytes secret_key_{}; ///< secret key
bytes secret_key_{}; ///< secret key
public:
/**
* \brief KEM algorithm details
Expand Down Expand Up @@ -484,7 +484,7 @@ class Signature {
std::shared_ptr<C::OQS_SIG> sig_{nullptr, [](C::OQS_SIG* p) {
C::OQS_SIG_free(p);
}}; ///< liboqs smart pointer to C::OQS_SIG
bytes secret_key_{}; ///< secret key
bytes secret_key_{}; ///< secret key

public:
/**
Expand Down Expand Up @@ -646,6 +646,60 @@ class Signature {
return signature;
}

/**
* \brief Sign message with context string
* \param message Message
* \param context Context string
* \return Message signature
*/
bytes sign_with_ctx_str(const bytes& message, const bytes& context) const {
if (secret_key_.size() != alg_details_.length_secret_key)
throw std::runtime_error(
"Incorrect secret key length, make sure you "
"specify one in the constructor or run "
"oqs::Signature::generate_keypair()");

bytes signature(alg_details_.max_length_signature, 0);

std::size_t len_sig;
OQS_STATUS rv_ = C::OQS_SIG_sign_with_ctx_str(
sig_.get(), signature.data(), &len_sig, message.data(),
message.size(), context.data(), context.size(), secret_key_.data());

if (rv_ != OQS_STATUS::OQS_SUCCESS)
throw std::runtime_error(
"Can not sign message with context string");

signature.resize(len_sig);

return signature;
}

/**
* \brief Verify signature with context string
* \param message Message
* \param signature Signature
* \param context Context string
* \param public_key Public key
* \return True if the signature is valid, false otherwise
*/
bool verify_with_ctx_str(const bytes& message, const bytes& signature,
const bytes& context,
const bytes& public_key) const {
if (public_key.size() != alg_details_.length_public_key)
throw std::runtime_error("Incorrect public key length");

if (signature.size() > alg_details_.max_length_signature)
throw std::runtime_error("Incorrect signature size");

OQS_STATUS rv_ = C::OQS_SIG_verify_with_ctx_str(
sig_.get(), message.data(), message.size(), signature.data(),
signature.size(), context.data(), context.size(),
public_key.data());

return rv_ == OQS_STATUS::OQS_SUCCESS;
}

/**
* \brief Verify signature
* \param message Message
Expand Down
6 changes: 4 additions & 2 deletions prettyprint.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#!/bin/sh

# $@ - List of directories

# Code beautifier with clang-format
# Recursively parses the directories passed as command line arguments

# Arguments:
#
# $@ - List of directories

if test -z "$CLANG_FORMAT"; then
echo "Please set the CLANG_FORMAT environment variable to point to the \
location of clang-format"
Expand Down
59 changes: 57 additions & 2 deletions unit_tests/tests/test_sig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

// no_thread_sig_patterns lists sig patterns that have issues running in a
// separate thread
static std::vector<std::string> no_thread_sig_patterns{"Rainbow-III",
"Rainbow-V"};
static std::vector<std::string> no_thread_sig_patterns{
"cross-rsdp", "cross-rsdpg", "SPHINCS+", "Falcon", "MAYO"};

// used for thread-safe console output
static std::mutex mu;
Expand All @@ -33,6 +33,29 @@ void test_sig_correctness(const std::string& sig_name, const oqs::bytes& msg) {
EXPECT_TRUE(is_valid);
}

void test_sig_correctness_with_ctx_str(const std::string& sig_name,
const oqs::bytes& msg) {
if (sig_name.substr(0, 6) != "ML-DSA")
return;
{
std::lock_guard<std::mutex> lg{mu};
std::cout << "Correctness with context string - " << sig_name
<< std::endl;
}
oqs::Signature signer{sig_name};
oqs::bytes context_str{"some context"_bytes};
oqs::bytes signer_public_key = signer.generate_keypair();
oqs::bytes signature = signer.sign_with_ctx_str(msg, context_str);
oqs::Signature verifier{sig_name};
bool is_valid = verifier.verify_with_ctx_str(msg, signature, context_str,
signer_public_key);
if (!is_valid)
std::cerr << sig_name
<< ": signature with context string verification failed"
<< std::endl;
EXPECT_TRUE(is_valid);
}

void test_sig_wrong_signature(const std::string& sig_name,
const oqs::bytes& msg) {
{
Expand Down Expand Up @@ -101,6 +124,38 @@ TEST(oqs_Signature, Correctness) {
elem.join();
}

TEST(oqs_Signature, CorrectnessWithContextString) {
oqs::bytes message = "This is our favourite message to sign"_bytes;
std::vector<std::thread> thread_pool;
std::vector<std::string> enabled_sigs = oqs::Sigs::get_enabled_sigs();
// first test sigs that belong to no_thread_sig_patterns[] in the main
// thread (stack size is 8Mb on macOS), due to issues with stack size being
// too small in macOS (512Kb for threads)
for (auto&& sig_name : enabled_sigs) {
for (auto&& no_thread_sig : no_thread_sig_patterns) {
if (sig_name.find(no_thread_sig) != std::string::npos) {
test_sig_correctness_with_ctx_str(sig_name, message);
}
}
}
// test the remaining sigs in separate threads
for (auto&& sig_name : enabled_sigs) {
bool test_in_thread = true;
for (auto&& no_thread_sig : no_thread_sig_patterns) {
if (sig_name.find(no_thread_sig) != std::string::npos) {
test_in_thread = false;
break;
}
}
if (test_in_thread)
thread_pool.emplace_back(test_sig_correctness_with_ctx_str,
sig_name, message);
}
// join the rest of the threads
for (auto&& elem : thread_pool)
elem.join();
}

TEST(oqs_Signature, WrongSignature) {
oqs::bytes message = "This is our favourite message to sign"_bytes;
std::vector<std::thread> thread_pool;
Expand Down
Loading