How to use RSA 1024 if 8 byte string is encrypted as 172 byte string, but RSA works on strings less than 62 bytes? - rsa

My question is implementation-irrelevant, but I am giving implementation details anyway: I am working with Delphi 10.2 TurboPower LockBox 2 (https://github.com/jarto/lockbox2) implementaion. This is quite popular library for Delphi and that is why I am expecting that it works reasonably well and that is why my question is not about possible failures in the particular implementation but is more about the way RSA works.
I have 8 character string and I am encrypting it with the public key RSA 1024, and the resulting string ir 172 bytes long. How can I decrypt with the private key RSA 1024, if https://stackoverflow.com/a/5868456/1375882 suggest that the maximum length of the message should not exceed 62 bytes?
I is possible to generate shorter encryptions (less than 60 bytes) with RSA 1024 to be on the safe side that I can decrypt them in reasonable time?
While I can decrypt the 172 byte message with the private key within some seconds. I am experiencing the problem in the other direction encryption with the private key is fast, the the decryption of the 172 byte string with the public key is unreasonably long - more than 10 minutes and even then the result is not achieved.
So - I guess that the referenced SO advice about the maximum length of 62 bytes should be observed, but how can I observe this rule if encryption generates strings that are 172 bytes longs?

Related

STUN MESSAGE-INTEGRITY dummy definition

in RFC5389 MESSAGE-INTEGRITY calculation includes itself but with dummy content
dummy content is not defined
how can MESSAGE-INTEGRITY be verified without knowing dummy content value?
why would MESSAGE-INTEGRITY calculation include itself?
is't it faster to calculate MESSAGE-INTEGRITY and equally secure if it didn't include itself?
Since the MESSAGE-INTEGRITY attribute itself is not part of the hash, you can append whatever you want for the last 20 bytes. Just replace it with the hash of all the bytes leading up to the attribute itself.
The algorithm is basically this:
Let L be the original size of the STUN message byte stream. Should be the same as the value for MESSAGE LENGTH in the STUN message header.
Append a 4 byte header onto the STUN message followed by 20 null bytes
Adjust the LENGTH field of the STUN message to account for these 24 new bytes.
Compute the HMAC/SHA1 of the first L bytes of the message (all but the 24 bytes you just appended).
replace the 20 null bytes with the 20 bytes of the computed hash
And as discussed in comments, the bytes don't have to be null bytes, they can be anything - since they aren't included in the hash computation.
There's an implementation of MESSAGE-INTEGRITY for both short-term and long-term credentials on my Github: here and here

Convert between X.509 and PKCS#1 RSA Public keys

I am using CryptoPP to generate RSA keys, and run encryption / decryption of large amounts of data. Because of this, I am deciding to input data through a web socket from a phone app (currently using flutter), along with already in place desktop clients (the desktop clients work as they support the format the server uses).
My issue is that the keys are in different formats, everything I try (specifically simple_rsa) fails to be compatible with the server. As flutter only supports PKCS#1 as far as I am aware.
I understand now that the public key is formatted with X.509 from crypto++ wiki, and through use of an online tool this I have found that the cipher type (I'm guessing padding?) is OAEP with SHA-1.
These show that both key types are encoded with ASN.1
For reference, the server code is very similar to this, but uses a key size of 4096
////////////////////////////////////////////////
// Generate keys
AutoSeededRandomPool rng;
InvertibleRSAFunction parameters;
parameters.GenerateRandomWithKeySize( rng, 1536 );
RSA::PrivateKey privateKey( parameters );
RSA::PublicKey publicKey( parameters );
And the key is written to a .pem file by encoding the data in base64.
std::string base64 = macaron::Base64::Encode(pubKeyString);
std::string base64LineLength;
int i = 0;
while (i < base64.size()) {
if (i % 64 == 0 && i)
base64LineLength.push_back('\n');
base64LineLength.push_back(base64[i]);
i++;
}
base64LineLength = "-----BEGIN PUBLIC KEY-----\n" + base64LineLength + "\n-----END PUBLIC KEY-----\n";
std::ofstream pubkeyOut("secure_chat_rsa.pub");
pubkeyOut << base64LineLength;
pubkeyOut.close();
Also, this is an example of a public key with the formatting (X.509)
-----BEGIN PUBLIC KEY-----
MIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKCAgEAmQlXbYS1I+B4AUXwU/ua
KgwdrUzYRwXPaR6435DAguDGW+zTeekDgP55lg9Lqn32UW+T/5PIgYQ2HpA/gfYU
IMvrLAhSSaXSEFzIzdwgFgo3IMZHdhcx/xP/+pmDTrflhmba/7QEOE/bC2hFzQCh
2Zd1DJbItIR64uyyi1Z0B6bFlLyDA2E+lctBLhuHSyYSqPrVUqYTRdptLNk8/vsN
HdWKrYq7H8n4QKQefspD5zU3SJdUumOIusqzXeMe70mPds+Qe9u4Ti5Ca7guZCN4
kNXUF/kJH7Y3dBh7409r2v/bjGEznFpY1cmP1f0EFYTQU1BirbNiwqnAjhy9fT2M
quSlpmwo7V0YbZDI/KBcLDxTY64oO6XMz6DHkdmpOluALWQAJZFJ7iHntsLp1GRB
DtLaidCr9EI+pN7cfwsSYLRHtEmUZoiz30RZra5c5+aE4sg24c/PJ5nVe9GDOaQs
dHL3+sc2r9LTEK9pCSO5cWdbxSRvKNrevElr2+8ORUQL1cRsCmL8ri4eYwrwukBn
HFJc1pZFD8i5sFjnJxEIKzoIa+eGVgqEwkwxKvNuUUyH3tJD9YJVlhs1G68VlxOf
RSk+LZGhwSMZs+PbfuxmPQZyapT5TqRJ2JJ7f9HErIq5f8WjBrzcqy63rygy33Hw
M94iQLwuTM3X99Z4FnyTsTECARE=
-----END PUBLIC KEY-----
Edit:
I have tried putting the key through an ANS.1 decoder, and extracted the bit string from it, then put that through a base64 encoder to give:
MIICCAKCAgEAmQlXbYS1I+B4AUXwU/uaKgwdrUzYRwXPaR6435DAguDGW+zTeekDgP55lg9Lqn32UW+T/5PIgYQ2HpA/gfYUIMvrLAhSSaXSEFzIzdwgFgo3IMZHdhcx/xP/+pmDTrflhmba/7QEOE/bC2hFzQCh2Zd1DJbItIR64uyyi1Z0B6bFlLyDA2E+lctBLhuHSyYSqPrVUqYTRdptLNk8/vsNHdWKrYq7H8n4QKQefspD5zU3SJdUumOIusqzXeMe70mPds+Qe9u4Ti5Ca7guZCN4kNXUF/kJH7Y3dBh7409r2v/bjGEznFpY1cmP1f0EFYTQU1BirbNiwqnAjhy9fT2MquSlpmwo7V0YbZDI/KBcLDxTY64oO6XMz6DHkdmpOluALWQAJZFJ7iHntsLp1GRBDtLaidCr9EI+pN7cfwsSYLRHtEmUZoiz30RZra5c5+aE4sg24c/PJ5nVe9GDOaQsdHL3+sc2r9LTEK9pCSO5cWdbxSRvKNrevElr2+8ORUQL1cRsCmL8ri4eYwrwukBnHFJc1pZFD8i5sFjnJxEIKzoIa+eGVgqEwkwxKvNuUUyH3tJD9YJVlhs1G68VlxOfRSk+LZGhwSMZs+PbfuxmPQZyapT5TqRJ2JJ7f9HErIq5f8WjBrzcqy63rygy33HwM94iQLwuTM3X99Z4FnyTsTECARE=
However, this is not a valid RSA key. (from trying to encrypt with it)
I have 4 main questions:
Is there a way for the X.509 format to be converted to PKCS#1 and vice versa
If converted, will the output be compatible. When the server encodes data, will the client be able to decrypt it if the keys are converted?
Is there a way for flutter to work with X.509 formatted keys?
If this is only due to ANS.1, how exactly would you go about encoding ciphers or keys?

How to reduce the length of a message encrypted with Hybrid encryption

I was looking for a good encryption scheme to encrypt my message and i founded that the Hybrid encryption is good for large and small messages. but i have a problem with the length of the output cipher message which is large.
if the input was "hello", then the length of the output message will be 586, and twice if if the message larger
here is the Encrypt function that i use:
def encrypt(username, msg):
#get the reciever's public key
f = open("{}.pem".format(username)) # a.salama.pem
recipient_key = RSA.import_key(f.read())
f.close()
# Encrypt the session key with the reciever's public RSA key
cipher_rsa = PKCS1_OAEP.new(recipient_key)
# Encrypt the data with the AES128 session key
session_key = get_random_bytes(16)
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(msg)
#finishing your processing
encrypted_data = cipher_rsa.encrypt(session_key) + cipher_aes.nonce + tag + ciphertext
encrypted_data = hexlify(encrypted_data).decode("utf-8")
return encrypted_data
There's a fixed number of extra bytes in the header regardless of the amount of plaintext being encrypted. That's evident from your line of code
encrypted_data = cipher_rsa.encrypt(session_key) + cipher_aes.nonce + tag + ciphertext
This extra data will be dominated by the RSA-encrypted session key. A more space-efficient choice would be ECIES using a well-known 256-bit elliptic curve.
However, you also have expansion of the data due to encoding. Your choice of encoding is hex encoding which doubles the amount of data. A more efficient and well-supported encoding is base64 encoding. Base64 encoding expands the data by a factor of 4/3. The most space-efficient is avoid encoding altogether and just store and transmit raw bytes. You only need to encode the data if it will transit over channel that cannot handle binary data.

Visa RSA keys length

I just found that Visa public keys have odd length like 1408 bits. On the other hand found most crypto libs (OpenSSL, Bouncy Castle, MS crypto API, Java Card) require fixed keys length like 1024 or 2048. I can see that in theory RSA key can be of any length but I do not understand:
1) why would visa use strange key lengths
2) which of the above libs will work with 1408 bits keys
Thanks!
The 1408 key is part of the Visa's EMV Public Key infrastructure. It is basically used with smart cards (on-card chips). The key size was chose because of the ability of the card to handle it (via an on-chip RSA accelerator). There is actually a schedule of keys. The 1408 key is set to expire December 31 2022. The 1024 key is already expired.
According to the emvco.com faq they do not use x.509 but ISO/IEC 9796-2 digital signature algorithm. Bouncy Castle has a 9796-2 signer (org.bouncycastle.crypto.signers.ISO9796d2PSSSigner). Card Contact has a lib and tutorial

What are those "garbage" 16 bytes at the beginning of an unencrypted EncryptedData tag from an encrypted ws-security SOAP message? (WCF)

I'm inspecting a WCF request message in order to implement part of the WS-Security standard to have iPhone <-> WCF intercommunication (I'm using certificate security over basicHttpBinding).
After reading the standard xmlenc-core I could decrypt both the SignedInfo and the Body tags, but I see 16 bytes at the beginning of both unencrypted tags from which I have no idea.
I create a sample application according to the standard in order to send request from the iPhone to a self hosted WCF but it continues responding "An error occurred when verifying security for the message".
The only thing I don't know how to implement are those 16 bytes, does anybody knows what to use on those 16 bytes?
Thanks
When using Triple-DES and AES the cipher-text is prefixed by the IV. So when decrypting, you should use the first 16 bytes of the value as the IV and then perform the AES-CBC decryption on the remaining bytes. My guess is that you have forgotten this and thus are decrypting the IV also (which will yield garbage).