Search code examples
c++opensslrsa

verify signature failed with RSA public key using OpenSSL


I have a pair of public and private keys. I use the private key to sign a data string, then I get the signature string, and I use the public key to verify it. However, it failed! This is my code:

    static char* encrypt_private_key = "-----BEGIN RSA PRIVATE KEY-----\n"
        "MIICXAIBAAKBgQDQb4hTBU584fJNot6BNG7TKWuVPlBlngIDTts1s5WYA2rAgoOZ\n"
        "hvFLVCQV2zQNcNOe+kbI1ejOYLyWE+P9R8LmgYrfmMge0bIH4a1IdSZLqIc6ON9L\n"
        "rDAUTIK1b06jLPz9Xn0ql5RPnkShUwkoDWipMklGNqW7X7LTLg8EpHzvdQIDAQAB\n"
        "AoGAccBMj7JXsUPF7qSx9aVdzhPOyLYnPi3LP27rpxUI0NsciU8w7rp8OPYEc4Eb\n"
        "mTI364z+0GAdG3Qjt2vHgtSFAjZVTKP8ncpowhzpoUCFVIhPXi7Y1iPbNylabnwx\n"
        "cwsmqJHvnyKldVbH5AXJiVVe2r+8oW6VjioRqLicgbOcbUkCQQD5Yom+FgjCFfD7\n"
        "H6uw2LZ96oLJL5+fPEJnp+HeD0T89bej7BrA2fRpTSvf9zqzl6rNLUr7txWDORC2\n"
        "9r7p0wEPAkEA1fbtKFGArHyik7oTDYWBQakU14WbU01iHcLK0PccIfVorrKqnRN7\n"
        "txVqNtz3iW15HZSQmfMuM9t4UxGdENc/OwJBAKNLe4glY2y680VsUn8FGFHQ2fyk\n"
        "m2+oBI9dJY/DDdhZiPrkIgx/awP8jSsk9qIcQLIC42N5WbPIDQLRBOeUy88CQDKj\n"
        "4Zd0SscILJZYKOA/Y8s9kGA+D/gUTY+LpeL1SWREKAWI5daNYO+BEwVvIOsWzN6S\n"
        "ZfL52kqNvBm1Bn6Q4zcCQH+ETH6Jr+5QRxTgU5IJJ3CJhtPCjqENdrZI4DHliB6E\n"
        "sKsrNbPZJGHQff9+Bq2/LU/Z014UzEiG0SUod0wDs24=\n"
        "-----END RSA PRIVATE KEY-----";
    RSA* encrypt_rsa_pri_key = 0;
    // -----BEGIN RSA PUBLIC KEY-----
    // MIGJAoGBANBviFMFTnzh8k2i3oE0btMpa5U+UGWeAgNO2zWzlZgDasCCg5mG8UtU
    // JBXbNA1w0576RsjV6M5gvJYT4/1HwuaBit+YyB7RsgfhrUh1Jkuohzo430usMBRM
    // grVvTqMs/P1efSqXlE+eRKFTCSgNaKkySUY2pbtfstMuDwSkfO91AgMBAAE=
    // -----END RSA PUBLIC KEY-----
    static unsigned char encrypt_public_key[] = {
        129, 129, 129, 129, 129, 238, 233, 235, 229, 226, 140, 254, 255, 237, 140, 252, 249, 238, 224, 229, 239, 140, 231, 233, 245, 129, 129, 129, 
        129, 129, 166, 225, 229, 235, 230, 237, 195, 235, 238, 237, 226, 238, 218, 197, 234, 225, 234, 248, 194, 214, 196, 148, 199, 158, 197, 159, 
        195, 233, 156, 206, 216, 225, 220, 205, 153, 249, 135, 249, 235, 251, 201, 237, 203, 226, 227, 158, 214, 251, 214, 192, 246, 203, 232, 205, 
        223, 239, 239, 203, 153, 193, 235, 148, 249, 216, 249, 166, 230, 238, 244, 206, 226, 237, 157, 219, 156, 153, 155, 154, 254, 223, 198, 250, 
        154, 225, 153, 203, 218, 230, 245, 248, 152, 131, 157, 228, 219, 217, 205, 238, 197, 216, 135, 245, 213, 238, 155, 254, 223, 203, 202, 196, 
        222, 249, 196, 157, 230, 199, 217, 195, 196, 214, 195, 152, 159, 156, 217, 223, 225, 238, 254, 225, 166, 203, 222, 250, 218, 248, 221, 225, 
        223, 131, 252, 157, 201, 202, 255, 221, 244, 192, 233, 135, 201, 254, 231, 234, 248, 239, 255, 203, 226, 205, 231, 199, 213, 255, 249, 245, 
        158, 220, 206, 216, 202, 223, 216, 225, 217, 232, 219, 255, 199, 202, 227, 149, 157, 237, 203, 225, 238, 237, 237, 233, 145, 166, 129, 129, 
        129, 129, 129, 233, 226, 232, 140, 254, 255, 237, 140, 252, 249, 238, 224, 229, 239, 140, 231, 233, 245, 129, 129, 129, 129, 129, 166
        };
    int pub_is_decrypt = 0;
    RSA* encrypt_rsa_pub_key = 0;
    std::string testRSA(std::string data) {
        if (encrypt_rsa_pri_key == 0) {
            BIO *rsa_pri_io = BIO_new_mem_buf(encrypt_private_key, strlen(encrypt_private_key));
            encrypt_rsa_pri_key = PEM_read_bio_RSAPrivateKey(rsa_pri_io, 0, 0, 0);
            //BIO_free(rsa_pri_io);
        }
        if (pub_is_decrypt == 0) {
            for (int idx = 0; idx < sizeof(encrypt_public_key); idx++) {
                encrypt_public_key[idx] = encrypt_public_key[idx] ^ 0xac;
            }
            pub_is_decrypt = 1;
        }
        if (encrypt_rsa_pub_key == 0) {
            BIO* rsa_pub_io = BIO_new_mem_buf(encrypt_public_key, sizeof(encrypt_public_key));
            if (rsa_pub_io == NULL) {
                return "";
            }
            // PKCS#8 publickey should use PEM_read_bio_RSA_PUBKEY() while PKCS#1 use PEM_read_bio_RSAPublicKey() instead
            encrypt_rsa_pub_key = PEM_read_bio_RSAPublicKey(rsa_pub_io, 0, 0, 0);
            if (encrypt_rsa_pub_key == 0) {
                return "";
            }
            BIO_free(rsa_pub_io);
        }
        BIGNUM* rsa_pub_n = NULL, * rsa_priv_n = NULL;
        RSA_get0_key(encrypt_rsa_pub_key, (const BIGNUM**)&rsa_pub_n, NULL, NULL);
        RSA_get0_key(encrypt_rsa_pri_key, (const BIGNUM**)&rsa_priv_n, NULL, NULL);
        int match = BN_cmp(rsa_pub_n, rsa_priv_n);
        unsigned char digest[SHA256_DIGEST_LENGTH];
        SHA256(reinterpret_cast<const unsigned char*>(data.c_str()), data.length(), digest);
        unsigned int signatureLength = RSA_size(encrypt_rsa_pri_key);
        unsigned char* signature = new unsigned char[signatureLength];
        int result = RSA_sign(NID_sha256, digest, SHA256_DIGEST_LENGTH, signature, &signatureLength, encrypt_rsa_pri_key);
        std::string retStr(signature, signature + signatureLength);
        result = RSA_verify(NID_sha256, (const unsigned char*)data.c_str(), data.length(), (const unsigned char*)signature, signatureLength, encrypt_rsa_pub_key);
        return retStr;
    }

I try to check if the keys matched, and the match is 0 which means thery are matched. However, the RSA_sign() function returns 1 but the RSA_verify() function returns 0.

What's wrong with my code? Thanks!


Solution

  • In RSA_verify() the 2nd and 3rd parameters are incorrect:

    Instead of (const unsigned char*)data.c_str(), data.length() pass digest, SHA256_DIGEST_LENGTH (just like with signing, s. RSA_verify()). With this fix, verification is successful.