mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-26 22:15:52 +00:00
Cryptoconditions: ED25519 (RIPD-1214)
This commit is contained in:
@@ -1782,6 +1782,8 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\Condition.h">
|
<ClInclude Include="..\..\src\ripple\conditions\Condition.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple\conditions\Ed25519.h">
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\Fulfillment.h">
|
<ClInclude Include="..\..\src\ripple\conditions\Fulfillment.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\impl\base64.h">
|
<ClInclude Include="..\..\src\ripple\conditions\impl\base64.h">
|
||||||
@@ -1790,6 +1792,10 @@
|
|||||||
<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\Ed25519.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\conditions\impl\Fulfillment.cpp">
|
<ClCompile Include="..\..\src\ripple\conditions\impl\Fulfillment.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>
|
||||||
@@ -4546,6 +4552,9 @@
|
|||||||
<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\test\conditions\Ed25519_test.cpp">
|
||||||
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\test\conditions\PreimageSha256_test.cpp">
|
<ClCompile Include="..\..\src\test\conditions\PreimageSha256_test.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -2421,6 +2421,9 @@
|
|||||||
<ClInclude Include="..\..\src\ripple\conditions\Condition.h">
|
<ClInclude Include="..\..\src\ripple\conditions\Condition.h">
|
||||||
<Filter>ripple\conditions</Filter>
|
<Filter>ripple\conditions</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\ripple\conditions\Ed25519.h">
|
||||||
|
<Filter>ripple\conditions</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\conditions\Fulfillment.h">
|
<ClInclude Include="..\..\src\ripple\conditions\Fulfillment.h">
|
||||||
<Filter>ripple\conditions</Filter>
|
<Filter>ripple\conditions</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -2430,6 +2433,9 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\conditions\impl\Condition.cpp">
|
<ClCompile Include="..\..\src\ripple\conditions\impl\Condition.cpp">
|
||||||
<Filter>ripple\conditions\impl</Filter>
|
<Filter>ripple\conditions\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\ripple\conditions\impl\Ed25519.cpp">
|
||||||
|
<Filter>ripple\conditions\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
<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>
|
||||||
@@ -5328,6 +5334,9 @@
|
|||||||
<ClCompile Include="..\..\src\test\beast\SemanticVersion_test.cpp">
|
<ClCompile Include="..\..\src\test\beast\SemanticVersion_test.cpp">
|
||||||
<Filter>test\beast</Filter>
|
<Filter>test\beast</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\test\conditions\Ed25519_test.cpp">
|
||||||
|
<Filter>test\conditions</Filter>
|
||||||
|
</ClCompile>
|
||||||
<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>
|
||||||
|
|||||||
@@ -127,6 +127,9 @@ validate (Condition const& c)
|
|||||||
if (c.type == condition_hashlock)
|
if (c.type == condition_hashlock)
|
||||||
return (c.featureBitmask == (feature_sha256 | feature_preimage));
|
return (c.featureBitmask == (feature_sha256 | feature_preimage));
|
||||||
|
|
||||||
|
if (c.type == condition_ed25519)
|
||||||
|
return (c.featureBitmask == feature_ed25519);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
100
src/ripple/conditions/Ed25519.h
Normal file
100
src/ripple/conditions/Ed25519.h
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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_ED25519_H
|
||||||
|
#define RIPPLE_CONDITIONS_ED25519_H
|
||||||
|
|
||||||
|
#include <ripple/conditions/Condition.h>
|
||||||
|
#include <ripple/conditions/Fulfillment.h>
|
||||||
|
#include <ripple/protocol/PublicKey.h>
|
||||||
|
#include <ripple/protocol/SecretKey.h>
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace cryptoconditions {
|
||||||
|
|
||||||
|
class Ed25519 final
|
||||||
|
: public Fulfillment
|
||||||
|
{
|
||||||
|
static std::size_t constexpr signature_size_ = 64;
|
||||||
|
static std::size_t constexpr pubkey_size_ = 32;
|
||||||
|
|
||||||
|
std::array<std::uint8_t,
|
||||||
|
pubkey_size_ + signature_size_> payload_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Ed25519 () = default;
|
||||||
|
|
||||||
|
/** Create a fulfillment given a keypair and the message */
|
||||||
|
Ed25519 (
|
||||||
|
SecretKey const& secretKey,
|
||||||
|
PublicKey const& publicKey,
|
||||||
|
Slice message);
|
||||||
|
|
||||||
|
/** Create a fulfillment given a secret key and the message */
|
||||||
|
Ed25519 (
|
||||||
|
SecretKey const& secretKey,
|
||||||
|
Slice message);
|
||||||
|
|
||||||
|
Condition
|
||||||
|
condition() const override;
|
||||||
|
|
||||||
|
std::uint16_t
|
||||||
|
type () const override
|
||||||
|
{
|
||||||
|
return condition_ed25519;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t
|
||||||
|
features () const override
|
||||||
|
{
|
||||||
|
return feature_ed25519;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ok () const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
payloadSize () const override
|
||||||
|
{
|
||||||
|
return payload_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer
|
||||||
|
payload() const override
|
||||||
|
{
|
||||||
|
return { payload_.data(), payload_.size() };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
validate (Slice data) const override;
|
||||||
|
|
||||||
|
bool
|
||||||
|
parsePayload (Slice s) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
115
src/ripple/conditions/impl/Ed25519.cpp
Normal file
115
src/ripple/conditions/impl/Ed25519.cpp
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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/Ed25519.h>
|
||||||
|
#include <ripple/conditions/impl/base64.h>
|
||||||
|
#include <ripple/basics/contract.h>
|
||||||
|
#include <ed25519-donna/ed25519.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace cryptoconditions {
|
||||||
|
|
||||||
|
Ed25519::Ed25519 (
|
||||||
|
SecretKey const& secretKey,
|
||||||
|
PublicKey const& publicKey,
|
||||||
|
Slice message)
|
||||||
|
{
|
||||||
|
if (publicKeyType (publicKey) != KeyType::ed25519)
|
||||||
|
LogicError ("An Ed25519 public key is required.");
|
||||||
|
|
||||||
|
// When PublicKey wraps an Ed25519 key it prefixes
|
||||||
|
// the key itself with a 0xED byte. We carefully
|
||||||
|
// skip that byte.
|
||||||
|
std::memcpy (
|
||||||
|
payload_.data(),
|
||||||
|
publicKey.data() + 1,
|
||||||
|
publicKey.size() - 1);
|
||||||
|
|
||||||
|
// Now sign:
|
||||||
|
ed25519_sign (
|
||||||
|
message.data(),
|
||||||
|
message.size(),
|
||||||
|
secretKey.data(),
|
||||||
|
payload_.data(),
|
||||||
|
payload_.data() + pubkey_size_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a fulfillment given a secret key and the message */
|
||||||
|
Ed25519::Ed25519 (
|
||||||
|
SecretKey const& secretKey,
|
||||||
|
Slice message)
|
||||||
|
{
|
||||||
|
// First derive the public key, and place it in the
|
||||||
|
// payload:
|
||||||
|
ed25519_publickey (
|
||||||
|
secretKey.data(),
|
||||||
|
payload_.data());
|
||||||
|
|
||||||
|
ed25519_sign (
|
||||||
|
message.data(),
|
||||||
|
message.size(),
|
||||||
|
secretKey.data(),
|
||||||
|
payload_.data(),
|
||||||
|
payload_.data() + pubkey_size_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Condition
|
||||||
|
Ed25519::condition() const
|
||||||
|
{
|
||||||
|
Condition cc;
|
||||||
|
cc.type = type();
|
||||||
|
cc.featureBitmask = features();
|
||||||
|
cc.maxFulfillmentLength = payloadSize();
|
||||||
|
|
||||||
|
std::memcpy (
|
||||||
|
cc.fingerprint.data(),
|
||||||
|
payload_.data(),
|
||||||
|
pubkey_size_);
|
||||||
|
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Ed25519::validate (Slice data) const
|
||||||
|
{
|
||||||
|
return ed25519_sign_open (
|
||||||
|
data.data(),
|
||||||
|
data.size(),
|
||||||
|
payload_.data(),
|
||||||
|
payload_.data() + pubkey_size_) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Ed25519::parsePayload (Slice s)
|
||||||
|
{
|
||||||
|
// The payload consists of 96 consecutive bytes:
|
||||||
|
// The public key is the first 32 and the
|
||||||
|
// remaining 64 bytes are the signature.
|
||||||
|
if (s.size() != sizeof(payload_))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::memcpy (payload_.data(), s.data(), s.size());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <ripple/conditions/Condition.h>
|
#include <ripple/conditions/Condition.h>
|
||||||
#include <ripple/conditions/Fulfillment.h>
|
#include <ripple/conditions/Fulfillment.h>
|
||||||
#include <ripple/conditions/PreimageSha256.h>
|
#include <ripple/conditions/PreimageSha256.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>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@@ -79,6 +80,10 @@ loadFulfillment (std::uint16_t type, Slice payload)
|
|||||||
p = std::make_unique<PreimageSha256>();
|
p = std::make_unique<PreimageSha256>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case condition_ed25519:
|
||||||
|
p = std::make_unique<Ed25519>();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::domain_error (
|
throw std::domain_error (
|
||||||
"Unknown cryptocondition type " +
|
"Unknown cryptocondition type " +
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public:
|
|||||||
|
|
||||||
~SecretKey();
|
~SecretKey();
|
||||||
|
|
||||||
|
SecretKey (std::array<std::uint8_t, 32> const& data);
|
||||||
SecretKey (Slice const& slice);
|
SecretKey (Slice const& slice);
|
||||||
|
|
||||||
std::uint8_t const*
|
std::uint8_t const*
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ SecretKey::~SecretKey()
|
|||||||
beast::secure_erase(buf_, sizeof(buf_));
|
beast::secure_erase(buf_, sizeof(buf_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SecretKey::SecretKey (std::array<std::uint8_t, 32> const& key)
|
||||||
|
{
|
||||||
|
std::memcpy(buf_, key.data(), key.size());
|
||||||
|
}
|
||||||
|
|
||||||
SecretKey::SecretKey (Slice const& slice)
|
SecretKey::SecretKey (Slice const& slice)
|
||||||
{
|
{
|
||||||
if (slice.size() != sizeof(buf_))
|
if (slice.size() != sizeof(buf_))
|
||||||
|
|||||||
@@ -21,3 +21,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>
|
||||||
|
|||||||
199
src/test/conditions/Ed25519_test.cpp
Normal file
199
src/test/conditions/Ed25519_test.cpp
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
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/Ed25519.h>
|
||||||
|
#include <ripple/protocol/PublicKey.h>
|
||||||
|
#include <ripple/protocol/SecretKey.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace cryptoconditions {
|
||||||
|
|
||||||
|
class Ed25519_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
void
|
||||||
|
check (
|
||||||
|
std::array<std::uint8_t, 32> const& secretKey,
|
||||||
|
std::vector<std::uint8_t> const& message,
|
||||||
|
std::string const& fulfillment,
|
||||||
|
std::string const& condition)
|
||||||
|
{
|
||||||
|
SecretKey const sk { makeSlice (secretKey) };
|
||||||
|
PublicKey const pk = derivePublicKey (KeyType::ed25519, sk);
|
||||||
|
|
||||||
|
auto f = loadFulfillment (fulfillment);
|
||||||
|
auto c = loadCondition (condition);
|
||||||
|
|
||||||
|
BEAST_EXPECT (f);
|
||||||
|
BEAST_EXPECT (c);
|
||||||
|
|
||||||
|
if (f && c)
|
||||||
|
{
|
||||||
|
// Ensure that loading works correctly
|
||||||
|
BEAST_EXPECT (to_string (*f) == fulfillment);
|
||||||
|
BEAST_EXPECT (to_string (*c) == condition);
|
||||||
|
|
||||||
|
// Ensures that the fulfillment generates
|
||||||
|
// the condition correctly:
|
||||||
|
BEAST_EXPECT (f->condition() == c);
|
||||||
|
|
||||||
|
// Check fulfillment
|
||||||
|
BEAST_EXPECT (validate (*f, *c, makeSlice(message)));
|
||||||
|
|
||||||
|
// Check correct creation of fulfillment
|
||||||
|
BEAST_EXPECT (*f == Ed25519 (sk, pk, makeSlice(message)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testKnownVectors ()
|
||||||
|
{
|
||||||
|
testcase ("Known Vectors");
|
||||||
|
|
||||||
|
std::array<std::uint8_t, 32> sk =
|
||||||
|
{{
|
||||||
|
0x50, 0xd8, 0x58, 0xe0, 0x98, 0x5e, 0xcc, 0x7f,
|
||||||
|
0x60, 0x41, 0x8a, 0xaf, 0x0c, 0xc5, 0xab, 0x58,
|
||||||
|
0x7f, 0x42, 0xc2, 0x57, 0x0a, 0x88, 0x40, 0x95,
|
||||||
|
0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c
|
||||||
|
}};
|
||||||
|
|
||||||
|
std::vector<std::uint8_t> const payload (512, 0x21);
|
||||||
|
|
||||||
|
check (sk, payload,
|
||||||
|
"cf:4:RCmTBlAEqh5MSPTdAVgZTAI0m8xmTNluQA6iaZGKjVGfTbzglso5Uo3i2O2WVP6abH1dz5k0H5DLylizTeL5UC0VSptUN4VCkhtbwx3B00pCeWNy1H78rq6OTXzok-EH",
|
||||||
|
"cc:4:20:RCmTBlAEqh5MSPTdAVgZTAI0m8xmTNluQA6iaZGKjVE:96");
|
||||||
|
|
||||||
|
sk.fill (0x00);
|
||||||
|
check (sk, hexblob (""),
|
||||||
|
"cf:4:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2imPiVs8r-LJUGA50OKmY4JWgARnT-jSN3hQkuQNaq9IPk_GAWhwXzHxAVlhOM4hqjV8DTKgZPQj3D7kqjq_U_gD",
|
||||||
|
"cc:4:20:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik:96");
|
||||||
|
|
||||||
|
sk.fill (0xff);
|
||||||
|
check (sk, hexblob ("616263"),
|
||||||
|
"cf:4:dqFZIESm5PURJlvKc6YE2QsFKdHfYCvjChmpJXZg0fWuxqtqkSKv8PfcuWZ_9hMTaJRzK254wm9bZzEB4mf-Litl-k1T2tR4oa2mTVD9Hf232Ukg3D4aVkpkexy6NWAB",
|
||||||
|
"cc:4:20:dqFZIESm5PURJlvKc6YE2QsFKdHfYCvjChmpJXZg0fU:96");
|
||||||
|
}
|
||||||
|
|
||||||
|
void testFulfillment ()
|
||||||
|
{
|
||||||
|
testcase ("Fulfillment");
|
||||||
|
|
||||||
|
std::array<std::uint8_t, 32> sk =
|
||||||
|
{{
|
||||||
|
0x50, 0xd8, 0x58, 0xe0, 0x98, 0x5e, 0xcc, 0x7f,
|
||||||
|
0x60, 0x41, 0x8a, 0xaf, 0x0c, 0xc5, 0xab, 0x58,
|
||||||
|
0x7f, 0x42, 0xc2, 0x57, 0x0a, 0x88, 0x40, 0x95,
|
||||||
|
0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c
|
||||||
|
}};
|
||||||
|
|
||||||
|
std::vector<std::uint8_t> const v1 (512, 0x21);
|
||||||
|
std::vector<std::uint8_t> const v2 (512, 0x22);
|
||||||
|
|
||||||
|
Ed25519 const f ({ sk }, makeSlice(v1));
|
||||||
|
|
||||||
|
// First check against incorrect conditions:
|
||||||
|
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:uKkFs6dhGZCwD51c69vVvHYSp25cRi9IlvXfFaxhMjo:518",
|
||||||
|
"cc:4:20:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik:96"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto cc : ccs)
|
||||||
|
{
|
||||||
|
auto c = loadCondition (cc);
|
||||||
|
|
||||||
|
if (BEAST_EXPECT (c))
|
||||||
|
{
|
||||||
|
BEAST_EXPECT (! validate (f, c.get(), makeSlice(v1)));
|
||||||
|
BEAST_EXPECT (! validate (f, c.get(), makeSlice(v2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, finally, check the correct condition:
|
||||||
|
auto c = loadCondition (
|
||||||
|
"cc:4:20:RCmTBlAEqh5MSPTdAVgZTAI0m8xmTNluQA6iaZGKjVE:96");
|
||||||
|
|
||||||
|
if (BEAST_EXPECT (c))
|
||||||
|
{
|
||||||
|
BEAST_EXPECT (validate (f, c.get(), makeSlice(v1)));
|
||||||
|
BEAST_EXPECT (! validate (f, c.get(), makeSlice(v2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Under the existing spec, multiple messages sharing
|
||||||
|
// the same key should generate the same fulfillment:
|
||||||
|
{
|
||||||
|
Ed25519 const f1 ({ sk }, makeSlice (v1));
|
||||||
|
Ed25519 const f2 ({ sk }, makeSlice (v2));
|
||||||
|
|
||||||
|
BEAST_EXPECT (f1.condition () == f2.condition ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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:4:0:RCmTBlAEqh5MSPTdAVgZTAI0m8xmTNluQA6iaZGKjVE:96");
|
||||||
|
BEAST_EXPECT (!c1);
|
||||||
|
|
||||||
|
// The following will load but fail in different ways
|
||||||
|
auto c2 = loadCondition ( // only sha256
|
||||||
|
"cc:4:1:RCmTBlAEqh5MSPTdAVgZTAI0m8xmTNluQA6iaZGKjVE:96");
|
||||||
|
BEAST_EXPECT (c2 && !validate(*c2));
|
||||||
|
|
||||||
|
auto c3 = loadCondition ( // only preimage
|
||||||
|
"cc:4:2:RCmTBlAEqh5MSPTdAVgZTAI0m8xmTNluQA6iaZGKjVE:96");
|
||||||
|
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 ( // Ed25519+threshold
|
||||||
|
"cc:1:28:Yja3qFj7NS_VwwE7aJjPJos-uFCzStJlJLD4VsNy2XM:1");
|
||||||
|
BEAST_EXPECT (c6 && !validate(*c6));
|
||||||
|
}
|
||||||
|
|
||||||
|
void run ()
|
||||||
|
{
|
||||||
|
testKnownVectors ();
|
||||||
|
testFulfillment ();
|
||||||
|
testMalformedCondition ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE (Ed25519, conditions, ripple);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -18,3 +18,4 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <test/conditions/PreimageSha256_test.cpp>
|
#include <test/conditions/PreimageSha256_test.cpp>
|
||||||
|
#include <test/conditions/Ed25519_test.cpp>
|
||||||
|
|||||||
Reference in New Issue
Block a user