Topic: Issues with PKCS#1_v1.5 (RSA with SHA256 signature)
Hi everyone!
We are going to use a wolfSSL library in our project, but we have faced issues with it.
First of all, we've made some experiments with PKCS#1_v1.5 (RSA with SHA256 signature) using WolfSSL, Python (pycryptodome lib) and OpenSSL (linux console-based and our custom C code), and we see that Python and OpenSSL generate the same signature, but not as the WolfSSL's one.
It is important to note that our goal is sending signed messages to the third-party server. Using some set of APIs we have an opportunity to validate signatures on the remote side, and we see, that signatures made with OpenSSL and Python were validated, while signature made with WolfSSL was refused. Thus, I believe, that signatures from Python and OpenSSL are correct.
We investigated wolfSSL manuals and examples in git repo, and made a simple test with wolfSSL signature. All details and a source code are below.
Probably, we are doing something wrong, but we don't know what exactly.
Any help is appreciated. Thanks in advance!
Here is a keypair in PEM format:
Private Key:
-----BEGIN RSA PRIVATE KEY-----\n
MIIEpAIBAAKCAQEAq6UTzL3bzW85zqixWhuLcsSxkwpqwlYuG9hUQ/WuskWhcNOx\n
qOQ03c5V7MVjnX5P25tXKVlNLtmlnlIYnAqXJd3f/7zlNodw12RS+Cd9HyRbIQ/6\n
G8s5UUb/JNPiIjYNDseQfaI4nrpnzmD99O7N7KxI8nNf1zc+T8sYt8jX1CrPuuPe\n
5n38AEN2k/23ijHHdln7hWCVCk5pT1rHx4QgDdDLft6eKltm8wrwXv20r5d6W6dk\n
cRS1nPBOyESKrBvSdjQqj6XartZh+Os5v13+ikyPJIAJk8A5hvLEo6uhCU2sz7UI\n
1kPoDmHPFZbAqjzm/jNmPm9YYVaRheL7JmRm1wIDAQABAoIBADwukJ8ocIF6vp+F\n
iU2JO98dNQ/TxrPl6JvNwVnksgCCpoS7TN7lSN3+YyU13mQRrilXMXvnekbze/zj\n
VwqbMfzOayQtVIbGfVugKvEkU1wQcL1Kb0zAeBPV207L1c1d+z0T3scWElkhDZWQ\n
b2qqMlyJ2bfcmR2KGph6ouuJiZczaobyhSyesdpQ0aRtGpw0liRm4C7FV+zvjQaw\n
TRofICs5yD/36UcuJ466/ht5ZKeSrolpaBRx5AGjKKfU11uH+FQGn4whdUPHnljK\n
z+ksz7I/ztWg+RBx4ymn3/cTtf5h6Iua+GEoafgKO0IhGUPguqsa4umXq3l6r0PC\n
H0gF/N0CgYEAzh/vKF0NK94thsYrZeQPCt1sDefW9W3OMfzYzYxnpXV5Vd8NR5jq\n
wExiUJlmMJeC2OJ96LjNATceFmbO6ZvgRWf4ZGs+x1dnI7ZplViGMuo4N/YOGEW6\n
nbMtzRmHB46jjdcLeD6F57t8s++qQ4SSDPAvvbm06rIpVdH8wP+mpo0CgYEA1S1X\n
L4ZiS/rzmHT+KdEl+CDuXgfN5eJ7e06BJ8aKwNtD6FVPvrvqT911wFCLzMnZ81/L\n
gqPU1mY4bFHHXhG/7C0cY7AMLEcWLo1cKYBooin5qx4GjzMKEFfjaHEHj2PcPShF\n
yZw01turPiM0/qMybJvgLKp3ib2odC/+MNBNS/MCgYEAwPi+orAyw432W0WtnW9b\n
8dUH8yDIau8I6l2H7y9yXUHUfWMcAJqVs8APDtv+AqHluvyX2cchDfE29sv7DFOF\n
LBVBQ2nv1RnrklCVGl9NC9+hECsIWQr2werchzZN5vJQBlt7/m+yVxd8kMxgP2Oe\n
hARc/acdS9fNwO2dTmZI84UCgYAhvN9Dgj0kUT8kLb/b1mHv9yZCc3G+pC1uwmnm\n
ZaGoDAufRYEtaogWw7HTEexOKNP5lHuc3Vjd5aegXQD0flKlii4oCMCkcUutamnf\n
l5b3szT0Q/g9yZIaLA6thNXxd5hvhWQmGDa0mmdrmh7U/fcJAVJlP0VT41Q5ry7H\n
gu/4yQKBgQDKc65UNsvaPxSI5y7JnoQ9l+P8DknPY1RXXzwfQVdq20EhxXeirzuh\n
6qrB0uW3Fa8Du2t1pRdnVqmFe9BW7Sem5PTH1iwxBGYHYciErzFvHKVTRCpEY8/a\n
KfGSVxMUK8EefX0JSj4Tm8zrZTGxlSDK1PsHU8UsKZR7anh+TkTM3g==\n
-----END RSA PRIVATE KEY-----
Public Key:
-----BEGIN PUBLIC KEY-----\n
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq6UTzL3bzW85zqixWhuL\n
csSxkwpqwlYuG9hUQ/WuskWhcNOxqOQ03c5V7MVjnX5P25tXKVlNLtmlnlIYnAqX\n
Jd3f/7zlNodw12RS+Cd9HyRbIQ/6G8s5UUb/JNPiIjYNDseQfaI4nrpnzmD99O7N\n
7KxI8nNf1zc+T8sYt8jX1CrPuuPe5n38AEN2k/23ijHHdln7hWCVCk5pT1rHx4Qg\n
DdDLft6eKltm8wrwXv20r5d6W6dkcRS1nPBOyESKrBvSdjQqj6XartZh+Os5v13+\n
ikyPJIAJk8A5hvLEo6uhCU2sz7UI1kPoDmHPFZbAqjzm/jNmPm9YYVaRheL7JmRm\n
1wIDAQAB\n
-----END PUBLIC KEY-----
Here is the plain-text message we are trying to sign:
ed6235936c5c81ce8ea007480f955441204605a0a6777f17ee75af7a369442ec
We see the following signature results (All in Base64):
WolfSSL:
NzJlMzBmNjRkMGY0ZTM1ZjU2MGQyODlkZjdkNWJmNTRhNzVlMGE4NTc0ODMxMGJkOGNmNTE0NGVlMjFkOGNmZjQ4MzU3YTA0YWFlOTBjODgwZmY5M2FlMjUyZjA4YWRhOTQxNjkwMTRmNWU4Njc5ODczYTJkYzAwNmYxYjc3MDIwYTM3ZDJkZjJhZTMxY2Y1ZWNlZjkwOTkyNWQxYjE1MDk1NzYyMGMwNzI1NDkzNDFiYTRmMjMzMzg5NzVkNjcxZmM2NjA0MThmZWFkOTNmYmRiM2Y0ZmM0ZDk0NzMzZWMzMmE4ZmYzMjM2MGRlYjFjMmJlZTNkNGE3ZGEyN2ZjMDY1ODkzZGZkNWFjMjc3MjE3N2FlZTNmNDllODI4NDAzZWNmYjM0NTMxYzhlOTg1NWI5N2FkNzg0ZDFjOTI0NGVlODU1NDhjYzBjZmY1ODgzYTE3Y2E0Njc4NDgyYWU2ODk4OTk2YTQyMTQzZTc2Yzg5MTYyMWY1N2VjYzU2NTM0N2RhZmExMGExZTJkZjA0MjQ5ZmYzZjI2ZGU0OGI4OGEwM2Q3OWVkOGU4MjYyMGM1ZDVjNzM5NjYwZmNjMjY3NjBjODBhNDYxZmU1OTZkZDUyNWJmNThjZjIyYzg3Y2E5NTkwMGI3NTFkZGFmODJhNjBiODZjNmY0OWNjN2U4YzU=
OpenSSL:
fjC40FP6WHZ/wgHrJ/46ivXD0PTGattWnhQ1w1SmQMfZza3kNhvln/kh5bfyIzi+35lFDndlvl+Srhd8+n3lfW91UnVxOmi90rM0x8SsIeh9LU+vd293rfK2rgLS47p+iK8ZL4BIvJQ0Z9aK4/QCSvyft2Oeto5vG4FbByrsbR7H4gsZpiHwujOUI6S/GlOPzCSe++MIPkPFWDV07YVKPv7E+Fos/XfLmOR7MY5lERRIj+NqAWLeOKRht+XNpuflxDpQ9vXJnPn/h5feYsT6AFHCrn3fCqr74kAYdHqbEiWrdleIaQrSI05FtBpHlD5ncP4hImojA6BTpPnRznVbrQ==
Python:
fjC40FP6WHZ/wgHrJ/46ivXD0PTGattWnhQ1w1SmQMfZza3kNhvln/kh5bfyIzi+35lFDndlvl+Srhd8+n3lfW91UnVxOmi90rM0x8SsIeh9LU+vd293rfK2rgLS47p+iK8ZL4BIvJQ0Z9aK4/QCSvyft2Oeto5vG4FbByrsbR7H4gsZpiHwujOUI6S/GlOPzCSe++MIPkPFWDV07YVKPv7E+Fos/XfLmOR7MY5lERRIj+NqAWLeOKRht+XNpuflxDpQ9vXJnPn/h5feYsT6AFHCrn3fCqr74kAYdHqbEiWrdleIaQrSI05FtBpHlD5ncP4hImojA6BTpPnRznVbrQ==
Source code with our experiments (OpenSSL and Python) are in the attachment.
WolfSSL-based source code (signature part only) is below:
//...
static const byte private_key_pem[] =
"-----BEGIN RSA PRIVATE KEY-----\n\
MIIEpAIBAAKCAQEAq6UTzL3bzW85zqixWhuLcsSxkwpqwlYuG9hUQ/WuskWhcNOx\n\
qOQ03c5V7MVjnX5P25tXKVlNLtmlnlIYnAqXJd3f/7zlNodw12RS+Cd9HyRbIQ/6\n\
G8s5UUb/JNPiIjYNDseQfaI4nrpnzmD99O7N7KxI8nNf1zc+T8sYt8jX1CrPuuPe\n\
5n38AEN2k/23ijHHdln7hWCVCk5pT1rHx4QgDdDLft6eKltm8wrwXv20r5d6W6dk\n\
cRS1nPBOyESKrBvSdjQqj6XartZh+Os5v13+ikyPJIAJk8A5hvLEo6uhCU2sz7UI\n\
1kPoDmHPFZbAqjzm/jNmPm9YYVaRheL7JmRm1wIDAQABAoIBADwukJ8ocIF6vp+F\n\
iU2JO98dNQ/TxrPl6JvNwVnksgCCpoS7TN7lSN3+YyU13mQRrilXMXvnekbze/zj\n\
VwqbMfzOayQtVIbGfVugKvEkU1wQcL1Kb0zAeBPV207L1c1d+z0T3scWElkhDZWQ\n\
b2qqMlyJ2bfcmR2KGph6ouuJiZczaobyhSyesdpQ0aRtGpw0liRm4C7FV+zvjQaw\n\
TRofICs5yD/36UcuJ466/ht5ZKeSrolpaBRx5AGjKKfU11uH+FQGn4whdUPHnljK\n\
z+ksz7I/ztWg+RBx4ymn3/cTtf5h6Iua+GEoafgKO0IhGUPguqsa4umXq3l6r0PC\n\
H0gF/N0CgYEAzh/vKF0NK94thsYrZeQPCt1sDefW9W3OMfzYzYxnpXV5Vd8NR5jq\n\
wExiUJlmMJeC2OJ96LjNATceFmbO6ZvgRWf4ZGs+x1dnI7ZplViGMuo4N/YOGEW6\n\
nbMtzRmHB46jjdcLeD6F57t8s++qQ4SSDPAvvbm06rIpVdH8wP+mpo0CgYEA1S1X\n\
L4ZiS/rzmHT+KdEl+CDuXgfN5eJ7e06BJ8aKwNtD6FVPvrvqT911wFCLzMnZ81/L\n\
gqPU1mY4bFHHXhG/7C0cY7AMLEcWLo1cKYBooin5qx4GjzMKEFfjaHEHj2PcPShF\n\
yZw01turPiM0/qMybJvgLKp3ib2odC/+MNBNS/MCgYEAwPi+orAyw432W0WtnW9b\n\
8dUH8yDIau8I6l2H7y9yXUHUfWMcAJqVs8APDtv+AqHluvyX2cchDfE29sv7DFOF\n\
LBVBQ2nv1RnrklCVGl9NC9+hECsIWQr2werchzZN5vJQBlt7/m+yVxd8kMxgP2Oe\n\
hARc/acdS9fNwO2dTmZI84UCgYAhvN9Dgj0kUT8kLb/b1mHv9yZCc3G+pC1uwmnm\n\
ZaGoDAufRYEtaogWw7HTEexOKNP5lHuc3Vjd5aegXQD0flKlii4oCMCkcUutamnf\n\
l5b3szT0Q/g9yZIaLA6thNXxd5hvhWQmGDa0mmdrmh7U/fcJAVJlP0VT41Q5ry7H\n\
gu/4yQKBgQDKc65UNsvaPxSI5y7JnoQ9l+P8DknPY1RXXzwfQVdq20EhxXeirzuh\n\
6qrB0uW3Fa8Du2t1pRdnVqmFe9BW7Sem5PTH1iwxBGYHYciErzFvHKVTRCpEY8/a\n\
KfGSVxMUK8EefX0JSj4Tm8zrZTGxlSDK1PsHU8UsKZR7anh+TkTM3g==\n\
-----END RSA PRIVATE KEY-----";
static const byte public_key_pem[] =
"-----BEGIN PUBLIC KEY-----\n\
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq6UTzL3bzW85zqixWhuL\n\
csSxkwpqwlYuG9hUQ/WuskWhcNOxqOQ03c5V7MVjnX5P25tXKVlNLtmlnlIYnAqX\n\
Jd3f/7zlNodw12RS+Cd9HyRbIQ/6G8s5UUb/JNPiIjYNDseQfaI4nrpnzmD99O7N\n\
7KxI8nNf1zc+T8sYt8jX1CrPuuPe5n38AEN2k/23ijHHdln7hWCVCk5pT1rHx4Qg\n\
DdDLft6eKltm8wrwXv20r5d6W6dkcRS1nPBOyESKrBvSdjQqj6XartZh+Os5v13+\n\
ikyPJIAJk8A5hvLEo6uhCU2sz7UI1kPoDmHPFZbAqjzm/jNmPm9YYVaRheL7JmRm\n\
1wIDAQAB\n\
-----END PUBLIC KEY-----";
printf("private_key_pem:\n%s\n", private_key_pem);
printf("public_key_pem:\n%s\n", public_key_pem);
static byte private_key_der[4096] = {0};
RsaKey key;
WC_RNG rng;
wc_InitRng(&rng);
wc_InitRsaKey(&key, NULL);
int32_t private_key_der_size = wc_KeyPemToDer(private_key_pem, strlen((const char*)private_key_pem), private_key_der, sizeof(private_key_der), NULL);
word32 idx = 0;
return_value = wc_RsaPrivateKeyDecode(private_key_der, &idx, &key, private_key_der_size);
static byte message[] = "ed6235936c5c81ce8ea007480f955441204605a0a6777f17ee75af7a369442ec";
// Get signature length
int message_signed_size = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA, &key, sizeof(key));
static byte message_signed[4096] = {0};
// Perform signature generation using private key
return_value = wc_SignatureGenerate(
WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA,
message, (strlen(message) + 1),
message_signed, &message_signed_size,
&key, sizeof(key),
&rng);
printf("Signature Generation: %s (%d)\n", (return_value == 0) ? "Pass" : "Fail", return_value);
static byte message_signed_base16[4096] = {0};
word32 message_signed_base16_size = sizeof(message_signed_base16);
Base16_Encode(message_signed, message_signed_size, message_signed_base16, &message_signed_base16_size);
//Convert all chars to lowercase
for(int cnt = 0; message_signed_base16[cnt]; cnt++)
{
message_signed_base16[cnt] = tolower(message_signed_base16[cnt]);
}
printf("message_signed_base16:\n%s\n", message_signed_base16);
static byte message_signed_base16_base64[4096] = {0};
word32 message_signed_base16_base64_size = sizeof(message_signed_base16_base64);
return_value = Base64_Encode_NoNl(message_signed_base16, strlen((const char*)message_signed_base16), message_signed_base16_base64, &message_signed_base16_base64_size);
printf("message_signed_base16_base64:\n%s\n", message_signed_base16_base64);