OpenSSL RSA Public Key encryption in Java in Server and decryption with Private Key in Client in OSX - macos

I have an application which is client/server based. The client is developed for both iOS and OSX. The server is common for both the clients (and server's implementation cannot be changed).
The client developed in iOS generates an RSA public/private key pair and send the public key in base64 encoding to the server. The server (implemented in Java) encrypts some secure data and sends the same to the client who is required to decrypt data with the private key. The RSA key pair is generated on iOS using the Crypto Exercise Sample provided by apple.
The public and private key generated (of key length 1024) in base64Encoding is of length 216 and 844 bytes respectively and of the form provided below.
Private Key:
MIMAAnQwDQYJKoZIhvcNAQEBBQAkabeCYAAwggJbAgEAAoGBANDV3P+17zCIw/ZIwjM/5q7DeEEi4AVYE2STPnbuApvc0JjC3gx+F+mLtCfR+lxi0TAWqdFK6MkjGzyKONcEHRWxA/7ltFC1RlgEWzxmdr4kOEL5DV6DRep4Ykh4guvGf3A4N1A87com0rSjOoWR++N9HCmGxrnEhgV7gb9wknoRAgMBAAECgYAS+pyvEJXAT22fwFUF21TXpSQUp1q8oZiBl3Ah1ted2p+Kgoszj3IU44Fn7QlXxBNGz4h3YNtvDCWS3JVp1RHfZRonPdrvcwSMSk6M7crxS0NTxZlhvbgTuD2AlKjAT381gMUAxGGm9tvHlxwxhuIFEmXV1rz3hxbPYyFppCCrwQJBAd83wa9FwfGkcWU/gN3I0kJc8EfQwYDooY/V6hLcCYNW7wXyn3ja6Xl9XtgQnPeYSx+h2bGs339cDPKYtG2imm0CQG+PiLA8IHmIJDiEeB+jIRXAizd2aMgsvUomjWmMiYl/SPocvL3HxgGhvNNs8tUJKcw+/JhKPSBFX2+aRF55l7UCQQEZmVsQUs6P35De7T0dlrevVYvAt7QtuwXNTueYo4JXkosslJEPZJxTzs8f6ktC11Q1x1b0KGDBJ2dYW1GTJzzVAkBB6iq3Bi+h3wCXrB1VhAsOUR9we7PZYiXNZA31qSWyadRygvw5nYmueSOaQCi1Ep7xoN2aFXMcWCDVTe7La0hpAkBjBU9PDamhULFstd4hlx2UkPOGGnWZCAnr2zU+r2Q12eK20tjDZzS4TQWZWmKXkI2QAd+SJ44oI6+hZq5AHHEl
Public Key:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADkIJlKBgQDQ1dz/te8wiMP2SMIzP+auw3hBIuAFWBNkkz527gKb3NCYwt4Mfhfpi7Qn0fpcYtEwFqnRSujJIxmTFzjXBB0VsQP+5bRQtUZYBFs8Zna+JDhC+Q1eg0XqeGJIeILrxn9wODdQPO3KJtK0ozqFkfvjfRwphsa5xIYFe4G/cJJ6EQIDAQAB
Things are working fine in the iOS world.
I am trying to implement this in the MAC using Objective-c and find that the Crypto Exercise sample is not working as expected. The SecItemCopyMatching is returning failure.
While investigating for the solution found that the public/private key using Open SSL met the criteria of private and public key except for the header and footer that is appended to the generated key pair.
I used the SSCrypto OpenSSL wrapper (http://septicus.com/products/opensource/) to generate the public and private key pair using OpenSSL which is of the form.
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCrEgoLjG34pNLj4ahpWlvXZZEhzimg/mJoKJLdrjE3Fg817Qf2
+iXTPMWAtmCkYgHn9Y99VJSdJzrb0/E1JnxMPva52ZMS8ilS/hSZnXRAlq2OPFMj
64SU9XDu/eWqJMULELNkBcTtPgTCAkjrDU6Qt2AbwNUwrgufJC8WJEhWdQIDAQAB
AoGBAKc2Y8E0C44dtdFvEgmge+MH8RuFA6XM4O2Es0Gh8ZMxqb6BKObdTbmzTi3o
loA3GDveB9puoTEXVm3nNX9JVfYr952+54vEfFGDnUfnsjpzQih5NkODKKxS0NXW
DsCgemo9QmOYlGUm/mcvdv2gnjrl/E1TgRbC5cJ8bX5O3sAhAkEA04mFvAx+B+mx
uVH8RxBkv0iB7lEuR87jrZuL7n7LnyHdnstK85xs9mmx95nMhmh6jWD1VIRVbx3X
XsRqoRVQjQJBAM8HER8bae89Vw6ptBezB3ihs4NZ/dF5jM3ksLN10hm9n00hSSmo
FaT7PcSizFkoUs2kGcytZuzTkSYVaeM154kCQQC6AXQJ7cYoeRJgjTnS1xRvqnct
sk6Kr949usepl+6+Z83zInkuiv65Eil+OcvA6D/S703p2k8xXMETQI0uRYrFAkBV
sIEftQMV6Pe9s/Q80vdGsPdSaM8sAvmKxxt0TFIYIWpsTFiyC0ZaMTuRxih6xrvv
LfsXwrYVVESB1N8tEkSxAkAbPNx57ceCLMvkknDWuNdygtBgtAskSccktWnbXk9C
CnpHn/toehb9Grk6pbR1PqLRgD2l8ctiYBq/+2t+L/lp
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrEgoLjG34pNLj4ahpWlvXZZEh
zimg/mJoKJLdrjE3Fg817Qf2+iXTPMWAtmCkYgHn9Y99VJSdJzrb0/E1JnxMPva5
2ZMS8ilS/hSZnXRAlq2OPFMj64SU9XDu/eWqJMULELNkBcTtPgTCAkjrDU6Qt2Ab
wNUwrgufJC8WJEhWdQIDAQAB
-----END PUBLIC KEY-----
To extract the public key, I stripped of the "-----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY-----" footer and white spaces to extract the public key to be sent to the server.
The problem is that when I strip the header and footer the sent the public key to the server, though the server successfully encrypts the data (using the public key) and sent encrypted data to the client, the decryption using private key (in PEM format) using OpenSSL fails.
I think the decryption has failed as when i modify the public key's content (by stripping of the header/fooders), the public and private key seize to be key pairs.
Can somebody help me with the solution such that I am able to use the private key to decrypt the received encrypted data.
Alternatively, can somebody help me in generation of public key/private key pair of abovementioned lengths using objective-c api's (pair as generated by OpenSSL) which will fix the issue I am facing?
Thanks & Regards.
The data encrypted by server using Public Key is an AES key. The size of the AES key after encryption using public key is 176 characters. Here is the code snippet which does it.
public static String encryptAESKey(byte[] aesKeyBytes, String publicKeyStr) {
String cipherStr = null;
try {
PublicKey pkey = getPublicKey(publicKeyStr);
final Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, pkey);
byte[] cipherBytes = cipher.doFinal(aesKeyBytes);
cipherStr = Base64.encodeBase64String(cipherBytes);
} catch (Exception e) {
e.printStackTrace();
}
return cipherStr;
}
private static PublicKey getPublicKey(String publicKey) throws InvalidKeySpecException, NoSuchAlgorithmException {
KeyFactory rsaKeyFac = KeyFactory.getInstance(RSA_ALGORITHM);
byte[] keyBytes = Base64.decodeBase64(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
RSAPublicKey rsaPubKey = (RSAPublicKey)rsaKeyFac.generatePublic(keySpec);
return rsaPubKey;
}

Related

Test which public keys were generated by a specific private key

Let's say I've used near keys foo.near to identify all the keys for a given account and I want to understand which of those public keys were generated by a particular private key. How would I do that most easily?
If you know the private key in question, this is a pretty trivial problem. You can use near-api-js to generate the KeyPair and get the public key. A quick code-snippet:
const { KeyPair } = require("near-api-js");
let keyPair = KeyPair.fromString(secretKey);
let publicKey = keyPair.getPublicKey().toString();
At this point, you have the Public Key and can compare with the keys returned from the CLI.

Ruby OpenSSL: How to fetch just token from public key

I am using OpenSSL::PKey::RSA.new(2048) to create public and private key..
privae_key = OpenSSL::PKey::RSA.new(2048)
public_key = private_key.public_key
Below is my public key
puts public_key.class
=> OpenSSL::PKey::RSA
puts public_key
=> -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAywjG1X8f87fAg7yW/u7V
wPxOoR/yVAs87ew0rpcWuSKClVF8sXSuGI9LPXDVFIrBegw4zVI6PBAdKWqw6Ogv
y3KwHGD3z6AtwzQzUHvkT74zkSKcpGMSqITwAzUOjX0JbJSH0n3YBhekg3og6A+G
TxZDivoa3VPsN+hoW7bvai4dUDbCpeDbahLgPggVe9mc/jNc2+Ozf79lROgC4q9P
cpyQi7e4qHsZfptNU9lE3a69fI23O2MhGNtu1+ke2D+GL8whXC66pXctnhPD+3+5
OC7x/dFaN7OIv44rYc7udc7lwEtHhfKIgVP8mIYai+cJMfq4G+Ip/nn5xwihCkUt
4QIDAQAB
-----END PUBLIC KEY-----
from the above public key i want to extract only key portion i.e i want to extract only below data from above public key in the form of string. i want to ignore header -----BEGIN PUBLIC KEY----- and footer -----END PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAywjG1X8f87fAg7yW/u7V
wPxOoR/yVAs87ew0rpcWuSKClVF8sXSuGI9LPXDVFIrBegw4zVI6PBAdKWqw6Ogv
y3KwHGD3z6AtwzQzUHvkT74zkSKcpGMSqITwAzUOjX0JbJSH0n3YBhekg3og6A+G
TxZDivoa3VPsN+hoW7bvai4dUDbCpeDbahLgPggVe9mc/jNc2+Ozf79lROgC4q9P
cpyQi7e4qHsZfptNU9lE3a69fI23O2MhGNtu1+ke2D+GL8whXC66pXctnhPD+3+5
OC7x/dFaN7OIv44rYc7udc7lwEtHhfKIgVP8mIYai+cJMfq4G+Ip/nn5xwihCkUt
4QIDAQAB
Is there a way to do this? i tried all methods supported on object public_key but nothing is working.. can someone help?
You can export the key to a string with to_pem(). This string contains the PEM encoded key, i.e. header, Base64 encoded body with line breaks, and footer. Header and footer can then be removed with sub():
require "openssl"
private_key = OpenSSL::PKey::RSA.new(2048)
public_key = private_key.public_key
pem = public_key.to_pem
pem.sub! "-----BEGIN PUBLIC KEY-----\n", ''
pem.sub! "\n-----END PUBLIC KEY-----", ''
#pem.gsub! "\n", '' # remove all remaining linebreaks
puts pem.class
puts pem
Possible output:
String
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmTbDL1Tqz83QPvQ8cbFp
GWIXk5ukTX0E18PHY//3GaSF0xMLGBx6KeGprCpJbhUGcxFQi2/Hdr9BAjaqDwF6
89Bo2CHW5wU4HL0IgcahrfcpZGlggMEbEpKH6boppt6XZuppAAkxBprHVkJ951Ve
TK3tqpO8i4x9t5JuJteSbb67ts2IOXbi/YGUOassby3y4Q286YCYZh5VXHMLdKKJ
qHgICUn1dlAMI7ie0n4s1ESnkqo9GXgWAy3WrJTUsX/FK97+8h+b1aa0qnHbwWpp
dxNxExdUUEgBGHKz4piVwTJ9gfQu4hSQpcVstUgjDx6qTo9HSu4iQi1FPKxZG0lN
xwIDAQAB
Alternatively, the key can be exported with to_der() and the result Base64 encoded.

how does private key contain modulus?

In RSA, we got public/private key.
let's say I have a private key. How can I get public key ? to get public key, i would need to know private key pairs(q and N), but private key seems one long thing only.

Generate a private key from public key

I am try to generate a private key from rsa public key. My attempts to use the formulas from this solution were unfortunately unsuccessful, because the codes never matched. My target is to calculate an RSA 1024 bit private key from this public key.
Edit: I have now added the public key, because the previous one was an entire certificate.
-----BEGIN PUBLIC KEY-----
MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQD1cJDUjO87H/eM+VxtUxB5gHIH
W2Q1wniS6kxXPzaEnPPzaQflsEHOV2mrCnXd2qsa9Soqpl5U0x3OlzjXnaYRfck7
0BsppFRnEFfhPFmXOKxv4pCx30O9O+yAD69Z8h+OGJtL2DQfPpcTuOxxwYS77BfG
rSymPSF0gLFV1mn4AwIBAw==
-----END PUBLIC KEY-----

Unable to Generate RSA Public key in ruby

I am unable to create a object of OpenSSL::PKey::RSA class for a public key in string format. The following is my code:
public_key = '-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAttI6ImgD74PhHWVqnrqSOmStboplyL02DB3/nc2iyDdYLzXoBIQN+NPMBPlsZlEKuKjsg5Ycfp6VjcmncM3CH9MGIr+Lmbj1HZmO/jJGJ84RPhzYOiZuElzs3seIcOtOa3BpFeqRsXJlrf1IVBKVU3erka5ACLVyrsjmp/VXMx5QjPD0qXARMGb6rDewTkyg3pGz07Y7rZgXkTl54ase+XaPegOankxdEQhVjPdrk7eSlIQS5Ni7FAcSyTOtYoPgiP7W0PolOMHvpFg96CHjc8V8xDsFdh0wbHd49WcKxiJMIfL65VUIW5aob9fw05a5FczyASa0iNtRiICy/QnCqQIDAQAB-----END PUBLIC KEY-----'
OpenSSL::PKey::RSA.new public_key
I am getting the following error:
OpenSSL::PKey::RSAError: Neither PUB key nor PRIV key: nested asn1 error
I am using ruby version ruby 2.3.7. Any body can tell me what is wrong with string or function.?
I have try adding \n solution suggested here
public_key = "-----BEGIN PUBLIC KEY-----MIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAttI6ImgD74PhHWVqnrqSOmStboplyL02DB3/nc2iyDdYLzXoBIQN+NPMBPlsZlEKuKjsg5Ycfp6VjcmncM3CH9MGIr+Lmbj1HZmO/jJGJ84RPhzYOiZuElzs3seIcOtOa3BpFeqRsXJlrf1IVBKVU3erka5ACLVyrsjmp/VXMx5QjPD0qXARMGb6rDewTkyg3pGz07Y7rZgXkTl54ase+XaPegOankxdEQhVjPdrk7eSlIQS5Ni7FAcSyTOtYoPgiP7W0PolOMHvpFg96CHjc8V8xDsFdh0wbHd49WcKxiJMIfL65VUIW5aob9fw05a5FczyASa0iNtRiICy/QnCqQIDA\nQAB-----END PUBLIC KEY-----"
but I am getting same error
OpenSSL::PKey::RSAError: Neither PUB key nor PRIV key: nested asn1 error
Add \n on different places
public_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAttI6ImgD74PhHWVqnrqSOmStboplyL02DB3/nc2iyDdYLzXoBIQN+NPMBPlsZlEKuKjsg5Ycfp6VjcmncM3CH9MGIr+Lmbj1HZmO/jJGJ84RPhzYOiZuElzs3seIcOtOa3BpFeqRsXJlrf1IVBKVU3erka5ACLVyrsjmp/VXMx5QjPD0qXARMGb6rDewTkyg3pGz07Y7rZgXkTl54ase+XaPegOankxdEQhVjPdrk7eSlIQS5Ni7FAcSyTOtYoPgiP7W0PolOMHvpFg96CHjc8V8xDsFdh0wbHd49WcKxiJMIfL65VUIW5aob9fw05a5FczyASa0iNtRiICy/QnCqQIDAQAB\n-----END PUBLIC KEY-----"
public_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAttI6ImgD74PhHWVqnrqSOmStboplyL02DB3/nc2iyDdYLzXoBIQN+NPMBPlsZlEKuKjsg5Ycfp6VjcmncM3CH9MGIr+Lmbj1HZmO/jJGJ84RPhzYOiZuElzs3seIcOtOa3BpFeqRsXJlrf1IVBKVU3erka5ACLVyrsjmp/VXMx5QjPD0qXARMGb6rDewTkyg3pGz07Y7rZgXkTl54ase+XaPegOankxdEQhVjPdrk7eSlIQS5Ni7FAcSyTOtYoPgiP7W0PolOMHvpFg96CHjc8V8xDsFdh0wbHd49WcKxiJMIfL65VUIW5aob9fw05a5FczyASa0iNtRiICy/QnCqQIDA\nQAB-----END PUBLIC KEY-----"
Is generating same error message.
Thanks
The OpenSSL::PKey::RSA.new class was unable to created the new object because their is some issue with the public string key.
I find out the key is invalid in the following way:
In ruby console/irb
puts public_key.to_s.gsub('\n', "\n")
Save the output in a file with name public_key.txt and run the following command on ubuntu terminal
openssl pkey -inform PEM -pubin -in public_key.txt -noout &> /dev/null
if [ $? != 0 ] ; then
echo "this was definitely not a public key in PEM format"
exit 1
fi
If key is invalid the above script will print
this was definitely not a public key in PEM format
And will print nothing if key is valid.
Thanks
This doesn't generate any errors for me (your original string yielded the same error you noted).
require 'openssl'
public_key = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAttI6ImgD74PhHWVqnrqSOmStboplyL02DB3/nc2iyDdYLzXoBIQN+NPMBPlsZlEKuKjsg5Ycfp6VjcmncM3CH9MGIr+Lmbj1HZmO/jJGJ84RPhzYOiZuElzs3seIcOtOa3BpFeqRsXJlrf1IVBKVU3erka5ACLVyrsjmp/VXMx5QjPD0qXARMGb6rDewTkyg3pGz07Y7rZgXkTl54ase+XaPegOankxdEQhVjPdrk7eSlIQS5Ni7FAcSyTOtYoPgiP7W0PolOMHvpFg96CHjc8V8xDsFdh0wbHd49WcKxiJMIfL65VUIW5aob9fw05a5FczyASa0iNtRiICy/QnCqQIDAQAB\n-----END PUBLIC KEY-----"8xDsFdh0wbHd49WcKxiJMIfL65VUIW5aob9fw05a5FczyASa0iNtRiICy/QnCqQIDAQAB\n-----END PUBLIC KEY-----"
OpenSSL::PKey::RSA.new public_key
That returns #<OpenSSL::PKey::RSA:0x00007fa78b9b6ee8> rather than an error. If I remove the \n I can reproduce the error you noted.
Ruby 2.5.3, macOS, using openssl installed via homebrew.

Resources