aboutsummaryrefslogtreecommitdiffstats
path: root/src/pubkey
diff options
context:
space:
mode:
Diffstat (limited to 'src/pubkey')
-rw-r--r--src/pubkey/dsa/dsa.cpp31
-rw-r--r--src/pubkey/dsa/dsa.h21
-rw-r--r--src/pubkey/ecdsa/ecdsa.cpp30
-rw-r--r--src/pubkey/ecdsa/ecdsa.h19
-rw-r--r--src/pubkey/gost_3410/gost_3410.cpp42
-rw-r--r--src/pubkey/gost_3410/gost_3410.h23
-rw-r--r--src/pubkey/nr/nr.cpp27
-rw-r--r--src/pubkey/nr/nr.h20
-rw-r--r--src/pubkey/pk_keys.h7
-rw-r--r--src/pubkey/pk_ops.h43
-rw-r--r--src/pubkey/pubkey.cpp93
-rw-r--r--src/pubkey/pubkey.h89
-rw-r--r--src/pubkey/rsa/rsa.h21
-rw-r--r--src/pubkey/rw/rw.cpp23
-rw-r--r--src/pubkey/rw/rw.h18
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;
};
}