RSA Encryption in Javascript with existing DER / PEM keys

╄→尐↘猪︶ㄣ 提交于 2021-02-06 13:58:35

问题


my first post.

I'm trying to asymmetrically encrypt data in JavaScript (in the user's browser), using the existing public key that I've used to successfully encrypt data in our native iOS and Android app.

I created the keys this way:

openssl req -x509 -out public_key.der -outform der -new -newkey rsa:1024 -keyout private_key.pem -days 3650

(Thanks to http://jslim.net/blog/2013/01/05/rsa-encryption-in-ios-and-decrypt-it-using-php/)

When I use these wonderful JavaScipt examples:

  1. Example.
  2. Another example.

When I paste in my PEM formatted key, and encrypt a short string, I get what appears to be legitimate ciphertext in Base64, but it doesn't decrypt (I get a blank string). The decryption code works perfectly with the Base64 ciphertext from Android / iPhone.

The PEM public keys in these tutorials are generated with:

openssl genrsa -out rsa.pem 1024 
openssl rsa -in rsa.pem -pubout

I converted my existing DER public key to PEM this way:

openssl x509 -in public_key.der -out nopass_public_with_cert.pem -inform DER -outform PEM
openssl x509 -pubkey -in nopass_public_with_cert.pem > public.pem

I believe the problem is the format/type of keys and files. Or misunderstanding of why certificates are involved / what I've actually created using the above openssl command. (What is PKCS?)

My question: How can I encrypt in Javascript using the existing keys, or convert these files into a format usable by JavaScript libraries?

If it helps to explain what I've done, here is the successful encryption in Android:

import java.security.(...);

import javax.crypto.Cipher;

String publickeybase64 = go_get_file_bytes_as_base64("public_key.der");
byte[]decode = Base64.decode(publickeybase64, Base64.DEFAULT);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
Certificate certificate = certificateFactory.generateCertificate(new ByteArrayInputStream(decode));
PublicKey publicKey = certificate.getPublicKey();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
String plaintext = "hello world";
String encryptedstring = new String(Base64.encode(cipher.doFinal(plaintext.getBytes()),Base64.NO_WRAP));

Thankyou all!


回答1:


There seems to be a slight mismatch in your understanding what a public key consists of and the JavaScript libs that you're using.


An X5.09 certificate is a DER structure that contains a public key. It also contains a lot of other data of the holder, issuer, key and of course the signature of the issuer.

A public key is usually also encoded as (PKCS#1) DER encoded data, but it only consists of the modulus and the public exponent (for RSA).

PEM is just an ASCII armor with DER inside.


Now your Android software seems to use the certificate for encryption. That's fine, the underlying Cipher implementation just retrieves the public key and encrypts with it. Your JavaScript code however just takes the public key, not a certificate. So you'll need some kind of library to retrieve the public key from the certificate.


The big issue is of course how to make sure that JavaScript can trust the public key. This can be solved on iOS and Android by including a trusted (higher level CA) certificate in the application and verify the certificate or public key with that. That's usually not possible for JavaScript where the code gets distributed using the same untrusted channel as the public key. So technically solving this issue may not bring you real security.



来源:https://stackoverflow.com/questions/28900116/rsa-encryption-in-javascript-with-existing-der-pem-keys

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!