【发布时间】:2021-07-12 01:33:21
【问题描述】:
我正在使用安全嵌入式芯片 (ATECC508) 使用 secp256r1 曲线生成 ECDSA 消息/签名组合。
来自芯片的信息在Uint8Arrays中输出:message[32]、signature[64]、publickey[64]; 公钥是原始字节格式,在 64 字节数组中给出两个 X/Y 坐标,前面没有 0x04 填充。
只要我在前面用 0x04 填充 64 字节数组,公钥才会成功导入 WebCrypto。
但是,当我尝试验证消息和签名时,总是失败。
我创建了一个模拟器脚本来帮助调试。它使用 WebCrypto 来生成消息、签名和公钥,而不是使用加密芯片。模拟器生成一个 32 字节的 Uint8array 消息数组,并对消息进行签名,返回一个 64 字节的 Uint8array 用于其签名。 WebCrypto 生成的公钥也被验证在前面有 0x04 填充,在代表曲线 X/Y 坐标的 64 字节之前。这意味着我相信模拟器生成的信息应该与芯片提供的格式完全相同。
从 WebCrypto 生成的任何消息、签名和公钥都可以成功验证...但我无法验证来自芯片的信息...总是不成功。
我没有理由怀疑来自芯片的值是错误的,并且我已经从芯片生成了许多消息/签名......它们都不起作用。我还尝试了第二个芯片,结果相同。
芯片的输出示例(未验证):
uint8_t message[32] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
};
uint8_t signature[64] = {
0xD6,0x82,0x25,0xCC,0x68,0x6F,0x4F,0x84,0x91,0x48,0x63,0x6E,0x67,0x3C,0xD4,0xC0,0xF8,0xE5,0x9D,0x7B,0xAD,0x6B,0xB3,0xF1,0x1C,0xDB,0x90,0xB7,0x1A,0x5E,0x43,0xCF,0xD8,0xC3,0x8C,0x77,0x74,0xE2,0xA0,0x29,0xFF,0x43,0x22,0x7D,0xF9,0x41,0x56,0x12,0x8A,0x1B,0xEA,0x4D,0x57,0x8A,0x37,0x9C,0x6A,0x85,0x0A,0x56,0xBE,0xEC,0x1A,0x69
};
uint8_t publicKey[64] = {
0x39,0xC3,0xDD,0x74,0x13,0x17,0x29,0x44,0x6D,0xC1,0xB3,0xDA,0x67,0xD4,0x9F,0xC0,
0x46,0xFC,0xBF,0x07,0x2F,0xCC,0x5B,0x9F,0xA5,0x1C,0x05,0xB9,0x74,0x30,0x7F,0x96,
0x9C,0x40,0x3B,0x16,0x35,0xF0,0x44,0x9F,0x02,0xBD,0x42,0x27,0x51,0xE3,0x31,0x21,
0xA4,0x43,0x4F,0x15,0x2F,0x2B,0x2B,0x2A,0x3F,0x67,0x52,0x19,0xC5,0xD9,0x25,0xF6,
};
注意:上面的公钥在导入前用0x04填充,否则WebCrypto会报错。
WebCrypto 模拟器 javascript 控制台的输出示例(验证成功):
Message to import in hex: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
Message Uint8Array conversion: Uint8Array(32) [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, … ]
the signature in hex: 5d4575a19cad9a56b554bafbb1db212d8badd48b5d29f6556fa33f0e8650175f48157e70377c7aa5f97e55bc455b6520060dc86f32a00577a254a97e1b7b394c
the signature buffer:
Uint8Array(64) [ 93, 69, 117, 161, 156, 173, 154, 86, 181, 84, … ]
public key in hex:
04d18669eb64b54118fbcdacbf79d2f185383abadb1982382a51675650f4596d9f917a7b9b215f2424418b4e7c824500dc29ea507f08b4ef51ca35f58de75ca274
注意:上面是十六进制字符串,但我在调用 WebCrypto API 之前转换为 UintArray8。 PublicKey 在用于验证之前被转换为正确的 CryptoKey() 类型。
我用于验证的 javascript 代码:
let result = await window.crypto.subtle.verify({
name: "ECDSA",
hash: { name: "SHA-256" }
},
publicKey, sigbuffer, msgbuffer);
最后是导入:
return window.crypto.subtle.importKey(
'raw',
key, {
name: 'ECDSA',
namedCurve: 'P-256'
},
true, ["verify"]
);
我的意图是能够将芯片中的信息成功导入并验证到 WebCrypto API,但到目前为止我还没有成功。目前我完全陷入困境,非常感谢任何帮助......提前感谢
【问题讨论】:
标签: javascript arrays encryption webcrypto-api