Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
7.13.1 Problem
You have some data, an RSA digital signature of that data, and the public key that you believe corresponds to the signature. You want to determine whether the signature is valid. A successful check would demonstrate both that the data was not modified from the time it was signed (message integrity) and that the entity with the corresponding public key signed the data (authentication). 7.13.2 Solution
Use the verification algorithm that corresponds to the chosen signing algorithm from Recipe 7.12. Generally, this should be included with your cryptographic library. 7.13.3 Discussion
Recipe 7.12 explains the basic components of digital signatures with RSA. When verifying, you will generally need to provide the following inputs:
The API should simply return indication of success or failure. Some implementations of RSA signature verification are susceptible to timing attacks. Basically, if RSA private key operations do not happen in a fixed amount of time, such attacks are possible. A technique called blinding can thwart timing attacks. The amount of time it takes to decrypt is randomized somewhat by operating on a random number in the process. To eliminate the possibility of such attacks, you should always turn blinding on before doing a signature validation operation. With OpenSSL, blinding can be enabled with by calling RSA_blinding_on( ), which has the following signature: int RSA_blinding_on(RSA *r, BN_CTX *x); This function has the following arguments:
The OpenSSL analog to RSA_sign( ) (discussed in Recipe 7.12) is RSA_verify( ), which has the following signature: int RSA_verify(int md_type, unsigned char *dgst, unsigned int dlen, unsigned char *sig, unsigned int siglen, RSA *r); This function has the following arguments:
As we discussed in Recipe 7.12, OpenSSL RSA signatures only support PKCS #1 v1.5 and do not support RSASSA-PSS. Here's code that implements verification on an arbitrary message, given a signature and the public RSA key of the signer: #include <openssl/bn.h> #include <openssl/sha.h> #include <openssl/rsa.h> #include <openssl/objects.h> int spc_verify(unsigned char *msg, unsigned int mlen, unsigned char *sig, unsigned int siglen, RSA *r) { unsigned char hash[20]; BN_CTX *c; int ret; if (!(c = BN_CTX_new( ))) return 0; if (!SHA1(msg, mlen, hash) || !RSA_blinding_on(r, c)) { BN_CTX_free(c); return 0; } ret = RSA_verify(NID_sha1, hash, 20, sig, siglen, r); RSA_blinding_off(r); BN_CTX_free(c); return ret; } 7.13.4 See Also
Recipe 7.4, Recipe 7.12 |