javascript - 从 Java 导出随机 RSA 公钥并使用 Web Crypto 将其导入 JavaScript

标签 javascript java websocket rsa webcrypto-api

我能够将字节数组从 Java 服务器传输到 JavaScript 服务器(作为 Int32Array 接收)。有了这个,我希望能够传输在 Java 中生成的 PublicKey 并在 JavaScript 中将其作为 CryptoKey 接收。

RSA 公钥是用 Java 生成的,如下所示:

SecureRandom sr = new SecureRandom();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048, sr);
KeyPair kp = generator.generateKeyPair();
PublicKey pKey = kp.getPublic();

我尝试的是使用 Key#getEncoded() 将公钥作为字节数组获取,使用 aformenetioned 方法将其传输到 JavaScript,然后像这样导入:

const subtle = window.crypto.subtle;
await subtle.importKey("spki", array, { name: "RSA-OAEP", hash: "SHA-256" }, false, [ "encrypt" ])

其中“array”是从 Java 服务器接收到的 Int32Array。然而,这不起作用,我总是得到一个非描述性的 DOMException ,指出“提供给操作的数据不符合要求”。我已经完成了明显的故障排除,检查发送前后的数组是否相同,将 TypedArray 转换为 ArrayBuffer,以 Base64 进行编码和解码作为字节完整性检查,并尝试不同的算法但无济于事。

一些资源:

这是一个示例 key#getEncoded() 字节数组,在发送之前由 Java 报告(发送后是具有相同内容的 Int32Array([...]))

[48, -126, 1, 32, 48, 11, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 10, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -44, -97, 125, 40, -104, -77, -56, 30, 64, -51, -44, 35, -91, 83, 43, -92, 1, 104, -7, -71, 61, -111, 74, -17, -43, 96, 47, 5, 71, 57, -23, -80, 12, 23, -89, -5, 18, 56, 32, -125, -48, 115, -126, 45, 71, 73, -53, -68, -104, -95, 18, -76, 21, 22, 122, 26, -89, -128, -118, 99, -65, 89, -81, -120, 72, -85, 20, 44, -119, -38, 4, -1, -69, -105, -70, -52, 126, 58, 86, -9, 4, -55, 104, -81, 21, -91, -128, -101, -82, -15, -1, -4, -13, -116, 48, -91, -60, 81, 111, 53, 126, 91, -46, 16, -5, -99, 73, -40, -99, -24, -46, -75, -99, 48, -67, 92, -92, -78, -115, 76, -35, -51, 75, -56, 70, 56, -10, 13, -108, 56, 79, 34, -22, -123, -91, -12, 9, -21, -32, 22, -88, -79, -13, -35, 61, 24, -115, -93, 40, 46, -88, 5, -105, -69, 82, -57, 10, -15, -91, 21, 53, -60, -31, -102, -63, -35, 71, -72, 50, 2, 37, 93, -70, -87, -110, -69, -10, 88, 51, 118, 30, 45, -11, 74, -92, -109, -10, 102, 79, -128, 14, 61, 94, -100, 69, 97, 56, 38, -14, 29, -85, -78, 2, 31, -127, -107, 86, -16, -114, -7, -83, 31, 77, -120, 77, 73, 114, 38, -124, 31, 116, -83, 39, -36, 85, 92, 86, 52, 22, -90, -47, 101, 16, 94, -16, -95, -33, 68, 112, 88, 94, -47, 121, -83, 3, -80, 111, 21, -42, 65, -101, 72, -126, 4, -83, -11, 2, 3, 1, 0, 1]

相同的数据以十六进制表示

