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

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?

Related

Swift Load RSA Public Key from String (MacOS)

i was wondering how could i load a RSA Public Key from a String and encrypt another string with it.
The public key is something like:
let key = """ -----BEGIN PUBLIC KEY----- blah blah blah -----END PUBLIC KEY-----"""
I would prefer to do this without an outside library but if it makes things easier im willing to use them.
Thanks in advance.
The key data you have is PEM encoded. However, Apple supports DER encoding for their security API. So first we'll have to transform your key data to the correct format. The example below is created with a random RSA key exporting the public key to PEM format. PEM headers can differ from library to library, so be sure you remove the tags, before continuing to the DER transformation.
var pem = "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAs6AofVx+UAXcVjnIU0Z5SAGO/LPlTunA9zi7jNDcIrZTR8ULHTrm\naSAg/ycNR1/wUeac617RrFeQuoPSWjhZPRJrMa3faVMCqTgV2AmaPgKnPWBrY2ir\nGhnCnIAvD3sitCEKultjCstrTA71Jo/BuVaj6BVgaA/Qn3U9mQ+4JiEFiTxy4kOF\nes1/WwTLjRQYVf42oG350bTKw9F0MklTTZdiZKCQtc3op86A7VscFhwusY0CaZfB\nlRDnTgTMoUhZJpKSLZae93NVFSJY1sUANPZg8TzujqhRKt0g5HR/Ud61icvBbcx8\n+a3NzmuwPylvp5m6hz/l14Y7UZ8UT5deywIDAQAB\n-----END RSA PUBLIC KEY-----\n"
// Remove headers and footers from the PEM, leaving us with DER encoded data split by new lines
[
"-----BEGIN RSA PUBLIC KEY-----", "-----END RSA PUBLIC KEY-----",
"-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----"
].forEach { pem = pem.replacingOccurrences(of: $0, with: "") }
// Construct DER data from the remaining PEM data
let der = Data(base64Encoded: pem, options: .ignoreUnknownCharacters)!
Now that we have our DER encoded data, it's time to construct our key. Firstly, create the attributes describing the key, after that create the key from the DER data. Note here how der is of type Data not of type String. Generally speaking, crypto operations occur on Data. The security API however uses CFData, but one can easily exchange them (as CFData or as Data). The same goes for the attribute dictionary.
// Key generation attributes
let attributes: [String: Any] = [
String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
String(kSecAttrKeyClass): kSecAttrKeyClassPublic,
String(kSecAttrKeySizeInBits): der.count * 8
]
// For simplicity I force unwrap here. The nil parameter can be used to extract an error
let key = SecKeyCreateWithData(der as CFData, attributes as CFDictionary, nil)!
Now that we have our key, we can use it to encrypt. Be aware however that RSA cannot encrypt huge amounts of data (not technically true, you could create chunks of data and do it that way, but RSA is not intended for this. If you want to do such thing, read up on key exchange and symmetric encryption. RSA is not intended for that behaviour). Also note that OAEP (as used in the example) has a random factor to it. Meaning the cipher text output will differ each time you run this code. This doesn't mean it's not working, it's simply a property OAEP has. I'd also like to point out that PKCS1 padding should be avoided when able in favour of OAEP.
// An example message to encrypt
let plainText = "This is my secret".data(using: .utf8)!
// Perform the actual encryption
// Again force unwrapping for simplicity
let cipherText = SecKeyCreateEncryptedData(key, .rsaEncryptionOAEPSHA256, plainText as CFData, nil)! as Data
In the example above .rsaEncryptionOAEPSHA256 is used. This is one of the available encryption algorithms for RSA:
.rsaEncryptionRaw
.rsaEncryptionPKCS1
.rsaEncryptionOAEPSHA1
.rsaEncryptionOAEPSHA224
.rsaEncryptionOAEPSHA256
.rsaEncryptionOAEPSHA384
.rsaEncryptionOAEPSHA512
I highly recommend using one of the OAEP variants, but that is up to you. I hope this helps. The SecKeyCreateEncryptedData is available for macOS since 10.12. You can read more about it here.

Swift: RSA Encrypt a string with a specific private key

