diff options
Diffstat (limited to 'src/pubkey')
-rw-r--r-- | src/pubkey/dsa/dsa.cpp | 31 | ||||
-rw-r--r-- | src/pubkey/dsa/dsa.h | 21 | ||||
-rw-r--r-- | src/pubkey/ecdsa/ecdsa.cpp | 30 | ||||
-rw-r--r-- | src/pubkey/ecdsa/ecdsa.h | 19 | ||||
-rw-r--r-- | src/pubkey/gost_3410/gost_3410.cpp | 42 | ||||
-rw-r--r-- | src/pubkey/gost_3410/gost_3410.h | 23 | ||||
-rw-r--r-- | src/pubkey/nr/nr.cpp | 27 | ||||
-rw-r--r-- | src/pubkey/nr/nr.h | 20 | ||||
-rw-r--r-- | src/pubkey/pk_keys.h | 7 | ||||
-rw-r--r-- | src/pubkey/pk_ops.h | 43 | ||||
-rw-r--r-- | src/pubkey/pubkey.cpp | 93 | ||||
-rw-r--r-- | src/pubkey/pubkey.h | 89 | ||||
-rw-r--r-- | src/pubkey/rsa/rsa.h | 21 | ||||
-rw-r--r-- | src/pubkey/rw/rw.cpp | 23 | ||||
-rw-r--r-- | src/pubkey/rw/rw.h | 18 |
15 files changed, 363 insertions, 144 deletions
diff --git a/src/pubkey/dsa/dsa.cpp b/src/pubkey/dsa/dsa.cpp index 628841fba..52df9827f 100644 --- a/src/pubkey/dsa/dsa.cpp +++ b/src/pubkey/dsa/dsa.cpp @@ -124,4 +124,35 @@ SecureVector<byte> DSA_Signature_Operation::sign(const byte msg[], return output; } +DSA_Verification_Operation::DSA_Verification_Operation(const DSA_PublicKey& dsa) : + q(dsa.group_q()), y(dsa.get_y()) + { + powermod_g_p = Fixed_Base_Power_Mod(dsa.group_g(), dsa.group_p()); + powermod_y_p = Fixed_Base_Power_Mod(y, dsa.group_p()); + mod_p = Modular_Reducer(dsa.group_p()); + mod_q = Modular_Reducer(dsa.group_q()); + } + +bool DSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + const BigInt& q = mod_q.get_modulus(); + + if(sig_len != 2*q.bytes() || msg_len > q.bytes()) + return false; + + BigInt r(sig, q.bytes()); + BigInt s(sig + q.bytes(), q.bytes()); + BigInt i(msg, msg_len); + + if(r <= 0 || r >= q || s <= 0 || s >= q) + return false; + + s = inverse_mod(s, q); + s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)), + powermod_y_p(mod_q.multiply(s, r))); + + return (mod_q.reduce(s) == r); + } + } diff --git a/src/pubkey/dsa/dsa.h b/src/pubkey/dsa/dsa.h index e0aab1b52..68ae34235 100644 --- a/src/pubkey/dsa/dsa.h +++ b/src/pubkey/dsa/dsa.h @@ -83,6 +83,27 @@ class BOTAN_DLL DSA_Signature_Operation : public PK_Ops::Signature_Operation Modular_Reducer mod_q; }; +class BOTAN_DLL DSA_Verification_Operation : public PK_Ops::Verification + { + public: + DSA_Verification_Operation(const DSA_PublicKey& dsa); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return q.bits(); } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const BigInt& q; + const BigInt& y; + + Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; + Modular_Reducer mod_p, mod_q; + }; + } #endif diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp index ba8c20571..143389751 100644 --- a/src/pubkey/ecdsa/ecdsa.cpp +++ b/src/pubkey/ecdsa/ecdsa.cpp @@ -78,4 +78,34 @@ SecureVector<byte> ECDSA_Signature_Operation::sign(const byte msg[], return output; } +ECDSA_Verification_Operation::ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa) : + base_point(ecdsa.domain().get_base_point()), + public_point(ecdsa.public_point()), + order(ecdsa.domain().get_order()) + { + } + +bool ECDSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + if(sig_len != order.bytes()*2) + return false; + + BigInt e(msg, msg_len); + + BigInt r(sig, sig_len / 2); + BigInt s(sig + sig_len / 2, sig_len / 2); + + if(r < 0 || r >= order || s < 0 || s >= order) + return false; + + BigInt w = inverse_mod(s, order); + + PointGFp R = w * (e * base_point + r * public_point); + if(R.is_zero()) + return false; + + return (R.get_affine_x() % order == r); + } + } diff --git a/src/pubkey/ecdsa/ecdsa.h b/src/pubkey/ecdsa/ecdsa.h index 75a7b152a..4331cd87c 100644 --- a/src/pubkey/ecdsa/ecdsa.h +++ b/src/pubkey/ecdsa/ecdsa.h @@ -116,6 +116,25 @@ class BOTAN_DLL ECDSA_Signature_Operation : public PK_Ops::Signature_Operation const BigInt& x; }; +class BOTAN_DLL ECDSA_Verification_Operation : public PK_Ops::Verification + { + public: + ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const PointGFp& base_point; + const PointGFp& public_point; + const BigInt& order; + }; + } #endif diff --git a/src/pubkey/gost_3410/gost_3410.cpp b/src/pubkey/gost_3410/gost_3410.cpp index c3735c720..1c028eca3 100644 --- a/src/pubkey/gost_3410/gost_3410.cpp +++ b/src/pubkey/gost_3410/gost_3410.cpp @@ -110,9 +110,10 @@ GOST_3410_Signature_Operation::GOST_3410_Signature_Operation( { } -SecureVector<byte> GOST_3410_Signature_Operation::sign(const byte msg[], - u32bit msg_len, - RandomNumberGenerator& rng) +SecureVector<byte> +GOST_3410_Signature_Operation::sign(const byte msg[], + u32bit msg_len, + RandomNumberGenerator& rng) { BigInt k; do @@ -142,4 +143,39 @@ SecureVector<byte> GOST_3410_Signature_Operation::sign(const byte msg[], } +GOST_3410_Verification_Operation::GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost) : + base_point(gost.domain().get_base_point()), + public_point(gost.public_point()), + order(gost.domain().get_order()) + { + } + +bool GOST_3410_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + if(sig_len != order.bytes()*2) + return false; + + BigInt e(msg, msg_len); + + BigInt r(sig, sig_len / 2); + BigInt s(sig + sig_len / 2, sig_len / 2); + + if(r < 0 || r >= order || s < 0 || s >= order) + return false; + + e %= order; + if(e == 0) + e = 1; + + BigInt v = inverse_mod(e, order); + + BigInt z1 = (s*v) % order; + BigInt z2 = (-r*v) % order; + + PointGFp R = (z1 * base_point + z2 * public_point); + + return (R.get_affine_x() == r); + } + } diff --git a/src/pubkey/gost_3410/gost_3410.h b/src/pubkey/gost_3410/gost_3410.h index 12abd6354..3def2cfb9 100644 --- a/src/pubkey/gost_3410/gost_3410.h +++ b/src/pubkey/gost_3410/gost_3410.h @@ -113,6 +113,10 @@ class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature_Operati public: GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410); + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + SecureVector<byte> sign(const byte msg[], u32bit msg_len, RandomNumberGenerator& rng); @@ -122,6 +126,25 @@ class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature_Operati const BigInt& x; }; +class BOTAN_DLL GOST_3410_Verification_Operation : public PK_Ops::Verification + { + public: + GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const PointGFp& base_point; + const PointGFp& public_point; + const BigInt& order; + }; + } #endif diff --git a/src/pubkey/nr/nr.cpp b/src/pubkey/nr/nr.cpp index df483499b..700e93092 100644 --- a/src/pubkey/nr/nr.cpp +++ b/src/pubkey/nr/nr.cpp @@ -134,4 +134,31 @@ SecureVector<byte> NR_Signature_Operation::sign(const byte msg[], return output; } +NR_Verification_Operation::NR_Verification_Operation(const NR_PublicKey& nr) : + q(nr.group_q()), y(nr.get_y()) + { + powermod_g_p = Fixed_Base_Power_Mod(nr.group_g(), nr.group_p()); + powermod_y_p = Fixed_Base_Power_Mod(y, nr.group_p()); + mod_p = Modular_Reducer(nr.group_p()); + mod_q = Modular_Reducer(nr.group_q()); + } + +SecureVector<byte> +NR_Verification_Operation::verify_mr(const byte msg[], u32bit msg_len) + { + const BigInt& q = mod_q.get_modulus(); + + if(msg_len != 2*q.bytes()) + return false; + + BigInt c(msg, q.bytes()); + BigInt d(msg + q.bytes(), q.bytes()); + + if(c.is_zero() || c >= q || d >= q) + throw Invalid_Argument("NR verification: Invalid signature"); + + BigInt i = mod_p.multiply(powermod_g_p(d), powermod_y_p(c)); + return BigInt::encode(mod_q.reduce(c - i)); + } + } diff --git a/src/pubkey/nr/nr.h b/src/pubkey/nr/nr.h index 5fc7b2914..7a6aaf8fb 100644 --- a/src/pubkey/nr/nr.h +++ b/src/pubkey/nr/nr.h @@ -77,6 +77,26 @@ class BOTAN_DLL NR_Signature_Operation : public PK_Ops::Signature_Operation Modular_Reducer mod_q; }; +class BOTAN_DLL NR_Verification_Operation : public PK_Ops::Verification + { + public: + NR_Verification_Operation(const NR_PublicKey& nr); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return (q.bits() - 1); } + + bool with_recovery() const { return true; } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len); + private: + const BigInt& q; + const BigInt& y; + + Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; + Modular_Reducer mod_p, mod_q; + }; + } #endif diff --git a/src/pubkey/pk_keys.h b/src/pubkey/pk_keys.h index caf1a7c9c..f997a29e7 100644 --- a/src/pubkey/pk_keys.h +++ b/src/pubkey/pk_keys.h @@ -132,9 +132,6 @@ class BOTAN_DLL PK_Signing_Key : public virtual Private_Key */ class BOTAN_DLL PK_Verifying_with_MR_Key : public virtual Public_Key { - public: - virtual SecureVector<byte> verify(const byte[], u32bit) const = 0; - virtual ~PK_Verifying_with_MR_Key() {} }; /** @@ -142,10 +139,6 @@ class BOTAN_DLL PK_Verifying_with_MR_Key : public virtual Public_Key */ class BOTAN_DLL PK_Verifying_wo_MR_Key : public virtual Public_Key { - public: - virtual bool verify(const byte[], u32bit, - const byte[], u32bit) const = 0; - virtual ~PK_Verifying_wo_MR_Key() {} }; /** diff --git a/src/pubkey/pk_ops.h b/src/pubkey/pk_ops.h index 2386b968a..27190e0c3 100644 --- a/src/pubkey/pk_ops.h +++ b/src/pubkey/pk_ops.h @@ -49,7 +49,7 @@ class Signature_Operation virtual ~Signature_Operation() {} }; -class Verification_Operation +class BOTAN_DLL Verification { public: /** @@ -59,19 +59,50 @@ class Verification_Operation virtual u32bit max_input_bits() const = 0; /** - * @return boolean specifying if this key type supports recovery + * Find out the number of message parts supported by this scheme. + * @return the number of message parts + */ + virtual u32bit message_parts() const { return 1; } + + /** + * Find out the message part size supported by this scheme/key. + * @return the size of the message parts + */ + virtual u32bit message_part_size() const { return 0; } + + /** + * @return boolean specifying if this key type supports message + * recovery and thus if you need to call verify() or verify_mr() */ virtual bool with_recovery() const = 0; /* - * Perform a signature operation + * Perform a signature check operation + * @param msg the message + * @param msg_len the length of msg in bytes + * @param sig the signature + * @param sig_len the length of sig in bytes + * @returns if signature is a valid one for message + */ + virtual bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + throw Invalid_State("Message recovery required"); + } + + /* + * Perform a signature operation (with message recovery) + * Only call this if with_recovery() returns true * @param msg the message * @param msg_len the length of msg in bytes - * @returns recovered message if with_recovery() otherwise {0} or {1} + * @returns recovered message */ - virtual SecureVector<byte> verify(const byte msg[], u32bit msg_len); + virtual SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len) + { + throw Invalid_State("Message recovery not supported"); + } - virtual ~Verification_Operation() {} + virtual ~Verification() {} }; /* diff --git a/src/pubkey/pubkey.cpp b/src/pubkey/pubkey.cpp index dc4e6e1b1..64e080de3 100644 --- a/src/pubkey/pubkey.cpp +++ b/src/pubkey/pubkey.cpp @@ -197,26 +197,31 @@ SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng) /* * PK_Verifier Constructor */ -PK_Verifier::PK_Verifier(EMSA* emsa_obj) +PK_Verifier::PK_Verifier(const Public_Key& key, EMSA* emsa_obj) { + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); + + while(const Engine* engine = i.next()) + { + op = engine->get_verify_op(key); + if(op) + break; + } + + if(op == 0) + throw Lookup_Error("PK_Verifier: No working engine for " + + key.algo_name()); + emsa = emsa_obj; sig_format = IEEE_1363; } /* -* PK_Verifier Destructor -*/ -PK_Verifier::~PK_Verifier() - { - delete emsa; - } - -/* * Set the signature format */ void PK_Verifier::set_input_format(Signature_Format format) { - if(key_message_parts() == 1 && format != IEEE_1363) + if(op->message_parts() == 1 && format != IEEE_1363) throw Invalid_State("PK_Verifier: This algorithm always uses IEEE 1363"); sig_format = format; } @@ -224,15 +229,6 @@ void PK_Verifier::set_input_format(Signature_Format format) /* * Verify a message */ -bool PK_Verifier::verify_message(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig) - { - return verify_message(msg, msg.size(), sig, sig.size()); - } - -/* -* Verify a message -*/ bool PK_Verifier::verify_message(const byte msg[], u32bit msg_length, const byte sig[], u32bit sig_length) { @@ -249,30 +245,6 @@ void PK_Verifier::update(const byte in[], u32bit length) } /* -* Append to the message -*/ -void PK_Verifier::update(byte in) - { - update(&in, 1); - } - -/* -* Append to the message -*/ -void PK_Verifier::update(const MemoryRegion<byte>& in) - { - update(in, in.size()); - } - -/* -* Check a signature -*/ -bool PK_Verifier::check_signature(const MemoryRegion<byte>& sig) - { - return check_signature(sig, sig.size()); - } - -/* * Check a signature */ bool PK_Verifier::check_signature(const byte sig[], u32bit length) @@ -292,10 +264,11 @@ bool PK_Verifier::check_signature(const byte sig[], u32bit length) BigInt sig_part; ber_sig.decode(sig_part); real_sig.append(BigInt::encode_1363(sig_part, - key_message_part_size())); + op->message_part_size())); ++count; } - if(count != key_message_parts()) + + if(count != op->message_parts()) throw Decoding_Error("PK_Verifier: signature size invalid"); return validate_signature(emsa->raw_data(), @@ -311,25 +284,23 @@ bool PK_Verifier::check_signature(const byte sig[], u32bit length) /* * Verify a signature */ -bool PK_Verifier_with_MR::validate_signature(const MemoryRegion<byte>& msg, - const byte sig[], u32bit sig_len) +bool PK_Verifier::validate_signature(const MemoryRegion<byte>& msg, + const byte sig[], u32bit sig_len) { - SecureVector<byte> output_of_key = key.verify(sig, sig_len); - return emsa->verify(output_of_key, msg, key.max_input_bits()); - } - -/* -* Verify a signature -*/ -bool PK_Verifier_wo_MR::validate_signature(const MemoryRegion<byte>& msg, - const byte sig[], u32bit sig_len) - { - Null_RNG rng; + if(op->with_recovery()) + { + SecureVector<byte> output_of_key = op->verify_mr(sig, sig_len); + return emsa->verify(output_of_key, msg, op->max_input_bits()); + } + else + { + Null_RNG rng; - SecureVector<byte> encoded = - emsa->encoding_of(msg, key.max_input_bits(), rng); + SecureVector<byte> encoded = + emsa->encoding_of(msg, op->max_input_bits(), rng); - return key.verify(encoded, encoded.size(), sig, sig_len); + return op->verify(encoded, encoded.size(), sig, sig_len); + } } /* diff --git a/src/pubkey/pubkey.h b/src/pubkey/pubkey.h index fc0e90fa8..a1e98fb6e 100644 --- a/src/pubkey/pubkey.h +++ b/src/pubkey/pubkey.h @@ -191,14 +191,17 @@ class BOTAN_DLL PK_Verifier * @return true if the signature is valid */ bool verify_message(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig); + const MemoryRegion<byte>& sig) + { + return verify_message(msg, msg.size(), sig, sig.size()); + } /** * Add a message part (single byte) of the message corresponding to the * signature to be verified. - * @param msg_part the byte to add + * @param in the byte to add */ - void update(byte msg_part); + void update(byte in) { update(&in, 1); } /** * Add a message part of the message corresponding to the @@ -211,9 +214,10 @@ class BOTAN_DLL PK_Verifier /** * Add a message part of the message corresponding to the * signature to be verified. - * @param msg_part the new message part + * @param in the new message part */ - void update(const MemoryRegion<byte>& msg_part); + void update(const MemoryRegion<byte>& in) + { update(&in[0], in.size()); } /** * Check the signature of the buffered message, i.e. the one build @@ -230,7 +234,10 @@ class BOTAN_DLL PK_Verifier * @param sig the signature to be verified * @return true if the signature is valid, false otherwise */ - bool check_signature(const MemoryRegion<byte>& sig); + bool check_signature(const MemoryRegion<byte>& sig) + { + return check_signature(&sig[0], sig.size()); + } /** * Set the format of the signatures fed to this verifier. @@ -240,23 +247,23 @@ class BOTAN_DLL PK_Verifier /** * Construct a PK Verifier. + * @param pub_key the public key to verify against * @param emsa the EMSA to use * An example would be new EMSA1(new SHA_224) */ - PK_Verifier(EMSA* emsa); + PK_Verifier(const Public_Key& pub_key, EMSA* emsa); - virtual ~PK_Verifier(); - protected: - virtual bool validate_signature(const MemoryRegion<byte>&, - const byte[], u32bit) = 0; - virtual u32bit key_message_parts() const = 0; - virtual u32bit key_message_part_size() const = 0; - - Signature_Format sig_format; - EMSA* emsa; + ~PK_Verifier() { delete op; delete emsa; } private: PK_Verifier(const PK_Verifier&); PK_Verifier& operator=(const PK_Verifier&); + + bool validate_signature(const MemoryRegion<byte>& msg, + const byte sig[], u32bit sig_len); + + PK_Ops::Verification* op; + EMSA* emsa; + Signature_Format sig_format; }; /* @@ -397,56 +404,6 @@ class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor const EME* encoder; }; -/** -* Public Key Verifier with Message Recovery. -*/ -class BOTAN_DLL PK_Verifier_with_MR : public PK_Verifier - { - public: - /** - * Construct an instance. - * @param key the key to use inside the verifier - * @param emsa_name the name of the EMSA to use - */ - PK_Verifier_with_MR(const PK_Verifying_with_MR_Key& k, - EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {} - - private: - PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&); - PK_Verifier_with_MR& operator=(const PK_Verifier_with_MR&); - - bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit); - u32bit key_message_parts() const { return key.message_parts(); } - u32bit key_message_part_size() const { return key.message_part_size(); } - - const PK_Verifying_with_MR_Key& key; - }; - -/** -* Public Key Verifier without Message Recovery -*/ -class BOTAN_DLL PK_Verifier_wo_MR : public PK_Verifier - { - public: - /** - * Construct an instance. - * @param key the key to use inside the verifier - * @param emsa_name the name of the EMSA to use - */ - PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key& k, - EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {} - - private: - PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&); - PK_Verifier_wo_MR& operator=(const PK_Verifier_wo_MR&); - - bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit); - u32bit key_message_parts() const { return key.message_parts(); } - u32bit key_message_part_size() const { return key.message_part_size(); } - - const PK_Verifying_wo_MR_Key& key; - }; - } #endif diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h index 989cfd038..72b90fe5a 100644 --- a/src/pubkey/rsa/rsa.h +++ b/src/pubkey/rsa/rsa.h @@ -115,6 +115,27 @@ class BOTAN_DLL RSA_Signature_Operation : public PK_Ops::Signature_Operation u32bit n_bits; }; +class BOTAN_DLL RSA_Verification_Operation : public PK_Ops::Verification + { + public: + RSA_Verification_Operation(const RSA_PublicKey& rsa) : + powermod_e_n(rsa.get_e(), rsa.get_n()), + n_bits(rsa.get_n().bits()) + {} + + u32bit max_input_bits() const { return (n_bits - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len) + { + return BigInt::encode(powermod_e_n(BigInt(msg, msg_len))); + } + + private: + Fixed_Exponent_Power_Mod powermod_e_n; + u32bit n_bits; + }; + } #endif diff --git a/src/pubkey/rw/rw.cpp b/src/pubkey/rw/rw.cpp index de50313d2..85b10a69d 100644 --- a/src/pubkey/rw/rw.cpp +++ b/src/pubkey/rw/rw.cpp @@ -156,4 +156,27 @@ SecureVector<byte> RW_Signature_Operation::sign(const byte msg[], return BigInt::encode_1363(r, n.bytes()); } +SecureVector<byte> +RW_Verification_Operation::verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + + if((m > (n >> 1)) || m.is_negative()) + throw Invalid_Argument("RW signature verification: m > n / 2 || m < 0"); + + BigInt r = powermod_e_n(m); + if(r % 16 == 12) + return BigInt::encode(r); + if(r % 8 == 6) + return BigInt::encode(2*r); + + r = n - r; + if(r % 16 == 12) + return BigInt::encode(r); + if(r % 8 == 6) + return BigInt::encode(2*r); + + throw Invalid_Argument("RW signature verification: Invalid signature"); + } + } diff --git a/src/pubkey/rw/rw.h b/src/pubkey/rw/rw.h index a46cb5bb3..66dfd289e 100644 --- a/src/pubkey/rw/rw.h +++ b/src/pubkey/rw/rw.h @@ -84,7 +84,23 @@ class BOTAN_DLL RW_Signature_Operation : public PK_Ops::Signature_Operation Fixed_Exponent_Power_Mod powermod_d1_p, powermod_d2_q; Modular_Reducer mod_p; - u32bit n_bits; + }; + +class BOTAN_DLL RW_Verification_Operation : public PK_Ops::Verification + { + public: + RW_Verification_Operation(const RW_PublicKey& rw) : + n(rw.get_n()), powermod_e_n(rw.get_e(), rw.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len); + + private: + const BigInt& n; + Fixed_Exponent_Power_Mod powermod_e_n; }; } |