2017-12-17 7 views
2

Ich habe die Whitepaper und Spezifikationen zu blinden Unterschriften gelesen, auf die ich gestoßen bin, einschließlich der Wikipedia-Einträge, aber diese konzentrieren sich eher auf die mathematische Theorie dahinter.Erstellen und Überprüfen von blinden RSA-Signaturen mit Crypto ++?

Gibt es eine präzise praktische Implementierung von RSA Blind Signaturen in C++ mit der Crypto ++ Bibliothek?

Antwort

2

Gibt es eine präzise praktische Implementierung von RSA Blind Signaturen in C++ mit der Crypto ++ Bibliothek?

Ja. Das Crypto ++ Wiki hat einen Abschnitt über Blindsignaturen für RSA unter Raw RSA | RSA Blind Signature. Im Folgenden ist der Code aus dem Wiki entnommen.

Crypto ++ verfügt über keine Blindsignaturklassen. Das folgende Verfahren folgt dem Basisalgorithmus, wie er unter Blind Signatures beschrieben ist. Es unterscheidet sich jedoch von Wikipedia durch die Anwendung der s(s'(x)) = x Gegenprüfung. Die Gegenprobe war in Chaum's original paper vorhanden, aber es fehlt im Wiki-Artikel. Ein zweiter Unterschied zu Chaums Papier und Wikipedia ist, dass der folgende Code H(m) anstelle von m verwendet. Das liegt an Rabin in 1979.

Soweit wir wissen, gibt es keinen Standard, der das Signaturschema abdeckt. Der Mangel an Standardisierung wird sicherlich zu Interop-Problemen führen. Der folgende Code verwendet beispielsweise SHA256, um die zu signierende Nachricht zu hashen, während RSA Blind Signature Scheme for golang das vollständige Domain-Hashing verwendet. Siehe auch Is there a standard padding/format for RSA Blind Signatures? auf Crypto.SE.

Sie können zuerst eine Auffüllfunktion per Usability of padding scheme in blinded RSA signature? oder RSA blind signatures in practice anwenden.


#include "cryptlib.h" 
#include "integer.h" 
#include "nbtheory.h" 
#include "osrng.h" 
#include "rsa.h" 
#include "sha.h" 
using namespace CryptoPP; 

#include <iostream> 
#include <stdexcept> 
using std::cout; 
using std::endl; 
using std::runtime_error; 

int main(int argc, char* argv[]) 
{ 
    // Bob artificially small key pair 
    AutoSeededRandomPool prng; 
    RSA::PrivateKey privKey; 

    privKey.GenerateRandomWithKeySize(prng, 64); 
    RSA::PublicKey pubKey(privKey); 

    // Convenience 
    const Integer& n = pubKey.GetModulus(); 
    const Integer& e = pubKey.GetPublicExponent(); 
    const Integer& d = privKey.GetPrivateExponent(); 

    // Print params 
    cout << "Pub mod: " << std::hex << pubKey.GetModulus() << endl; 
    cout << "Pub exp: " << std::hex << e << endl; 
    cout << "Priv mod: " << std::hex << privKey.GetModulus() << endl; 
    cout << "Priv exp: " << std::hex << d << endl; 

    // For sizing the hashed message buffer. This should be SHA256 size. 
    const size_t SIG_SIZE = UnsignedMin(SHA256::BLOCKSIZE, n.ByteCount()); 

    // Scratch 
    SecByteBlock buff1, buff2, buff3; 

    // Alice original message to be signed by Bob 
    SecByteBlock orig((const byte*)"secret", 6); 
    Integer m(orig.data(), orig.size()); 
    cout << "Message: " << std::hex << m << endl; 

    // Hash message per Rabin (1979) 
    buff1.resize(SIG_SIZE); 
    SHA256 hash1; 
    hash1.CalculateTruncatedDigest(buff1, buff1.size(), orig, orig.size()); 

    // H(m) as Integer 
    Integer hm(buff1.data(), buff1.size()); 
    cout << "H(m): " << std::hex << hm << endl; 

    // Alice blinding 
    Integer r; 
    do { 
     r.Randomize(prng, Integer::One(), n - Integer::One()); 
    } while (!RelativelyPrime(r, n)); 

    // Blinding factor 
    Integer b = a_exp_b_mod_c(r, e, n); 
    cout << "Random: " << std::hex << b << endl; 

    // Alice blinded message 
    Integer mm = a_times_b_mod_c(hm, b, n); 
    cout << "Blind msg: " << std::hex << mm << endl; 

    // Bob sign 
    Integer ss = privKey.CalculateInverse(prng, mm); 
    cout << "Blind sign: " << ss << endl; 

    // Alice checks s(s'(x)) = x. This is from Chaum's paper 
    Integer c = pubKey.ApplyFunction(ss); 
    cout << "Check sign: " << c << endl; 
    if (c != mm) 
     throw runtime_error("Alice cross-check failed"); 

    // Alice remove blinding 
    Integer s = a_times_b_mod_c(ss, r.InverseMod(n), n); 
    cout << "Unblind sign: " << s << endl; 

    // Eve verifies 
    Integer v = pubKey.ApplyFunction(s);  
    cout << "Verify: " << std::hex << v << endl; 

    // Convert to a string 
    size_t req = v.MinEncodedSize(); 
    buff2.resize(req); 
    v.Encode(&buff2[0], buff2.size()); 

    // Hash message per Rabin (1979) 
    buff3.resize(SIG_SIZE); 
    SHA256 hash2; 
    hash2.CalculateTruncatedDigest(buff3, buff3.size(), orig, orig.size()); 

    // Constant time compare 
    bool equal = buff2.size() == buff3.size() && VerifyBufsEqual(
     buff2.data(), buff3.data(), buff3.size()); 

    if (!equal) 
     throw runtime_error("Eve verified failed"); 

    cout << "Verified signature" << endl; 

    return 0; 
} 

Hier ist das Ergebnis des Gebäudes und die Ausführung des Programms:

$ g++ blind.cxx ./libcryptopp.a -o blind.exe 
$ ./blind.exe 
Pub mod: b55dc5e79993680fh 
Pub exp: 11h 
Priv mod: b55dc5e79993680fh 
Priv exp: 1b4fc70ff2e97f1h 
Message: 736563726574h 
H(m): 2bb80d537b1da3e3h 
Random: 72dd6819f0fc5e5fh 
Blinded msg: 27a2e2e5e6f4fbfh 
Blind sign: 84e7039495bf0570h 
Check sign: 27a2e2e5e6f4fbfh 
Unblind sign: 61054203e843f380h 
Verify: 2bb80d537b1da3e3h 
Verified signature 
Verwandte Themen