mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-05 16:57:56 +00:00
Cryptoconditions: RSA-SHA-256 (RIPD-1213)
This commit is contained in:
@@ -1800,12 +1800,18 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\conditions\impl\RsaSha256.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\PrefixSha256.h">
|
<ClInclude Include="..\..\src\ripple\conditions\PrefixSha256.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\PreimageSha256.h">
|
<ClInclude Include="..\..\src\ripple\conditions\PreimageSha256.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple\conditions\RsaSha256.h">
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\core\Config.h">
|
<ClInclude Include="..\..\src\ripple\core\Config.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\core\ConfigSections.h">
|
<ClInclude Include="..\..\src\ripple\core\ConfigSections.h">
|
||||||
@@ -4563,6 +4569,9 @@
|
|||||||
<ClCompile Include="..\..\src\test\conditions\PreimageSha256_test.cpp">
|
<ClCompile Include="..\..\src\test\conditions\PreimageSha256_test.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\test\conditions\RsaSha256_test.cpp">
|
||||||
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\test\core\Config_test.cpp">
|
<ClCompile Include="..\..\src\test\core\Config_test.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
|
|||||||
@@ -2439,6 +2439,9 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\conditions\impl\Fulfillment.cpp">
|
<ClCompile Include="..\..\src\ripple\conditions\impl\Fulfillment.cpp">
|
||||||
<Filter>ripple\conditions\impl</Filter>
|
<Filter>ripple\conditions\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\conditions\impl\RsaSha256.cpp">
|
||||||
|
<Filter>ripple\conditions\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
|
||||||
<Filter>ripple\conditions\impl</Filter>
|
<Filter>ripple\conditions\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -2448,6 +2451,9 @@
|
|||||||
<ClInclude Include="..\..\src\ripple\conditions\PreimageSha256.h">
|
<ClInclude Include="..\..\src\ripple\conditions\PreimageSha256.h">
|
||||||
<Filter>ripple\conditions</Filter>
|
<Filter>ripple\conditions</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple\conditions\RsaSha256.h">
|
||||||
|
<Filter>ripple\conditions</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\core\Config.h">
|
<ClInclude Include="..\..\src\ripple\core\Config.h">
|
||||||
<Filter>ripple\core</Filter>
|
<Filter>ripple\core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -5346,6 +5352,9 @@
|
|||||||
<ClCompile Include="..\..\src\test\conditions\PreimageSha256_test.cpp">
|
<ClCompile Include="..\..\src\test\conditions\PreimageSha256_test.cpp">
|
||||||
<Filter>test\conditions</Filter>
|
<Filter>test\conditions</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\test\conditions\RsaSha256_test.cpp">
|
||||||
|
<Filter>test\conditions</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\test\core\Config_test.cpp">
|
<ClCompile Include="..\..\src\test\core\Config_test.cpp">
|
||||||
<Filter>test\core</Filter>
|
<Filter>test\core</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -150,6 +150,9 @@ validate (Condition const& c)
|
|||||||
return (cf2 & definedFeatures) == cf2;
|
return (cf2 & definedFeatures) == cf2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c.type == condition_rsa_sha256)
|
||||||
|
return (c.featureBitmask == (feature_rsa_pss | feature_sha256));
|
||||||
|
|
||||||
if (c.type == condition_ed25519)
|
if (c.type == condition_ed25519)
|
||||||
return (c.featureBitmask == feature_ed25519);
|
return (c.featureBitmask == feature_ed25519);
|
||||||
|
|
||||||
|
|||||||
83
src/ripple/conditions/RsaSha256.h
Normal file
83
src/ripple/conditions/RsaSha256.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2016 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_CONDITIONS_RSA_SHA256_H
|
||||||
|
#define RIPPLE_CONDITIONS_RSA_SHA256_H
|
||||||
|
|
||||||
|
#include <ripple/conditions/Condition.h>
|
||||||
|
#include <ripple/conditions/Fulfillment.h>
|
||||||
|
#include <ripple/basics/Buffer.h>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace cryptoconditions {
|
||||||
|
|
||||||
|
class RsaSha256 final
|
||||||
|
: public Fulfillment
|
||||||
|
{
|
||||||
|
Buffer modulus_;
|
||||||
|
Buffer signature_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RsaSha256 () = default;
|
||||||
|
|
||||||
|
Condition
|
||||||
|
condition() const override;
|
||||||
|
|
||||||
|
std::uint16_t
|
||||||
|
type () const override
|
||||||
|
{
|
||||||
|
return condition_rsa_sha256;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t
|
||||||
|
features () const override
|
||||||
|
{
|
||||||
|
return feature_rsa_pss | feature_sha256;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ok () const override
|
||||||
|
{
|
||||||
|
return !modulus_.empty() && !signature_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
payloadSize () const override;
|
||||||
|
|
||||||
|
Buffer
|
||||||
|
payload() const override;
|
||||||
|
|
||||||
|
bool
|
||||||
|
validate (Slice data) const override;
|
||||||
|
|
||||||
|
/** Sign the given message with an RSA key */
|
||||||
|
bool sign (
|
||||||
|
std::string const& key,
|
||||||
|
Slice message);
|
||||||
|
|
||||||
|
bool
|
||||||
|
parsePayload (Slice s) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <ripple/conditions/Fulfillment.h>
|
#include <ripple/conditions/Fulfillment.h>
|
||||||
#include <ripple/conditions/PreimageSha256.h>
|
#include <ripple/conditions/PreimageSha256.h>
|
||||||
#include <ripple/conditions/PrefixSha256.h>
|
#include <ripple/conditions/PrefixSha256.h>
|
||||||
|
#include <ripple/conditions/RsaSha256.h>
|
||||||
#include <ripple/conditions/Ed25519.h>
|
#include <ripple/conditions/Ed25519.h>
|
||||||
#include <ripple/conditions/impl/utils.h>
|
#include <ripple/conditions/impl/utils.h>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
@@ -85,6 +86,10 @@ loadFulfillment (std::uint16_t type, Slice payload)
|
|||||||
p = std::make_unique<PrefixSha256>();
|
p = std::make_unique<PrefixSha256>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case condition_rsa_sha256:
|
||||||
|
p = std::make_unique<RsaSha256>();
|
||||||
|
break;
|
||||||
|
|
||||||
case condition_ed25519:
|
case condition_ed25519:
|
||||||
p = std::make_unique<Ed25519>();
|
p = std::make_unique<Ed25519>();
|
||||||
break;
|
break;
|
||||||
|
|||||||
313
src/ripple/conditions/impl/RsaSha256.cpp
Normal file
313
src/ripple/conditions/impl/RsaSha256.cpp
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2016 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/conditions/Condition.h>
|
||||||
|
#include <ripple/conditions/Fulfillment.h>
|
||||||
|
#include <ripple/conditions/RsaSha256.h>
|
||||||
|
#include <ripple/conditions/impl/base64.h>
|
||||||
|
#include <ripple/protocol/digest.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/clamp.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace cryptoconditions {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
struct rsa_deleter
|
||||||
|
{
|
||||||
|
void operator() (RSA* rsa) const
|
||||||
|
{
|
||||||
|
RSA_free (rsa);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using RsaKey = std::unique_ptr<RSA, rsa_deleter>;
|
||||||
|
|
||||||
|
struct bn_deleter
|
||||||
|
{
|
||||||
|
void operator() (BIGNUM* bn) const
|
||||||
|
{
|
||||||
|
BN_free (bn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using BigNum = std::unique_ptr<BIGNUM, bn_deleter>;
|
||||||
|
|
||||||
|
// Check whether the public modulus meets the length
|
||||||
|
// requirements imposed by section 4.4.1 of the RFC.
|
||||||
|
bool
|
||||||
|
checkModulusLength (int len)
|
||||||
|
{
|
||||||
|
if (len <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return len == boost::algorithm::clamp(len, 128, 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
signHelper (
|
||||||
|
RSA* key,
|
||||||
|
Slice message,
|
||||||
|
Buffer& modulus,
|
||||||
|
Buffer& signature)
|
||||||
|
{
|
||||||
|
int const keySize = RSA_size(key);
|
||||||
|
if (!checkModulusLength (keySize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sha256_hasher h;
|
||||||
|
h (message.data(), message.size());
|
||||||
|
auto digest = static_cast<sha256_hasher::result_type>(h);
|
||||||
|
|
||||||
|
Buffer buf;
|
||||||
|
|
||||||
|
// Pad the result (-1 -> use hash length as salt length)
|
||||||
|
if (!RSA_padding_add_PKCS1_PSS(key,
|
||||||
|
buf.alloc(keySize), digest.data(),
|
||||||
|
EVP_sha256(), -1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Sign - we've manually padded the input already.
|
||||||
|
auto ret = RSA_private_encrypt(keySize, buf.data(),
|
||||||
|
signature.alloc (buf.size()), key, RSA_NO_PADDING);
|
||||||
|
|
||||||
|
if (ret == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BN_bn2bin (key->n, modulus.alloc(BN_num_bytes (key->n)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
validateHelper (
|
||||||
|
RSA* key,
|
||||||
|
Slice message,
|
||||||
|
Slice signature)
|
||||||
|
{
|
||||||
|
int const keySize = RSA_size(key);
|
||||||
|
if (!checkModulusLength (keySize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Buffer buf;
|
||||||
|
|
||||||
|
auto ret = RSA_public_decrypt(
|
||||||
|
keySize,
|
||||||
|
signature.data(),
|
||||||
|
buf.alloc (keySize),
|
||||||
|
key,
|
||||||
|
RSA_NO_PADDING);
|
||||||
|
|
||||||
|
if (ret == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sha256_hasher h;
|
||||||
|
h (message.data(), message.size());
|
||||||
|
auto digest = static_cast<sha256_hasher::result_type>(h);
|
||||||
|
|
||||||
|
return RSA_verify_PKCS1_PSS(key, digest.data(), EVP_sha256(), buf.data(), -1) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
parsePayloadHelper(
|
||||||
|
Slice s,
|
||||||
|
Buffer& modulus,
|
||||||
|
Buffer& signature)
|
||||||
|
{
|
||||||
|
auto start = s.data ();
|
||||||
|
auto finish = s.data () + s.size();
|
||||||
|
|
||||||
|
std::size_t len;
|
||||||
|
|
||||||
|
std::tie (start, len) = oer::decode_length (
|
||||||
|
start, finish);
|
||||||
|
|
||||||
|
if (std::distance (start, finish) < len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::memcpy (modulus.alloc (len), start, len);
|
||||||
|
std::advance (start, len);
|
||||||
|
|
||||||
|
std::tie (start, len) = oer::decode_length (
|
||||||
|
start, finish);
|
||||||
|
|
||||||
|
if (std::distance (start, finish) < len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::memcpy (signature.alloc (len), start, len);
|
||||||
|
std::advance (start, len);
|
||||||
|
|
||||||
|
// Enforce constraints from the RFC:
|
||||||
|
BigNum sig (BN_bin2bn (
|
||||||
|
signature.data(), signature.size(), nullptr));
|
||||||
|
|
||||||
|
BigNum mod (BN_bin2bn (
|
||||||
|
modulus.data(), modulus.size(), nullptr));
|
||||||
|
|
||||||
|
if (!sig || !mod)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Per 4.4.1 of the RFC we are required to reject
|
||||||
|
// moduli smaller than 128 bytes or greater than
|
||||||
|
// 512 bytes.
|
||||||
|
int modBytes = BN_num_bytes (mod.get());
|
||||||
|
|
||||||
|
if (!checkModulusLength (modBytes))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Per 4.4.2 of the RFC we must check whether the
|
||||||
|
// signature and modulus consist of the same number
|
||||||
|
// of octets and that the signature is numerically
|
||||||
|
// less than the modulus:
|
||||||
|
if (BN_num_bytes (sig.get()) != modBytes)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return BN_cmp (sig.get(), mod.get()) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Condition
|
||||||
|
RsaSha256::condition() const
|
||||||
|
{
|
||||||
|
std::vector<std::uint8_t> m;
|
||||||
|
m.reserve (1024);
|
||||||
|
|
||||||
|
oer::encode_octetstring (
|
||||||
|
modulus_.size(),
|
||||||
|
modulus_.data(),
|
||||||
|
modulus_.data() + modulus_.size(),
|
||||||
|
std::back_inserter(m));
|
||||||
|
|
||||||
|
sha256_hasher h;
|
||||||
|
h (m.data(), m.size());
|
||||||
|
|
||||||
|
Condition cc;
|
||||||
|
cc.type = type();
|
||||||
|
cc.featureBitmask = features();
|
||||||
|
cc.maxFulfillmentLength = payloadSize();
|
||||||
|
|
||||||
|
cc.fingerprint = static_cast<sha256_hasher::result_type>(h);
|
||||||
|
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
RsaSha256::payloadSize () const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
oer::predict_octetstring_size (modulus_.size()) +
|
||||||
|
oer::predict_octetstring_size (signature_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer
|
||||||
|
RsaSha256::payload() const
|
||||||
|
{
|
||||||
|
Buffer b (payloadSize());
|
||||||
|
|
||||||
|
auto out = oer::encode_octetstring (
|
||||||
|
modulus_.size(),
|
||||||
|
modulus_.data(),
|
||||||
|
modulus_.data() + modulus_.size(),
|
||||||
|
b.data());
|
||||||
|
|
||||||
|
oer::encode_octetstring (
|
||||||
|
signature_.size(),
|
||||||
|
signature_.data(),
|
||||||
|
signature_.data() + modulus_.size(),
|
||||||
|
out);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RsaSha256::validate (Slice data) const
|
||||||
|
{
|
||||||
|
if (!ok())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
detail::RsaKey rsa (RSA_new());
|
||||||
|
|
||||||
|
rsa->n = BN_new();
|
||||||
|
BN_bin2bn(modulus_.data(), modulus_.size(), rsa->n);
|
||||||
|
|
||||||
|
rsa->e = BN_new();
|
||||||
|
BN_set_word (rsa->e, 65537);
|
||||||
|
|
||||||
|
return detail::validateHelper (rsa.get(), data, signature_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sign the given message with an RSA key */
|
||||||
|
bool
|
||||||
|
RsaSha256::sign (
|
||||||
|
std::string const& key,
|
||||||
|
Slice message)
|
||||||
|
{
|
||||||
|
// This ugly const_cast/reinterpret_cast is needed
|
||||||
|
// on some machines. Although the documentation
|
||||||
|
// suggests that the function accepts a void const*
|
||||||
|
// argument, apparently some platforms have OpenSSL
|
||||||
|
// libraries that are up-to-date but accept void*.
|
||||||
|
auto bio = BIO_new_mem_buf(
|
||||||
|
const_cast<void*>(static_cast<void const*>(key.data())),
|
||||||
|
key.size());
|
||||||
|
|
||||||
|
if (!bio)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
detail::RsaKey rsa (PEM_read_bio_RSAPrivateKey(
|
||||||
|
bio, NULL, NULL, NULL));
|
||||||
|
|
||||||
|
BIO_free(bio);
|
||||||
|
|
||||||
|
if (!rsa)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (detail::signHelper (rsa.get(), message, modulus_, signature_))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
modulus_.clear();
|
||||||
|
signature_.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RsaSha256::parsePayload (Slice s)
|
||||||
|
{
|
||||||
|
// The payload may not be empty
|
||||||
|
if (!s.empty() && detail::parsePayloadHelper (s, modulus_, signature_))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Clear the state
|
||||||
|
modulus_.clear();
|
||||||
|
signature_.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -22,3 +22,4 @@
|
|||||||
#include <ripple/conditions/impl/Condition.cpp>
|
#include <ripple/conditions/impl/Condition.cpp>
|
||||||
#include <ripple/conditions/impl/Fulfillment.cpp>
|
#include <ripple/conditions/impl/Fulfillment.cpp>
|
||||||
#include <ripple/conditions/impl/Ed25519.cpp>
|
#include <ripple/conditions/impl/Ed25519.cpp>
|
||||||
|
#include <ripple/conditions/impl/RsaSha256.cpp>
|
||||||
|
|||||||
362
src/test/conditions/RsaSha256_test.cpp
Normal file
362
src/test/conditions/RsaSha256_test.cpp
Normal file
@@ -0,0 +1,362 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2016 Ripple Labs Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/basics/strHex.h>
|
||||||
|
#include <ripple/beast/unit_test.h>
|
||||||
|
#include <ripple/conditions/Condition.h>
|
||||||
|
#include <ripple/conditions/Fulfillment.h>
|
||||||
|
#include <ripple/conditions/RsaSha256.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace cryptoconditions {
|
||||||
|
|
||||||
|
class RsaSha256_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
// A well-known message, its fulfillment and its condition
|
||||||
|
std::string const knownMessage = "aaa";
|
||||||
|
|
||||||
|
std::string const knownFulfillment =
|
||||||
|
"cf:3:ggEA4e-LJNb3awnIHtd1KqJi8ETwSodNQ4CdMc6mEvmbDJeotDdBU-Pu89ZmF"
|
||||||
|
"oQ-DkHCkyZLcbYXPbHPDWzVWMWGV3Bvzwl_cExIPlnL_f1bPue8gNdAxeDwR_PoX8D"
|
||||||
|
"XWBV3am8_I8XcXnlxOaaILjgzakpfs2E3Yg_zZj264yhHKAGGL3Ly-HsgK5yJrdfNW"
|
||||||
|
"woHb3xT41A59n7RfsgV5bQwXMYxlwaNXm5Xm6beX04-V99eTgcv8s5MZutFIzlzh1J"
|
||||||
|
"1ljnwJXv1fb1cRD-1FYzOCj02rce6AfM6C7bbsr-YnWBxEvI0TZk-d-VjwdNh3t9X2"
|
||||||
|
"pbvLPxoXwArY4JGpbMJuYIBAEjolF7-AHVW1b9NXySeSAj3MH4pUR0yYtrvYdiAmPm"
|
||||||
|
"qSovAYjqMl1c49l1r9FnVQ_KJ1zy8evTqOjP78-xEQER5EdcilAkeVhgzYo5Jp3LtY"
|
||||||
|
"I3mxEWVqR4-F9bPXsOyUo1j0q3WRjmJsS7sV332Rwlg32gyqdhMNg0cIXrWTIYlvbW"
|
||||||
|
"U-wraCGzey73lgNQkv5dG0vDDEoJtu7AK1otSxMt9RxVro146mByXOGN5LMgNBKGAI"
|
||||||
|
"QpSQVhltks6YXdLHTl114qYsIIe5Vyg-GMF1CUp4Q6wFc79QC-1myq7je7lKm8kR9I"
|
||||||
|
"oRgPSGc1OjPnP_dVJiInDeAtZ3WpX731zJiA";
|
||||||
|
|
||||||
|
std::string const knownCondition =
|
||||||
|
"cc:3:11:uKkFs6dhGZCwD51c69vVvHYSp25cRi9IlvXfFaxhMjo:518";
|
||||||
|
|
||||||
|
// Some RSA keys we use to check
|
||||||
|
std::string const goodKey =
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
|
"MIIEpAIBAAKCAQEAq9QZZzSmdXaAFeSkUgK8/xuyKPQEFNkiEzatMSmmGN+DpCR7\n"
|
||||||
|
"HAK4W3wHfW6jegQFPlsvWLWbtnwgwCHhv1oW4jiL7BDD3prJIuJmhCE/w6WPKTFb\n"
|
||||||
|
"WhvxQY5sbqCDnjcd0x/adKjNLaTpSRANscR+hahbQA1vqPperHz/Z20reRPQ6aDn\n"
|
||||||
|
"w+qBL7dnVFgCPu8QrueyaZ0I5xQMIJiF0CnLXbPbU0ybxDVNgBDXsYeHE4VEM7ek\n"
|
||||||
|
"NQAMrsr6wodD5y94jynXHharEv5dzKsQFPRAGKzTvwQqWSiZr+Fgq4q1GqQW+oUa\n"
|
||||||
|
"xssbXWkGHEOxPBz6RFqLOFd8JnM9yVlWs2nWDwIDAQABAoIBAQCW9WNQCbCImBBV\n"
|
||||||
|
"q6c1qdQzaDiwxBjl3BGUwb+M5qNXTN9RkP9bj4Q6U5AdAdu7sdaNfvzsubjQrOL1\n"
|
||||||
|
"CY9UVqiuHLHJNr1uT5yP+knIoZFsqIJK1WMFmnDtgFwBISIhGRkpx91cCoUgKbcO\n"
|
||||||
|
"in0Nha0Gbe+lKWjFExmj/rlAO2grGO4yYd+P27BZ99mHBXPMQIIwQbSeRUTBLiRy\n"
|
||||||
|
"VhN7Mb60wag2m4F9zriEzhcj7pePNKHvpqNiuT5FCVoUNZW2CqFoXgEghF1VdWj5\n"
|
||||||
|
"UovZITUCN9zrGdFHWQj3Hx1LZo3UQz3auUp4XQ89dIm1GefqcZYpnzth+D43UXtC\n"
|
||||||
|
"f33nK9shAoGBANOm6aAhAh8Ahtc+52u3ykTnRGwI+H3QvgvzE7keZGIUb0yKtd/+\n"
|
||||||
|
"yuxYI3DgN/Mn69p3pLrYh/CJ9VonhELYv4oekGZfCmqEtUxmkTa9EgTKAIxIDw9W\n"
|
||||||
|
"t/jNBzzBccF22kl9w+nYHNOqo8M9yUlx0xwLnfioVX45G4jouucfPUDxAoGBAM/V\n"
|
||||||
|
"CmykuH8vIYluyobldKFglXKeFMQKlKG+Dv9wG71RSYPyamd7lu3fPgZyGcbAGd49\n"
|
||||||
|
"/Wewpq8ieagjrTuCEGlI0lhrL35axvBDKQcS+LTp+uD6vpxnFm986cxLgYRTNq0/\n"
|
||||||
|
"eMUvJy72Ms5zajZUMdjM/nqTA9zpVDofL+xb6Ib/AoGAVheU/H+wvy+VqcR6mgRe\n"
|
||||||
|
"kHyKBm/3tCXOyEmOAkTsjEDHrRjXNlAL9us7L1TlLVFVzL3SEfa2BQ/47z0XvaEw\n"
|
||||||
|
"+FvKXPnX4NAudu9ZrixmQfBxHJ7LEXAy0U+E3B/Lx+gyjqZLpLk1sJu+lVJyqB9W\n"
|
||||||
|
"whevoE/Ixtkv7BbOv+ijH+ECgYAb0WQnzpRzUZenkZDCJYxK3WajhM06wD/MtmfD\n"
|
||||||
|
"gPn1iR/R7WyYlU5KYIsoybTxiVztBlcYvehRoMev3baeNHaF4R1mgFJHE1d1aUfg\n"
|
||||||
|
"joWDkZ3m5ykEPjgejBWvJpwbXhf/cHN10S3pd0Ktp30b8IELh8S4G111ADYp4WrE\n"
|
||||||
|
"tDiXeQKBgQCROYcVuUEfkOiKeGHkBGbbsgj77KzZ1x7wUBzueKAND9+e2kX8kcc2\n"
|
||||||
|
"lX9DDkShUvZau0EJtQsFTehsZZeeBwtSvWu1A+2Wn9D19Hxe0qJCNZ6bqYQM9i2S\n"
|
||||||
|
"JjI6wG7YYl/foT3B3Zf3A3G9gUOc+P5/dnUi+6r+l7GUvQ5WnVQjDw==\n"
|
||||||
|
"-----END RSA PRIVATE KEY-----\n";
|
||||||
|
|
||||||
|
std::string const shortKey =
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
|
"MGMCAQACEQCtbMmYUOdPy+XwgP+xXzfrAgMBAAECEQCFPVJ5GpdMnxfbcKFUUb2\n"
|
||||||
|
"JAgkA2e+AQuY6Ns8CCQDLtxhLU8j0JQIJAKkphE9pUUp1AghYypxPMNy09QIISr\n"
|
||||||
|
"srXHy9nPk=\n"
|
||||||
|
"-----END RSA PRIVATE KEY-----\n";
|
||||||
|
|
||||||
|
std::string const longKey =
|
||||||
|
"-----BEGIN RSA PRIVATE KEY-----\n"
|
||||||
|
"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\n"
|
||||||
|
"QIpo2Qox/w==\n"
|
||||||
|
"-----END RSA PRIVATE KEY-----\n";
|
||||||
|
|
||||||
|
void check (
|
||||||
|
Fulfillment const& f,
|
||||||
|
Condition const& c,
|
||||||
|
Slice test,
|
||||||
|
Slice good)
|
||||||
|
{
|
||||||
|
BEAST_EXPECT (validate (f, c, test) ==
|
||||||
|
((test == good) && (f.condition() == c)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void testKnown ()
|
||||||
|
{
|
||||||
|
testcase ("Known");
|
||||||
|
|
||||||
|
Slice m = makeSlice (knownMessage);
|
||||||
|
std::string test = "aaabc";
|
||||||
|
|
||||||
|
// Load and test string and binary and text
|
||||||
|
// serialization & deserialization
|
||||||
|
auto const f = loadFulfillment(knownFulfillment);
|
||||||
|
BEAST_EXPECT (f);
|
||||||
|
BEAST_EXPECT (to_string (*f) == knownFulfillment);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto const f2 = loadFulfillment(makeSlice(to_blob(*f)));
|
||||||
|
BEAST_EXPECT (f2);
|
||||||
|
BEAST_EXPECT (*f == *f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the condition for this fulfillment and test
|
||||||
|
// binary and text serialization & deserialization
|
||||||
|
auto const c = f->condition();
|
||||||
|
BEAST_EXPECT (to_string(c) == knownCondition);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto c1 = loadCondition (knownCondition);
|
||||||
|
BEAST_EXPECT (c1);
|
||||||
|
BEAST_EXPECT (c == *c1);
|
||||||
|
|
||||||
|
auto c2 = loadCondition (makeSlice(to_blob(c)));
|
||||||
|
BEAST_EXPECT (c2);
|
||||||
|
BEAST_EXPECT (c == *c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First check against incorrect conditions, using both
|
||||||
|
// correct, incorrect and empty buffers.
|
||||||
|
char const* const ccs[] =
|
||||||
|
{
|
||||||
|
"cc:0:3:PWh2oBRt6FdusjlahY3hIT0bksZbd53zozHP1aRYRUY:256",
|
||||||
|
"cc:1:25:XkflBmyISKuevH8-850LuMrzN-HT1Ds9zKUEzaZ2Wk0:103",
|
||||||
|
"cc:2:2b:d3O4epRCo_3rj17Bf3v8hp5ig7vq84ivPok07T9Rdl0:146",
|
||||||
|
"cc:3:11:Mjmrcm06fOo-3WOEZu9YDSNfqmn0lj4iOsTVEurtCdI:518",
|
||||||
|
"cc:4:20:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik:96"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto cc : ccs)
|
||||||
|
{
|
||||||
|
auto nc = loadCondition (cc);
|
||||||
|
|
||||||
|
if (BEAST_EXPECT (nc && nc != c))
|
||||||
|
{
|
||||||
|
check (*f, nc.get(), makeSlice(test), m);
|
||||||
|
check (*f, nc.get(), m, m);
|
||||||
|
check (*f, nc.get(), { }, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now try against the correct condition with various
|
||||||
|
// buffers - most are incorrect, some are correct.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
for (Slice t = makeSlice (test); !t.empty(); t += 1)
|
||||||
|
check (*f, c, t, m);
|
||||||
|
} while (std::next_permutation(test.begin(), test.end()));
|
||||||
|
|
||||||
|
// And with an empty buffer:
|
||||||
|
check (*f, c, Slice { }, m);
|
||||||
|
|
||||||
|
// Under the existing spec, multiple messages sharing
|
||||||
|
// the same key should generate the same fulfillment:
|
||||||
|
{
|
||||||
|
std::array<std::uint8_t, 3> aaa {{ 'a', 'a', 'a' }};
|
||||||
|
std::array<std::uint8_t, 3> bbb {{ 'b', 'b', 'b' }};
|
||||||
|
|
||||||
|
RsaSha256 f1;
|
||||||
|
BEAST_EXPECT (f1.sign (goodKey, makeSlice (aaa)));
|
||||||
|
|
||||||
|
RsaSha256 f2;
|
||||||
|
BEAST_EXPECT (f2.sign (goodKey, makeSlice (bbb)));
|
||||||
|
|
||||||
|
BEAST_EXPECT (f1.condition () == f2.condition ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDynamic ()
|
||||||
|
{
|
||||||
|
testcase ("Dynamic");
|
||||||
|
|
||||||
|
Slice m = makeSlice (knownMessage);
|
||||||
|
|
||||||
|
std::string test = "aaabc";
|
||||||
|
|
||||||
|
RsaSha256 f;
|
||||||
|
BEAST_EXPECT (f.sign (goodKey, m));
|
||||||
|
|
||||||
|
{
|
||||||
|
auto const f2 = loadFulfillment(makeSlice(to_blob(f)));
|
||||||
|
BEAST_EXPECT (f2);
|
||||||
|
BEAST_EXPECT (f == *f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate and verify the condition for this fulfillment:
|
||||||
|
auto const c = f.condition();
|
||||||
|
|
||||||
|
{
|
||||||
|
auto c1 = loadCondition (to_string(c));
|
||||||
|
BEAST_EXPECT (c1);
|
||||||
|
BEAST_EXPECT (c == *c1);
|
||||||
|
|
||||||
|
auto c2 = loadCondition (makeSlice(to_blob(c)));
|
||||||
|
BEAST_EXPECT (c2);
|
||||||
|
BEAST_EXPECT (c == *c2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First check against incorrect conditions, using both
|
||||||
|
// correct, incorrect and empty buffers.
|
||||||
|
char const* const ccs[] =
|
||||||
|
{
|
||||||
|
"cc:0:3:PWh2oBRt6FdusjlahY3hIT0bksZbd53zozHP1aRYRUY:256",
|
||||||
|
"cc:1:25:XkflBmyISKuevH8-850LuMrzN-HT1Ds9zKUEzaZ2Wk0:103",
|
||||||
|
"cc:2:2b:d3O4epRCo_3rj17Bf3v8hp5ig7vq84ivPok07T9Rdl0:146",
|
||||||
|
"cc:3:11:Mjmrcm06fOo-3WOEZu9YDSNfqmn0lj4iOsTVEurtCdI:518",
|
||||||
|
"cc:4:20:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik:96"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto cc : ccs)
|
||||||
|
{
|
||||||
|
auto nc = loadCondition (cc);
|
||||||
|
|
||||||
|
if (BEAST_EXPECT (nc && nc != c))
|
||||||
|
{
|
||||||
|
check (f, nc.get(), makeSlice(test), m);
|
||||||
|
check (f, nc.get(), m, m);
|
||||||
|
check (f, nc.get(), { }, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now try against the correct condition with various
|
||||||
|
// buffers - most are incorrect, some are correct.
|
||||||
|
do
|
||||||
|
{
|
||||||
|
for (Slice t = makeSlice (test); !t.empty(); t += 1)
|
||||||
|
check (f, c, t, m);
|
||||||
|
} while (std::next_permutation(test.begin(), test.end()));
|
||||||
|
|
||||||
|
// And with an empty buffer:
|
||||||
|
check (f, c, Slice { }, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testKeySize ()
|
||||||
|
{
|
||||||
|
testcase ("Key Sizes");
|
||||||
|
|
||||||
|
RsaSha256 f1;
|
||||||
|
BEAST_EXPECT (!f1.sign (longKey, makeSlice (knownMessage)));
|
||||||
|
|
||||||
|
RsaSha256 f2;
|
||||||
|
BEAST_EXPECT (!f2.sign (shortKey, makeSlice (knownMessage)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void testMalformedCondition ()
|
||||||
|
{
|
||||||
|
testcase ("Malformed Condition");
|
||||||
|
|
||||||
|
// This is malformed and will not load because a
|
||||||
|
// feature suite of 0 is not supported.
|
||||||
|
auto c1 = loadCondition (
|
||||||
|
"cc:3:0:Mjmrcm06fOo-3WOEZu9YDSNfqmn0lj4iOsTVEurtCdI:518");
|
||||||
|
BEAST_EXPECT (!c1);
|
||||||
|
|
||||||
|
// The following will load but fail in different ways
|
||||||
|
auto c2 = loadCondition ( // only sha256
|
||||||
|
"cc:3:1:Mjmrcm06fOo-3WOEZu9YDSNfqmn0lj4iOsTVEurtCdI:518");
|
||||||
|
BEAST_EXPECT (c2 && !validate(*c2));
|
||||||
|
|
||||||
|
auto c3 = loadCondition ( // only preimage
|
||||||
|
"cc:3:2:Mjmrcm06fOo-3WOEZu9YDSNfqmn0lj4iOsTVEurtCdI:518");
|
||||||
|
BEAST_EXPECT (c3 && !validate(*c3));
|
||||||
|
|
||||||
|
auto c4 = loadCondition ( // sha256+preimage
|
||||||
|
"cc:4:3:RCmTBlAEqh5MSPTdAVgZTAI0m8xmTNluQA6iaZGKjVE:96");
|
||||||
|
BEAST_EXPECT (c4 && !validate(*c4));
|
||||||
|
|
||||||
|
auto c5 = loadCondition ( // Ed25519+sha256+preimage
|
||||||
|
"cc:1:23:Yja3qFj7NS_VwwE7aJjPJos-uFCzStJlJLD4VsNy2XM:1");
|
||||||
|
BEAST_EXPECT (c5 && !validate(*c5));
|
||||||
|
|
||||||
|
auto c6 = loadCondition ( // rsa+sha256+threshold
|
||||||
|
"cc:1:19:Yja3qFj7NS_VwwE7aJjPJos-uFCzStJlJLD4VsNy2XM:1");
|
||||||
|
BEAST_EXPECT (c6 && !validate(*c6));
|
||||||
|
|
||||||
|
auto c7 = loadCondition ( // rsa
|
||||||
|
"cc:1:10:Yja3qFj7NS_VwwE7aJjPJos-uFCzStJlJLD4VsNy2XM:1");
|
||||||
|
BEAST_EXPECT (c7 && !validate(*c7));
|
||||||
|
}
|
||||||
|
|
||||||
|
void run ()
|
||||||
|
{
|
||||||
|
testKnown();
|
||||||
|
testDynamic();
|
||||||
|
testKeySize();
|
||||||
|
testMalformedCondition();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE (RsaSha256, conditions, ripple);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,4 +19,5 @@
|
|||||||
|
|
||||||
#include <test/conditions/PreimageSha256_test.cpp>
|
#include <test/conditions/PreimageSha256_test.cpp>
|
||||||
#include <test/conditions/PrefixSha256_test.cpp>
|
#include <test/conditions/PrefixSha256_test.cpp>
|
||||||
|
#include <test/conditions/RsaSha256_test.cpp>
|
||||||
#include <test/conditions/Ed25519_test.cpp>
|
#include <test/conditions/Ed25519_test.cpp>
|
||||||
|
|||||||
Reference in New Issue
Block a user