当前位置: 首页 > 知识库问答 >
问题:

无法将WebCrypto密钥对转换为Java RSA密钥

华项明
2023-03-14

我有作为字符串的公钥和私钥,它们是由Webcrypto API RSA-OAEP算法生成的。我想加密和解密一些纯文本,使用这些和获得异常时,试图转换字符串到字节数组

Java代码:

package mailsend;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;

public class RsaOaep {
  public static void main(String[] args) throws Exception {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

    //Encryption
    byte[] input = "{\"userid\":\"1242\",\"appid\":\"1234\",\"tenentid\":\"4567\",\"sessionid\":\"session1234567\"}".getBytes();
    Cipher cipher = Cipher.getInstance("RSA/None/OAEPWithSHA1AndMGF1Padding", "BC");
    SecureRandom ranhtml" target="_blank">dom = new SecureRandom();
    String publicKey="{\n" + 
            "  \"alg\": \"RSA-OAEP-256\",\n" + 
            "  \"e\": \"AQAB\",\n" + 
            "  \"ext\": true,\n" + 
            "  \"key_ops\": [\n" + 
            "    \"encrypt\"\n" + 
            "  ],\n" + 
            "  \"kty\": \"RSA\",\n" + 
            "  \"n\": \"uChD48P6OBCynflLVsuP51hExmS7JIJmSPe6g_RYeb-O8rbaJA6mJE7QsMBeCrBUeyjhFYOFkGV9tpu3xIMkuRmTiyqy_mP2DKo8x9RB0gGVRvDuFjyOb3qpTAEA1SGyo_jGwN3RmVAVzVOTAAHqgQpRHtUsFEpQImUJgOUGVAfyFYpyyJKypcRv-RIU2JxOg3w7-i53erZPMHq_eWzEEXOgAU49UPjlTV18bXklBKSy3sbhKDpvHvOh_rEufhtD1Jl5RAQz3o8GGWPmcSf_3h5xa5ppqcgx6cfHDY9KKgxgCScwtjzTqU_QJO_zRnf3kYFU4dIFkfpXOJDDJc6RwQ\"\n" + 
            "}";
    byte[] keyBytes = Base64.getDecoder().decode(publicKey);
    PublicKey publicKeyNew = KeyFactory.getInstance("RSA", "BC").generatePublic(new X509EncodedKeySpec(keyBytes));
    cipher.init(Cipher.ENCRYPT_MODE, publicKeyNew, random);
    byte[] cipherText = cipher.doFinal(input);
    System.out.println("cipher: " + new String(cipherText));

    //Decryption
    String privateKey="{\n" + 
            "  \"alg\": \"RSA-OAEP-256\",\n" + 
            "  \"d\": \"FZO8Lp_r_a0xLHLE6cjElePg_QjY54Ry1RpXi3Xx9uPjrRsREJf5zffBGnCTpDd4Uozd4I4uNFa75c01eSwvfZOaVrw8SDOwpNe-cuBzDNbcJXl9v_O88aFi3DGi5hYCbxVrPjZPRGIeh9YCu4W98vwhOJZcCY2SeZEyjZxoAyjOmsvvylpUVN2ZVJ22lDOaBJMerPdwyXFv9wsUserFleZByk-M8WLz5JiT3MIg6NuMiMryx3-lhcHCBXgHJMeuxrdnPc_acer3WNkgWf5Q4LkTu9TT_Uz4kULtPvdbccv3-JyE0x4ZjCfiAmT65vUM5WvmCE6MZseR3WONIxmh0Q\",\n" + 
            "  \"dp\": \"FdzMUisoeG6Kk4C7Ol7k3QqR6QKa18LsMVIQXruQ7Vxm4bJ0lo8WyHWhLy4n11JLs7OGFENyXu7NtXw0ezmolfKIJVlItxWofICm8wm3Rhljrxe9KJnp1V4L1ibCXLOXOLsqhUwesWOhjAkfTHWJf3-wslSxVtFbif3fjeaKHlk\",\n" + 
            "  \"dq\": \"YTfHIEIOYiJ9AW_r3R8ou69ApwyzFNqczSeVooMKvKTYrpdj4ms6MeW5uL8Pq9HKFr8AFA2FWtOvrHrxShw_1V9IuvNChmPEF11RIO7CSc6xeK98zFtgqzbpJ81SKlcKh4icpaSjX3SQa7qbasgk9MBxK5gmpc5XZZNICDKfZ-E\",\n" + 
            "  \"e\": \"AQAB\",\n" + 
            "  \"ext\": true,\n" + 
            "  \"key_ops\": [\n" + 
            "    \"decrypt\"\n" + 
            "  ],\n" + 
            "  \"kty\": \"RSA\",\n" + 
            "  \"n\": \"uChD48P6OBCynflLVsuP51hExmS7JIJmSPe6g_RYeb-O8rbaJA6mJE7QsMBeCrBUeyjhFYOFkGV9tpu3xIMkuRmTiyqy_mP2DKo8x9RB0gGVRvDuFjyOb3qpTAEA1SGyo_jGwN3RmVAVzVOTAAHqgQpRHtUsFEpQImUJgOUGVAfyFYpyyJKypcRv-RIU2JxOg3w7-i53erZPMHq_eWzEEXOgAU49UPjlTV18bXklBKSy3sbhKDpvHvOh_rEufhtD1Jl5RAQz3o8GGWPmcSf_3h5xa5ppqcgx6cfHDY9KKgxgCScwtjzTqU_QJO_zRnf3kYFU4dIFkfpXOJDDJc6RwQ\",\n" + 
            "  \"p\": \"_8_ViZjqi4qU0jdt4dbrv81-FYFjJ0A3CpHhOwDxvIHRBMTS188_SEe-CZFwF91myv3AF9ZA64gYscr6t765F3-R7ydygryQWOedE-meRZhUHw3E3y-w_Khvtv0k3DW_NBO1-i3MDi8HV-xoSED9_ZYP6B0N05sBeoLhr76MuVk\",\n" + 
            "  \"q\": \"uErwgmSi7_t90oqKEED4Da8csEZVBN6_7n9xbZEk366lPf5rPETPbr8DKG-rA4kXq3l10ZksC-oo0RKdMpnqoHiYjmFPex1uLXJOAR_sg8ENtYtH-U6tNBjpoLufnbtg39O4bT7jr0HXx3MQmNy4rumfO97XypqIdKkrAODtJqk\",\n" + 
            "  \"qi\": \"brnAuBOvNKKdkwsI836lPNxmKqAMc-Jbtn7YmOu3ofq6PtiT5blJSGUJizMd1YDRHTLlQzWt1eqFZr_AjidGZ0QvYSj1jZT1hdpkIGn1M6oDDwh73mDC_Wqg5qtyFp6YudzWpSt5TG7m94pyPFx79wm1WedW53RVNQVdx3yOcBI\"\n" + 
            "}";
    byte[] keyBytesNew = Base64.getDecoder().decode(privateKey);
    PrivateKey privateKeyNew = KeyFactory.getInstance("RSA", "BC").generatePrivate(new X509EncodedKeySpec(keyBytesNew));
    cipher.init(Cipher.DECRYPT_MODE, privateKeyNew);
    byte[] plainText = cipher.doFinal(cipherText);
    System.out.println("plain : " + new String(plainText));
  }
}

