Skip to content

Commit d0794ef

Browse files
committed
added test_crypto.cpp with first code for rsa blinding
1 parent a257fe2 commit d0794ef

File tree

3 files changed

+170
-2
lines changed

3 files changed

+170
-2
lines changed

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ endif()
1616

1717
project(oc-issuer VERSION 0.0.2 LANGUAGES CXX)
1818

19+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
20+
1921
include(FetchContent)
2022

2123
#
@@ -96,7 +98,10 @@ add_executable(${PROJECT_NAME} src/main.cpp)
9698
target_link_libraries(${PROJECT_NAME} PRIVATE oc-mint-lib INTERFACE tl::expected::expected)
9799

98100
## these are unittests that can be run on any platform
99-
add_executable(tests test/test_big_int.cpp test/test.cpp)
101+
add_executable(tests test/test_big_int.cpp
102+
test/test_json_s8n.cpp
103+
test/test_crypto.cpp)
104+
100105
target_link_libraries(tests
101106
oc-mint-lib
102107
Catch2::Catch2WithMain)

test/test_crypto.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
2+
#include <catch2/catch_test_macros.hpp>
3+
4+
#include "cryptlib.h"
5+
#include "integer.h"
6+
#include "nbtheory.h"
7+
#include "osrng.h"
8+
#include "rsa.h"
9+
#include "sha.h"
10+
11+
#include <iostream>
12+
#include <stdexcept>
13+
14+
15+
CryptoPP::Integer blind_signature(unsigned char *msg,
16+
size_t msg_len,
17+
18+
const CryptoPP::RSA::PublicKey& pub_key,
19+
const CryptoPP::RSA::PrivateKey& priv_key) {
20+
using namespace CryptoPP;
21+
using std::cout;
22+
using std::endl;
23+
AutoSeededRandomPool prng;
24+
25+
// Convenience
26+
const Integer &n = pub_key.GetModulus();
27+
const Integer &e = pub_key.GetPublicExponent();
28+
const Integer &d = priv_key.GetPrivateExponent();
29+
30+
// For sizing the hashed message buffer. This should be SHA256 size.
31+
const size_t sig_size = UnsignedMin(SHA256::BLOCKSIZE, n.ByteCount());
32+
// Scratch
33+
SecByteBlock buff_1, buff_2, buff_3;
34+
35+
SecByteBlock orig(msg, msg_len);
36+
Integer m(orig.data(), orig.size());
37+
cout << "Message: " << std::hex << m << endl;
38+
39+
// Hash message per Rabin (1979)
40+
buff_1.resize(sig_size);
41+
SHA256 hash_1;
42+
hash_1.CalculateTruncatedDigest(buff_1, buff_1.size(), orig, orig.size());
43+
44+
// H(m) as Integer
45+
Integer hm(buff_1.data(), buff_1.size());
46+
cout << "H(m): " << std::hex << hm << endl;
47+
48+
// Alice blinding
49+
Integer r;
50+
do {
51+
r.Randomize(prng, Integer::One(), n - Integer::One());
52+
} while (!RelativelyPrime(r, n));
53+
54+
// Blinding factor
55+
Integer b = a_exp_b_mod_c(r, e, n);
56+
cout << "Random: " << std::hex << b << endl;
57+
58+
// Alice blinded message
59+
Integer mm = a_times_b_mod_c(hm, b, n);
60+
cout << "Blind msg: " << std::hex << mm << endl;
61+
62+
// Bob sign
63+
Integer ss = priv_key.CalculateInverse(prng, mm);
64+
cout << "Blind sign: " << ss << endl;
65+
66+
return ss;
67+
}
68+
69+
TEST_CASE("cryptopp", "[crypto]") {
70+
using namespace CryptoPP;
71+
using std::cout;
72+
using std::endl;
73+
using std::runtime_error;
74+
75+
// Bob artificially small key pair
76+
AutoSeededRandomPool prng;
77+
RSA::PrivateKey priv_key;
78+
79+
priv_key.GenerateRandomWithKeySize(prng, 64U);
80+
RSA::PublicKey pub_key(priv_key);
81+
82+
// Convenience
83+
const Integer &n = pub_key.GetModulus();
84+
const Integer &e = pub_key.GetPublicExponent();
85+
const Integer &d = priv_key.GetPrivateExponent();
86+
87+
// Print params
88+
cout << "Pub mod: " << std::hex << pub_key.GetModulus() << endl;
89+
cout << "Pub exp: " << std::hex << e << endl;
90+
cout << "Priv mod: " << std::hex << priv_key.GetModulus() << endl;
91+
cout << "Priv exp: " << std::hex << d << endl;
92+
93+
// For sizing the hashed message buffer. This should be SHA256 size.
94+
const size_t sig_size = UnsignedMin(SHA256::BLOCKSIZE, n.ByteCount());
95+
96+
// Scratch
97+
SecByteBlock buff_1, buff_2, buff_3;
98+
99+
// Alice original message to be signed by Bob
100+
SecByteBlock orig((const byte *)"secret", 6U);
101+
Integer m(orig.data(), orig.size());
102+
cout << "Message: " << std::hex << m << endl;
103+
104+
// Hash message per Rabin (1979)
105+
buff_1.resize(sig_size);
106+
SHA256 hash_1;
107+
hash_1.CalculateTruncatedDigest(buff_1, buff_1.size(), orig, orig.size());
108+
109+
// H(m) as Integer
110+
Integer hm(buff_1.data(), buff_1.size());
111+
cout << "H(m): " << std::hex << hm << endl;
112+
113+
// Alice blinding
114+
Integer r;
115+
do {
116+
r.Randomize(prng, Integer::One(), n - Integer::One());
117+
} while (!RelativelyPrime(r, n));
118+
119+
// Blinding factor
120+
Integer b = a_exp_b_mod_c(r, e, n);
121+
cout << "Random: " << std::hex << b << endl;
122+
123+
// Alice blinded message
124+
Integer mm = a_times_b_mod_c(hm, b, n);
125+
cout << "Blind msg: " << std::hex << mm << endl;
126+
127+
// Bob sign
128+
Integer ss = priv_key.CalculateInverse(prng, mm);
129+
cout << "Blind sign: " << ss << endl;
130+
131+
// Alice checks s(s'(x)) = x. This is from Chaum's paper
132+
Integer c = pub_key.ApplyFunction(ss);
133+
cout << "Check sign: " << c << endl;
134+
if (c != mm) {
135+
throw runtime_error("Alice cross-check failed");
136+
}
137+
// Alice remove blinding
138+
Integer s = a_times_b_mod_c(ss, r.InverseMod(n), n);
139+
cout << "Unblind sign: " << s << endl;
140+
141+
// Eve verifies
142+
Integer v = pub_key.ApplyFunction(s);
143+
cout << "Verify: " << std::hex << v << endl;
144+
145+
// Convert to a string
146+
size_t req = v.MinEncodedSize();
147+
buff_2.resize(req);
148+
v.Encode(&buff_2[0], buff_2.size());
149+
150+
// Hash message per Rabin (1979)
151+
buff_3.resize(sig_size);
152+
SHA256 hash_2;
153+
hash_2.CalculateTruncatedDigest(buff_3, buff_3.size(), orig, orig.size());
154+
155+
// Constant time compare
156+
bool equal = buff_2.size() == buff_3.size() &&
157+
VerifyBufsEqual(buff_2.data(), buff_3.data(), buff_3.size());
158+
159+
if (!equal) {
160+
throw runtime_error("Eve verified failed");
161+
}
162+
cout << "Verified signature" << endl;
163+
}

test/test.cpp renamed to test/test_json_s8n.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ TEST_CASE( "PublicKey::to_json", "[to_json]" ) {
1212
REQUIRE( json["modulus"].dump() == "\"" + k.modulus.to_string() + "\"" );
1313
REQUIRE( json["public_exponent"].dump() == "\"" + k.public_exponent.to_string()+"\"" );
1414
REQUIRE( json["type"].dump() == "\"rsa public key\"" );
15-
REQUIRE( json.keys().size() == 3 );
15+
REQUIRE( json.keys().size() == 3U );
1616
}
1717

1818
TEST_CASE("RequestCDDCSerial::from_string", "[from_string]") {

0 commit comments

Comments
 (0)