Ok, the problem is that the standard made it sound like it's using PKCS1
encryption padding for the signaure, when it's in fact using the signature
padding, but just without the hash identifiers. Try the attached code
instead.
On Wed, Oct 20, 2004 at 07:33:07AM -1000, Mukkamala, Subbarayudu wrote:
> HI
> I have some problem while using the ReverseRSAES that was sent to me in
> the last reply.
>
> I am able to decrypt the the message encrypted by Crypto++
> ReverseRSAES<PKCS1v15>::Encryptor,
>
> But when I try to decrypt the message from Cisico router, it failed.
>
> I tried the same with SSL RSA_public_decrypt function, and it succeeded.
>
> I am copying the the code and output for both Crypto++ and SSL. Please
> help me to find the problem with this.
>
> Thank You
> Subbu
>
>
>
> -----Original Message-----
> From: Wei Dai [mailto:[EMAIL PROTECTED]
> Sent: Friday, October 15, 2004 10:57 PM
> To: [EMAIL PROTECTED]
> Subject: Re: ISAKMP HASH_I/HASH_R encryption with RSA Private key
>
>
> Please ignore what I said in my private reply. (I didn't notice you sent
> a
> public post as well as a private email.) That will work for the
> encryption, but not the decryption. Try the attached code instead.
>
> On Fri, Oct 15, 2004 at 12:43:06PM -1000, Mukkamala, Subbarayudu wrote:
> > Hi:
> > I am trying to use RSA algorithms from Crypto ++ 5.2.1 library for
> IPSec.
> >
> > I need some clarification on signature generation using RSA,
> interpreting the following from IKE standard [rfc 2409] section 5.1.
> >
> > -------------- RFC 2409 Section 5.1---------------------------------
> > In general the signature will be over HASH_I and HASH_R as above
> > using the negotiated prf, or the HMAC version of the negotiated
> hash
> > function (if no prf is negotiated). However, this can be overridden
> > for construction of the signature if the signature algorithm is
> tied
> > to a particular hash algorithm (e.g. DSS is only defined with SHA's
> > 160 bit output). In this case, the signature will be over HASH_I
> and
> > HASH_R as above, except using the HMAC version of the hash
> algorithm
> > associated with the signature method. The negotiated prf and hash
> > function would continue to be used for all other prescribed pseudo-
> > random functions.
> >
> > Since the hash algorithm used is already known there is no need to
> > encode its OID into the signature. In addition, there is no binding
> > between the OIDs used for RSA signatures in PKCS #1 and those used
> in
> > this document. Therefore, RSA signatures MUST be encoded as a
> private
> > key encryption in PKCS #1 format and not as a signature in PKCS #1
> > format (which includes the OID of the hash algorithm). DSS
> signatures
> > MUST be encoded as r followed by s.
> > -------------- RFC 2409 Section 5.1---------------------------------
> >
> > I See the above to do the followign steps: See at
> http://www.netsys.com/ipsec/1998/msg00347.html
> >
> > - ISAKMP produces HASH_I/HASH_R however it wishes
> >
> > - the hash is used as input data for encryption with the RSA private
> key, with padding as required by the RSA algorithm
> >
> > - the (key bits) of encryption output is passed over the wire as the
> signature
> >
> > As I see RSA encryption algorithm of Crypto++ usually takes only
> public key, NOT private key except in case of RSA Signature generation.
> >
> > But as the spec indicates that we can not use RSA signature provided
> by Crypto++ as it encodes OID os algorithm Can you tell how to encrypt
> HASH_I/HASH_R with RSA private key using Crypto++?
> >
> > Please let me know.
> >
> > Thank You
> > Subbu
> >
> >
Content-Description: ReverseRSAProblem.txt
>
>
> Public Key from the Cisco Router:
> 305C300D 06092A86 4886F70D 01010105 00034B00 30480241 00C9303D D58D4EE0
> 12445584 3EB615F8 5CF79695 A2C3DC56 0249683D E63FF490 4CF4FAB0 5F3F109E
> 6BFAA619 A3BBA368 E745BC58 015EEF04 639D7CB2 930BFCEE 11020301 0001
>
> Encrypted Text:
> 133BAE7964AF3E65377DFDB2F9DB7078DED219D8C56020333134EBF5689CF729D9E7C296F88ABF2F48322B68AF7588F3669F7644B84C5B4BF5F5419B97AFF60C
>
> Crypto++ Code
>
> INT32 MyRSADecryptor2(const char *pubFilename, char *ciphertext, char *result_str)
> {
> DecodingResult isValid;
>
> try
> {
> std::string timeSeed;
> timeSeed = IntToString(time(NULL));
> const char* seed = timeSeed.c_str();
>
> RandomPool randPool;
> randPool.Put((byte *)seed, strlen(seed));
>
> cout << "Using seed: " << seed << endl << endl;
> // GlobalRNG().Put((const byte *)seed, strlen(seed));
>
> FileSource pubFile(pubFilename, true, new HexDecoder);
> ReverseTrapdoorFunctionPublic<RSA> pub;
> pub.BERDecode(pubFile);
>
> ReverseRSAES<PKCS1v15>::Decryptor d(pub);
>
> string result;
> StringSource(ciphertext, true, new HexDecoder(new
> PK_DecryptorFilter(randPool, d, new StringSink(result))));
> strcpy (result_str, result.c_str());
> }
> catch(CryptoPP::Exception &e)
> {
> cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
> return -1;
> }
> return 1;
> }
>
> Crypto++ Output:
>
> CryptoPP::Exception caught: ReverseRSA/EME-PKCS1-v1_5: invalid ciphertext
>
> SSL: Code
>
> static int CiscoKey(RSA *key)
> {
> static unsigned char n[] =
> "\x00\xC9\x30\x3D\xD5\x8D\x4E\xE0\x12\x44\x55\x84\x3E\xB6\x15\xF8\x5C\xF7\x96\x95\xA2\xC3\xDC\x56\x02\x49\x68\x3D\xE6\x3F\xF4\x90\x4C\xF4\xFA\xB0\x5F\x3F\x10\x9E\x6B\xFA\xA6\x19\xA3\xBB\xA3\x68\xE7\x45\xBC\x58\x01\x5E\xEF\x04\x63\x9D\x7C\xB2\x93\x0B\xFC\xEE\x11";
>
> static unsigned char e[] = "\x01\x00\x01";
>
> key->n = BN_bin2bn(n, sizeof(n)-1, key->n);
> key->e = BN_bin2bn(e, sizeof(e)-1, key->e);
> }
>
> key = RSA_new();
> CiscoKey(key);
>
> RSA_public_decrypt(clen, ctext, ptext, key, padding);
>
> SSL Output:
>
> SSL RSA_public_decrypt(clen, ctext, ptext, key, RSA_PKCS1_PADDING); Output:
> 9E D7 8A 52 29 9A 84 5A 00 51 A5 69 D7 FA 3D C7
>
> SSL RSA_public_decrypt(clen, ctext, ptext, key, RSA_NO_PADDING); Output:
> 00 01 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
> FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 9E D7 8A 52 29 9A
> 84 5A 00 51 A5 69 D7 FA 3D C7
template <unsigned int L>
class TransparentHash : public HashTransformation
{
public:
enum {DIGESTSIZE = L};
static std::string CRYPTOPP_API StaticAlgorithmName() {return
"TransparentHash";}
void Update(const byte *input, unsigned int length)
{
if (m_hash.size() + length > L)
throw HashInputTooLong("TransparentHash");
m_hash.append((const char *)input, length);
}
unsigned int DigestSize() const
{return L;}
void TruncatedFinal(byte *digest, unsigned int digestSize)
{
m_hash.copy((char *)digest, digestSize);
}
protected:
std::string m_hash;
};
template<> const byte PKCS_DigestDecoration<TransparentHash<16> >::decoration[] = {0};
template<> const unsigned int PKCS_DigestDecoration<TransparentHash<16> >::length = 0;
void Test()
{
try
{
string a = "305C300D 06092A86 4886F70D 01010105 00034B00
30480241 00C9303D D58D4EE0"
"12445584 3EB615F8 5CF79695 A2C3DC56 0249683D E63FF490 4CF4FAB0 5F3F109E"
"6BFAA619 A3BBA368 E745BC58 015EEF04 639D7CB2 930BFCEE 11020301 0001";
string signature =
"133BAE7964AF3E65377DFDB2F9DB7078DED219D8C56020333134EBF5689CF729D9E7C296F88ABF2F48322B68AF7588F3669F7644B84C5B4BF5F5419B97AFF60C";
string digest = "9E D7 8A 52 29 9A 84 5A 00 51 A5 69 D7 FA 3D
C7";
std::string timeSeed;
timeSeed = IntToString(time(NULL));
const char* seed = timeSeed.c_str();
RandomPool randPool;
randPool.Put((byte *)seed, strlen(seed));
cout << "Using seed: " << seed << endl << endl;
// GlobalRNG().Put((const byte *)seed, strlen(seed));
StringSource pubFile(a, true, new HexDecoder);
RSA::PublicKey pub;
pub.BERDecode(pubFile);
RSASS<PKCS1v15, TransparentHash<16> >::Verifier v(pub);
HexDecoder f(new SignatureVerificationFilter(v));
f.Put((byte *)signature.data(), signature.size());
f.Put((byte *)digest.data(), digest.size());
f.MessageEnd();
byte verified;
f.Get(verified);
cout << "Verified: " << (int)verified << endl;
}
catch(CryptoPP::Exception &e)
{
cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
}
}