例外情况:

线程“main”Java.lang.IllegalArgumentException中出现异常:Java.util.base64$Decoder.Decode0(base64.:714)Java.util.base64$Decoder.Decode(base64.:526)Java.util.base64$Decoder.Decode(base64.:549)mailsend.rsaoaep.main(Rsaoaep.Java:30)处出现非法base64字符7b

共有1个答案

焦信鸥
2023-03-14

webcrypto导出的密钥是JWK(JSON Web密钥)格式。Java不直接支持这种格式,因此您必须首先处理RSA密钥对的组件

正确生成密钥后,就可以检查加密代码

1.Decode de JSON Web key:解析JSON字符串并提取公钥和私钥的组件

我建议使用像jackson这样的JSON库。请参阅此示例

public class JWK{
    String n;
    String e;
    //getters and setters
} 

ObjectMapper mapper = new ObjectMapper();
JWK jwk = mapper.readValue(publicKeyJson, JWK.class);

2.将关键组件转换为BigInteger:模数、公有指数、私有指数等编码为base64url字符串。将这些字符串解码为byte[]并使用它们构建BigInteger,这样它们就可以被Java密钥构建器加载

byte[] publicExponentBytes = Base64.getUrlDecoder().decode(jwkPublic.e);
byte[] privateExponentBytes = Base64.getUrlDecoder().decode(jwkPrivate.d);
byte[] modulusBytes = Base64.getUrlDecoder().decode(jwkPublic.n);

