Public Key Algorithms

1. Key Generation

Whether using a secret-key cryptosystem or a public-key cryptosystem, one needs a good source of random numbers for key generation. This program is to use a pseudo-random number generator fed by a random seed. The primary difference between random and pseudo-random numbers is that pseudo-random numbers are necessarily periodic whereas truly random numbers are not. Since pseudo-random number generators are deterministic algorithms, it is important to find one that is cryptographically secure and also to use a good random seed; the generator effectively acts as an "expander" from the seed to a larger amount of pseudo-random data. The seed must be sufficiently variable to deter attacks based on trying all possible seeds.

Please note that though we can't read the public/private key pairs unless opening a file, we can send seeds to peers during public key distribution. It's much safer by keeping the real random key secret. I have tested that handling-file time is trivial compared to encrypt/sign time.

We can use the function GenerateRSAKey to generate key pairs and save them to files.

2. Digital Signatures

The following program is to sign a plain msg, then verify that whether the signature is correct. We can separate them in other applications. Please note that the keyLength is not permitted to be too short in this program. Because we must hash the plaintext before encrypt the hash codes, we must use hash methods. In this program, we use SHA. If we want to change a method, we need only change the structure name of signer and verifier. Please refer to rsa.h for different declarations.

char seed[1024]="0123456789abcdef", privFilename[128]="priv.txt", pubFilename[128]="pub.txt";
unsigned int keyLength=512;

GenerateRSAKey(keyLength, privFilename, pubFilename, seed);


byte out[100], outPlain[100];
bool pass = true, fail;


char *plain = "EveryoneFridayOff";

FileSource keys("priv.txt", true, new HexDecoder);
RSASSA_PKCS1v15_SHA_Signer rsaPriv(keys);
RSASSA_PKCS1v15_SHA_Verifier rsaPub(rsaPriv);

unsigned int signatureLength = rsaPriv.SignMessage(GlobalRNG(), (byte *)plain, strlen(plain), out);

fail = !rsaPub.VerifyMessage((byte *)plain, strlen(plain), out, signatureLength);
pass = pass && !fail;

cout << (fail ? "Signature is verified to be wrong " : "Signature is verified to be right ")<<"\n";

กก

3. Encryption

The following program is to encrypt a msg with the public key stored in pubFileName, then decrypt it with the private key stored in privFilename. Please remember, the msg length can't be too long. For example, when the keyLength is 512 bytes, the msg length can't surpass 22 bytes, otherwise, an error warning will pop out.

char seed[1024]="0123456789abcdef", privFilename[128]="priv.txt", pubFilename[128]="pub.txt";
unsigned int keyLength=512, plainLen;

GenerateRSAKey(keyLength, privFilename, pubFilename, seed);


byte out[1024], outPlain[1024];
bool pass = true, fail;


char *plain = "Everyonetodayoff";
plainLen = strlen(plain);


FileSource keys("priv.txt", true, new HexDecoder);
RSAES_OAEP_SHA_Decryptor rsaPriv(keys);
FileSource pubkeys("pub.txt", true, new HexDecoder);
RSAES_OAEP_SHA_Encryptor rsaPub(pubkeys);

rsaPub.Encrypt(GlobalRNG(), (byte*)plain, plainLen, out);
DecodingResult result = rsaPriv.FixedLengthDecrypt(GlobalRNG(), out, outPlain);
fail = !result.isValidCoding || memcmp(plain, outPlain, 8);

cout << (fail ? "Encryption is verified to be wrong " : "Encryption is verified to be right ")<<"\n";

กก