I need to write a method in Swift which uses a particular PRIVATE KEY to encrypt a timestamp using RSA. This is NOT used for authentication (rather it validates the client app to the server), I know that you would normally encrypt with a public key to ensure security.
I have a key:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDIg+wteSjhalc1hSHEiUnz9X1pkrObCjaXMHqeSdfFQ/h5Q1Uh
...
o7wjoqFNxFnQMAYvkLzQZ7Y2jjfSJkaTVnhzJIZOfQ0=
-----END RSA PRIVATE KEY-----
And I need to encrypt a string using this particular key. I have written the Android application version of this app, but if I need to re-generate the keys specifically for iOS it's not a problem, but I would need this file for the Android version as well.
I have looked at the following web sites:
http://jslim.net/blog/2013/01/05/rsa-encryption-in-ios-and-decrypt-it-using-php/ Seems useful but it insists that the key be in a .der format - plus it's in Objective-C. Is it possible to generate a Key pair in both DER and PEM format, or convert between the two (using something like https://www.sslshopper.com/ssl-converter.html)?
https://github.com/henrinormak/Heimdall - but you cannot import a custom private key
https://github.com/ideawu/Objective-C-RSA/blob/master/RSA.m - seems long winded and is also in objective-c
One requirement is that all apps use the SAME key - it cannot be generated by each installation of the app. Also my Android app must be able to use the key as well (I am open to rethinking the Android version as leaving the key as a RAW file is not preferred for me).
Any help will be appreciated.
Other references checked:
How to encrypt a string with private key and decrypt with public key?
Using RSA public key to encrypt a string

What is the public portion of a base 64 encoded X509 certificate

Its not about how i get it, but its fine if you tell me also, but i simply dont know what this is:
If "asymmetric", the Value parameter must be set to the public portion
of a base 64 encoded X509 certificate.
I have the certificate in the MMC.exe in windows and under export i have found out that i can export a .cer file without the private key. This file .cer is just a file containing text.
------BEGIN CERTIFICATE-------
BASE64 I ASSUME
-------------------------------
is it the content of this file, all of it, the stuff between the lines or?
Base64 encoded bytes that compose a struct with this information: http://en.wikipedia.org/wiki/X.509#Structure_of_a_certificate
The most essential parts, functionally: your public key, your name, and the signature (of those) by your CA ( that is, a trusted third party vouching that the person having the corresponding private key is the specified name ).

IPhone Decryption with private key -Data Encrypted in Java

Can anyone help with the code how to decrypt with private key ,As in server side they are using OAEP encryption method .I tried decrypting using private key but the decrypted text is Null,I am getting the Error code as -9809 as decryption code result
When you say "with a private key" I assume you mean you're using SecKeyDecrypt() for asymmetric encryption rather than CommonCryptor for symmetric encryption.
SecKeyDecrypt() does not support OAEP. It only supports PKCS1 v1.5 padding (kSecPaddingPKCS1). It can also technically handle ASN.1 padding + PKCS1 padding, but this isn't usually relevant to decryption. You should have noticed this when you passed the SecPadding parameter. What did you pass?
That error number is errSSLCrypto which is a generic "something went wrong in crypto" message.

RSA iphone public key

I have a Public Key generated in JAVA.
I want to use this key and crypt the data using RSA and send it to the server.
How can I do that using the iPhone SDK?
Thanks
Unfortunately, iOS has no public APIs to deal with raw RSA keys.
There are two things you can do:
1) Instead of giving your app a Public Key, give your app a certificate instead. You can import the certificate with SecCertificateCreateWithData. Then create a trust with SecTrustCreateWithCertificates. Once you have the trust, you can extract the public key with SecTrustCopyPublicKey.
2) The other option is to include OpenSSL in your project. It has all the APIs you need, you can google for example code on how to work with RSA keys. This might be the simpler solution.
I have made available a script to easily build OpenSSL from source. You can grab it from:
http://github.com/st3fan/ios-openssl
If your public key is in modulus/exponent form, this question may help: Convert XML Dsig format to DER ASN.1 public key
I figured out how to binary-encode the modulus and exponent into the DER ASN.1 format that the SecKeyWrapper class of Apple's CryptoExercise project uses to import an external key.