BigInteger publicExponent = new BigInteger(1, publicExponentBytes );
BigInteger privateExponent = new BigInteger(1, privateExponentBytes);
BigInteger modulus = new BigInteger(1, modulusBytes);

3.利用模(n)和公共指数(e)建立公钥

RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, publicExponent );
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey publicKey = factory.generatePublic(spec);

4.利用模数(n)和私有指数(d)构建私有密钥

RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, privateExponent);
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = factory.generatePrivate(privateKeySpec);
 类似资料:
  • 我在我的C#代码中使用了RSACryptoServiceProvider,它工作得很好,我可以导出RSA XML私有和公共密钥,但是出于某种原因,我需要将这个密钥转换为*。带格式的PEM(pkcs 8未加密) 我的私钥就像 我想把它转换成(PKCS8未加密)如下 我不是这个安保人员的专业人员,我不确定我们能不能把它换成非专业人员?有人能帮忙做代码示例吗?

  • 我在C#程序(我在下面提到)中使用了RSA非对称密钥加密算法,我必须通过java程序加密数据。我希望我的java程序生成与C#程序相同的加密密钥。 公钥: C#加密程序: Java加密方案: 我尝试了上述java程序,但结果如下: O+gw 7+X hY x A 9 ltD V 5 zE RsF 4 Dy Xg MTc/gx 82 wR tT 1 x fR 3 su Y 0 XB JLa dp 7

  • 问题内容: 我目前正在研究一种将键转换为字符串,反之亦然的方法。它适用于公钥转换,并将私钥转换为String。由于某些原因,同一代码不会将String转换回私钥,我只是无法弄清楚。 转换器代码为: 我正在使用的驱动程序代码是: 运行此命令时,我得到了不合适的密钥说明,有人可以为此指出正确的方向吗?控制台输出为: 我知道我不应该使用sun.misc。*库,我们正在研究Apache版本,但仍然想弄清楚

  • 下面是一个生成IV并将其转换为Base64字符串的示例... 但是,当我将IV的字符串表示形式传递到加密方法中,然后将其转换回字节数组时,下面的代码会失败,说明IV的大小不正确。 在字节数组和字符串表示之间有没有一种标准的转换加密密钥和IV的方法?

  • 问题内容: 警告 :最初的问题是关于PKCS#1编码的密钥,而该问题中的实际示例需要SubjectPublicKeyInfo(X.509)编码的密钥。 我目前正在从头开始在Java中实现RSA算法,尤其是在密钥生成方面。现在,我的代码可以使我得到三个BigIntegers n,e和d。 从网上可以看到,RSA密钥(很像PGP签名)通常是字符的混合,而不仅仅是很长的数字。显然,这是因为密钥已加密/翻

  • 问题内容: 我尝试从KeyStore获取密钥。我通过Keytool创建了一个密钥库: keytool -genkeypair -dname“ cn = Mark Jones,ou = JavaSoft,o = Sun,c = US” -alias business2 -keypass abcdtest -keystore C:\ workspace \ XMLSample \ keystore \