使用现有DER / PEM密钥在Javascript中进行RSA加密

时间:2015-03-06 13:45:37

标签: javascript android ios encryption rsa

我的第一篇文章。

我正在尝试使用我用来成功加密数据的现有公钥 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.
  3. 当我粘贴我的PEM格式化密钥并加密一个短字符串时,我在Base64中得到看似合法的密文,但它没有解密(我得到一个空白字符串)。解密代码与Android / iPhone的Base64密文完美配合。

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

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

    我将现有的DER公钥转换为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
    

    我认为问题是密钥和文件的格式/类型。或者使用上面的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));
    

    谢谢你们!

1 个答案:

答案 0 :(得分:2)

您理解公钥的组成以及您正在使用的JavaScript库似乎存在轻微的不匹配。


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

公钥通常也编码为(PKCS#1)DER编码数据,但它只包含模数和公共指数(对于RSA)。

PEM只是一个带有DER内部的ASCII装甲。


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


最大的问题当然是如何确保JavaScript能够信任公钥。这可以在iOS和Android上通过在应用程序中包含可信(更高级别的CA)证书来解决,并使用该证书验证证书或公钥。对于使用与公钥相同的不可信通道分发代码的JavaScript,这通常是不可能的。因此,从技术上解决这个问题可能无法为您带来真正的安全保障。