30 82 01 20 30 0B 06 09 2A 86 48 86 F7 0D 01 01 0A 03 82 01 0F 00 30 82 01 0A 02 82 01 01 00 D4 9F 7D 28 98 B3 C8 1E 40 CD D4 23 A5 53 2B A4 01 68 F9 B9 3D 91 4A EF D5 60 2F 05 47 39 E9 B0 0C 17 A7 FB 12 38 20 83 D0 73 82 2D 47 49 CB BC 98 A1 12 B4 15 16 7A 1A A7 80 8A 63 BF 59 AF 88 48 AB 14 2C 89 DA 04 FF BB 97 BA CC 7E 3A 56 F7 04 C9 68 AF 15 A5 80 9B AE F1 FF FC F3 8C 30 A5 C4 51 6F 35 7E 5B D2 10 FB 9D 49 D8 9D E8 D2 B5 9D 30 BD 5C A4 B2 8D 4C DD CD 4B C8 46 38 F6 0D 94 38 4F 22 EA 85 A5 F4 09 EB E0 16 A8 B1 F3 DD 3D 18 8D A3 28 2E A8 05 97 BB 52 C7 0A F1 A5 15 35 C4 E1 9A C1 DD 47 B8 32 02 25 5D BA A9 92 BB F6 58 33 76 1E 2D F5 4A A4 93 F6 66 4F 80 0E 3D 5E 9C 45 61 38 26 F2 1D AB B2 02 1F 81 95 56 F0 8E F9 AD 1F 4D 88 4D 49 72 26 84 1F 74 AD 27 DC 55 5C 56 34 16 A6 D1 65 10 5E F0 A1 DF 44 70 58 5E D1 79 AD 03 B0 6F 15 D6 41 9B 48 82 04 AD F5 02 03 01 00 01

感谢所有花时间提供帮助或回复的人!

最佳答案

首先是一个可行的解决方案:使用 Key#getEncoded() 生成的 DER 编码的 X.509/SPKI key 经过 Base64 编码,然后导入到 JavaScript 端,如下所示:

(async () => {
    const subtle = window.crypto.subtle;
    var keyAB = b642ab("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuuKRgspvg47d4I3pAzCIWKSim2Rs1QeTVE1Hs+P099PkiuMt5dq5GIaIT1DZTYwJrwtUpxnMcr1TNdWGGfovDLJuIRXUFeST1xOD9+rA4FhVZPO/x6ts2TYKiueEq/qPlXREXw8aVq+msw0nYhHFIAAyrtmj7UR6gD3xxl1ghviIycKqUf7rL98b1d6YkYoNW62aIP/u3cJ5v3Fhnth02Cb02M/fX5gvFKJ3Nj2ARbLygZWbO3U09Vs/hnElxE2k1sKxYRqImJdQM04oQOXVVpafZP7eF9/T+YYDxMLcEKAwH9z0fTt9HaL4gyiDWUT02r6qWF7vI85I1jrPLn71mQIDAQAB")

    var key = await subtle.importKey("spki", new Uint8Array(keyAB), { name: "RSA-OAEP", hash: "SHA-256" }, false, [ "encrypt" ])   
    console.log(key)
})();

function b642ab(base64string){
    return Uint8Array.from(atob(base64string), c => c.charCodeAt(0)).buffer;
}

该问题是由您使用的 Int32Array 类型引起的。类型化数组是底层 ArrayBuffer 的类似数组的 View 。在 Int32Array 中,每个元素对应 4 个字节。
因为您的 Int32Array 包含与 Key#getEncoded相同 的值(),底层 ArrayBuffer 包含的值是原来的 4 倍,因此不再对应于原始键。

关于javascript - 从 Java 导出随机 RSA 公钥并使用 Web Crypto 将其导入 JavaScript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70587311/

相关文章:

javascript - 如何在node.js中向GET请求添加参数?

node.js - socket.io 重新连接示例

javascript - 使用 JXA 单击 UI 元素不起作用

javascript - 是否有糖与可选链接/无效合并来防止 Array.map 出现类型错误?

java - 在运行时使用反射实例化未知类对象的正确方法是什么?

java - 在 Android 中检索 TextView 时不显示 Firebase 实时数据库

php - 优化 IE 中的 float javascript

javascript - 这是跨站脚本: DOM in dhtmlHistory. js吗

java - 找不到类 org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer

websocket - 是否有任何使用纯 websocket 作为服务器后端的实时推送类型服务?