Hello, Everyone,
It seems like when I sign a message using the RSASSA_PKCS1v15_SHA_Signer as in
RSASignFile() in
test.cpp and then verify the message, verifying the prefix of the message returns
"true" AND
the size of the prefix seems to vary randomly.
I generated a random byte string and signed it with RSASSA_PKCS1v15_SHA_Signer. Then I
repeatedly chopped off a byte from the end of the string and tried to verify it with
RSASSA_PKCS1v15_SHA_Verifier. I printed out the size of the biggest string for which
the
verification does not succeed.
Here is my output:
[EMAIL PROTECTED]> ./csaClient
Original message is of size: 2048
Signature verification failing for message prefix of size: 101
Signature verification failing for message prefix of size: 71
Signature verification failing for message prefix of size: 144
Signature verification failing for message prefix of size: 143
Signature verification failing for message prefix of size: 98
Signature verification failing for message prefix of size: 18
Signature verification failing for message prefix of size: 128
Signature verification failing for message prefix of size: 156
Signature verification failing for message prefix of size: 85
Signature verification failing for message prefix of size: 181
Signature verification failing for message prefix of size: 519
Signature verification failing for message prefix of size: 493
Signature verification failing for message prefix of size: 7
Signature verification failing for message prefix of size: 57
Signature verification failing for message prefix of size: 1203
Signature verification failing for message prefix of size: 71
Signature verification failing for message prefix of size: 135
Signature verification failing for message prefix of size: 232
Signature verification failing for message prefix of size: 82
Here is my code:
int main(int argc, char** argv) {
cout << "Original message is of size: " << RSA_CHALLENGE_SIZE*2 << endl;
for(int i = 0; i < 20; i++ ) {
testSigning();
}
}
void testSigning() {
AuthClient client;
byte buffer[RSA_CHALLENGE_SIZE*2];
client.getRandomPool().GenerateBlock(buffer, RSA_CHALLENGE_SIZE*2);
ByteString* testString = new ByteString(buffer, RSA_CHALLENGE_SIZE*2);
ByteString* signature = client.sign(testString);
for(int i = 0; i < RSA_CHALLENGE_SIZE*2; i++) {
ByteString* substring = testString -> substring(0, RSA_CHALLENGE_SIZE*2 - i);
if( !client.verify(substring, signature) ) {
cout << "Signature verification failing for message prefix of size: "<<
RSA_CHALLENGE_SIZE*2 - i << endl;
break;
}
}
}
*******************************************************************************
*******************************************************************************
*******************************************************************************
/******************************************************************************/
/* */
/* Client-Server Authentication */
/* Olga Sayenko, [EMAIL PROTECTED] */
/* UIC Department of Computer Science */
/* */
/* authClient.h */
/* */
/* */
/******************************************************************************/
#ifndef ABSTRACT_CLINET_H
#define ABSTRACT_CLIENT_H
#include "cryptoComponent.h"
#include "clientCommunication.h"
#define KEY_FILE_NAME ".client_csa_keys"
namespace ClientServerAuthentication {
class AuthClient : public CryptoComponent, public ClientCommunication {
public:
AuthClient();
AuthClient(ByteString* clientPublic, ByteString* clientPrivate, ByteString*
serverPublic);
~AuthClient();
void connect();
void sendMessage(ByteString* message);
ByteString* receiveMessage();
void disconnect();
ByteString* encrypt(ByteString* plaintext);
ByteString* decrypt(ByteString* cyphertext);
ByteString* sign(ByteString* message);
bool verify(ByteString* message, ByteString* signature);
private:
ByteString* clientPublicKey;
ByteString* clientPrivateKey;
ByteString* serverPublicKey;
};
}
#endif
*******************************************************************************
*******************************************************************************
*******************************************************************************
ByteString* AuthClient::sign(ByteString* message) {
return rsaSign(clientPrivateKey, message);
}
bool AuthClient::verify(ByteString* message, ByteString* signature) {
return rsaVerify(clientPublicKey, signature, message);
}
*******************************************************************************
*******************************************************************************
*******************************************************************************
#ifndef CRYPTO_COMPONENT_H
#define CRYPTO_COMPONENT_H
#include "osrng.h"
#include "pubkey.h"
#include "pssr.h"
#include "rsa.h"
#include "byteString.h"
using namespace CryptoPP;
namespace ClientServerAuthentication {
#define RSA_KEY_LENGTH 1024
#define RSA_CHALLENGE_SIZE 1024
#define RSA_ENCODED_PRIVATE_KEY_SIZE 1264
#define RSA_ENCODED_PUBLIC_KEY_SIZE 320
#define RSA_SIGNATURE_LENGTH 256
#define RSA_ENCRYPTED_BLOCK_SIZE 256
#define BLOCK_SIZE 80
class CryptoComponent {
public:
CryptoComponent();
ByteString* generatePrivateKey();
ByteString* generateRandomNumber(int size);
ByteString* symmetricEncrypt(ByteString* key, ByteString* plaintext);
ByteString* symmetricDecrypt(ByteString* key, ByteString* cyphertext);
void generateRSAkey(ByteString** publicKey, ByteString** privateKey);
ByteString* rsaEncrypt(ByteString* publicKey, ByteString* plaintext);
ByteString* rsaDecrypt(ByteString* privateKey, ByteString* cyphertext);
ByteString* rsaSign(ByteString* privateKey, ByteString* plaintext);
bool rsaVerify(ByteString* publicKey, ByteString* signature, ByteString* message);
ByteString* signAndEncrypt(ByteString* publicOther, ByteString* privateOwn,
ByteString*
message);
ByteString* CryptoComponent::decryptAndVerify(ByteString* publicOther, ByteString*
privateOwn, ByteString* cyphertext);
RandomPool& getRandomPool();
protected:
AutoSeededRandomPool randomNumberPool;
};
}
#endif
*******************************************************************************
*******************************************************************************
*******************************************************************************
ByteString* CryptoComponent::rsaSign(ByteString* privateKey, ByteString* message) {
if(message == NULL) {
throw AuthException("Null message");
}
try {
StringSource keySource(privateKey->toStdString(), true, new HexDecoder);
RSASSA_PKCS1v15_SHA_Signer signer(keySource);
std::string signature;
StringSink* signatureSink = new StringSink(signature);
HexEncoder* signatureEncoder = new HexEncoder(signatureSink);
SignerFilter* signerFilter = new SignerFilter(randomNumberPool, signer,
signatureEncoder);
StringSource(message->toStdString(), true, signerFilter);
return new ByteString(signature.c_str());
}
catch( Exception e) {
cout << "CryptoComponent::rsaSign: " << e.what() << endl;
throw e;
}
}
bool CryptoComponent::rsaVerify(ByteString* publicKey, ByteString* signature,
ByteString*
message) {
if(message == NULL) {
throw AuthException("Null message");
}
StringSource publicKeySource(publicKey->toStdString(), true, new HexDecoder);
RSASSA_PKCS1v15_SHA_Verifier verifier(publicKeySource);
StringSource signatureSource(signature->toStdString(), true, new HexDecoder);
if (signatureSource.MaxRetrievable() != verifier.SignatureLength()) {
return false;
}
SecByteBlock signatureBlock(verifier.SignatureLength());
signatureSource.Get(signatureBlock, signatureBlock.size());
VerifierFilter* verifierFilter = new VerifierFilter(verifier);
verifierFilter->Put(signatureBlock, verifier.SignatureLength());
StringSource messageSource(message->toStdString(), true, verifierFilter);
bool verified = verifierFilter->GetLastResult();
return verified;
}
=====
Olga Sayenko
http://www.cs.uic.edu/~osayenko
Department of Computer Science
University of Illinois at Chicago