使用现有 DER / PEM 密钥的 Javascript 中的 RSA 加密

RSA Encryption in Javascript with existing DER / PEM keys

我的第一个 post.

我正在尝试使用 现有 public 密钥对 JavaScript(在用户浏览器中)中的数据进行非对称加密 我曾在我们的原生 iOS 和 Android 应用程序中成功加密数据。

我是这样创建密钥的:

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

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

当我使用这些精彩的 JavaScipt 示例时:

  1. Example.
  2. Another example.

当我粘贴我的 PEM 格式的密钥并加密一个短字符串时,我得到了看似合法的 Base64 密文,但它没有解密(我得到一个空字符串)。解密代码与来自 Android / iPhone.

的 Base64 密文完美配合

这些教程中的 PEM public 密钥是通过以下方式生成的:

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

我以这种方式将现有的 DER public 密钥转换为 PEM:

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

我认为问题出在密钥和文件的 format/type 上。或者误解了为什么涉及证书/我使用上面的 openssl 命令实际创建的内容。 (什么是 PKCS?)

我的问题:如何使用现有密钥在 Javascript 中加密,或将这些文件转换为 JavaScript 库可用的格式?

如果有助于解释我所做的事情,这里是 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));

谢谢大家!

您对 public 密钥的组成和您正在使用的 JavaScript 库的理解似乎略有不匹配。


X5.09 证书是一个 DER 结构,包含一个public密钥。它还包含持有人、发行人、密钥的许多其他数据,当然还有发行人的签名。

public 密钥通常也被编码为 (PKCS#1) DER 编码数据,但它仅由模数和 public 指数(对于 RSA)组成。

PEM 只是一个 ASCII 装甲,里面有 DER。


现在您的 Android 软件似乎使用证书进行加密。没关系,底层 Cipher 实现只是检索 public 密钥并用它加密。但是,您的 JavaScript 代码 仅采用 public 密钥 ,而不是证书。因此,您需要某种库来从证书中检索 public 密钥。


当然,最大的问题是如何确保 JavaScript 可以 信任 public 密钥。这可以在 iOS 和 Android 上解决,方法是在应用程序中包含受信任的(更高级别的 CA)证书并验证证书或 public 密钥。对于 JavaScript 这通常是不可能的,因为代码使用与 public 密钥相同的不受信任的渠道进行分发。所以从技术上解决这个问题可能不会给你带来真正的安全。