As stated here, the length of the message signature is equal to the modulus of the Private Key, aka the Public Key.
I'm implementing a system that signs a message, and I have a size mismatch that I can't solve.
I use crypto++
.
Here is the code I use :
/* Create RSA Keys */
RSA::PrivateKey privateKey;
privateKey.GenerateRandomWithKeySize(prng, 3072);
RSA::PublicKey publicKey(privateKey);
cout << ">> RSA Keys generated";
/* Key Size */
string spki;
StringSink sSink(spki);
publicKey.Save(sSink);
cout <<" ("<< spki.size()<<" bytes)"<<endl;
RSASSA_PKCS1v15_SHA_Signer signer(privateKey);
size_t length = signer.MaxSignatureLength();
cout <<"MaxSignatureLength " <<length<<endl;
SecByteBlock signature( length );
And the output is :
>> RSA Keys generated (420 bytes)
>> ServerHello sent (436 bytes)
MaxSignatureLength 384
RSA Signature length 384
Shouldn't the MaxSignatureLength
, and the RSA Signature length
420 bytes long ?
Is the problem with the algorithm I use ?
The maximum size for RSA is 512 bytes. The maximum size of ECC is 132. For RSA, this must be at least the byte length of the modulus rounded up to a multiple of 32 bytes for the X9. 31 signature format or one byte for all other signature formats.
RSA Digital Signatures To sign a message m, just apply the RSA function with the private key to produce a signature s; to verify, apply the RSA function with the public key to the signature, and check that the result equals the expected message. That's the textbook description of RSA signatures.
SHA256 with RSA signature is an efficient asymmetric encryption method used in many secure APIs. This algorithm first calculates a unique hash of the input data using SHA256 algorithm. The hash is then encrypted with a private key using the RSA algorithm.
Shouldn't the MaxSignatureLength, and the RSA Signature length 420 bytes long ?
No. You are asking for a key with 3072-bits or 384 bytes. That's the limit on the size of the signature.
Each cryptosystem will likely be different in this area.
cout <<" ("<< spki.size()<<" bytes)"<<endl;
This is the size of {OID,n,e}
with the ASN.1 framing or overhead. See your previous question Sending PublicKey within packet payload for what it looks like (in particular, the output of the command dumpasn1 rsa-public.der
).
cout <<"MaxSignatureLength " <<length<<endl;
This is n - 1
for RSA, if I recall correctly.
Is the problem with the algorithm I use ?
No, you are doing things correctly by calling MaxSignatureLength()
.
>> RSA Keys generated (420 bytes)
>> ServerHello sent (436 bytes)
I'm just speculating, but it appears you appear to have design issues, too.
When you encrypt a message, like the ServerHello
, you usually encrypt it under a symmetric cipher, like AES or Camellia. Then, you take that symmetric cipher key, and encrypt it under the RSA key. Finally, you send the pair {encrypted symmetric cipher key, encrypted message under symmetric cipher}
to the other party.
In the system partially described above, you're only encrypting 16 or 32 bytes under the public key.
I think what you should be doing is using an Integrated Encryption Scheme to send encrypted message back and forth. For that, see Elliptic Curve Integrated Encryption Scheme (ECIES) and Discrete Logarithm Integrated Encryption Scheme (DLIES). ECIES operates over elliptic curves, and DLIES operate over integers.
Integrated Encryption Schemes have some very desireable security properties, like they are IND-CCA2. They achieve it by not allowing you to do some things, like reusing a security context, so the security is baked into the scheme.
You still have to solve the key distribution problem, though. That's a thorny problem, and we don't have a good, scalable solution.
And now you see why algorithm agility is important, and why you want that OID sent as part of the key during the handshake phase :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With