首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WebCrypto API,importKey()用于来自ATECC508A安全芯片错误的原始数据(64字节十六进制)的公钥:提供的数据不符合要求

WebCrypto API,importKey()用于来自ATECC508A安全芯片错误的原始数据(64字节十六进制)的公钥:提供的数据不符合要求
EN

Stack Overflow用户
提问于 2021-04-13 23:07:15
回答 2查看 1.3K关注 0票数 1

我使用一个名为ATECC508A的嵌入式芯片来生成ECDSASHA-256公钥/私钥,并对给定消息进行签名。

当我从芯片中读取公钥时,我获得的值为:

代码语言:javascript
复制
0x4B 0x34 0x89 0xAB 0x1B 0xE2 0x4C 0x84 0xA4 0x74 0xBE 0x85 0xD9 0xCF 0x99 0xF1 
0x12 0xF1 0x5E 0x13 0x67 0x17 0xB8 0x8C 0x3D 0xD8 0x54 0xC4 0x70 0xB0 0x11 0x05 
0xB1 0x9E 0x4E 0x3D 0xED 0x39 0xFA 0xED 0xF3 0xDB 0x94 0x7A 0xF6 0xCE 0x3A 0x0F 
0x6C 0xB1 0x86 0xB1 0x64 0x5D 0x8A 0xB8 0xA2 0x74 0x9F 0xF2 0x42 0x55 0x67 0x62

它不会像DER格式化的键那样以0x30开头,我也不确定字节字符串是否有任何特殊的格式。

要以上述原始格式导入公钥,我在javascript中使用WebCrypto API (微妙密码库)执行以下操作:

  1. First,转换为一个新的Uint8array:

代码语言:javascript
复制
    var pubkeytest = new Uint8Array([0x4B 0x34 0x89 0xAB 0x1B 0xE2 0x4C 0x84 0xA4 0x74 0xBE 0x85 0xD9 0xCF 0x99 0xF1 
    0x12 0xF1 0x5E 0x13 0x67 0x17 0xB8 0x8C 0x3D 0xD8 0x54 0xC4 0x70 0xB0 0x11 0x05 
    0xB1 0x9E 0x4E 0x3D 0xED 0x39 0xFA 0xED 0xF3 0xDB 0x94 0x7A 0xF6 0xCE 0x3A 0x0F 
    0x6C 0xB1 0x86 0xB1 0x64 0x5D 0x8A 0xB8 0xA2 0x74 0x9F 0xF2 0x42 0x55 0x67 0x62]);

  1. 试图导入上面的uint8数组:

代码语言:javascript
复制
    window.crypto.subtle.importKey(
            "raw",
            pubkeytest.buffer, {
                name: "ECDSA",
                namedCurve: "P-256",
                hash: {
                    name: 'SHA-256'
                }
            },
            false, //whether the key is extractable (i.e. can be used in exportKey)
            ["verify"] //"verify" for public key import, "sign" for private key imports
        )
        .then(function(pubkeytest) {
            //returns a publicKey (or privateKey if you are importing a private key)
            console.log(pubkeytest);
        })
        .catch(function(err) {
            console.error(err);
        });

控制台中的输出在console.error(err)行上触发一个错误:

代码语言:javascript
复制
DOMException: Data provided to an operation does not meet requirements

通过执行以下操作,我可以使用AES成功地导入随机公钥:

代码语言:javascript
复制
const rawKey = window.crypto.getRandomValues(new Uint8Array(16));
代码语言:javascript
复制
window.crypto.subtle.importKey(
      "raw",
      rawKey,
      "AES-GCM",
      true,
      ["encrypt", "decrypt"]
    );

我看到的唯一不同是数组中的字节数(16比64),以及算法类型AES-GCM,而不是ECDSA,它不声明P-256或SHA-256。

如何将上面的64字节原始十六进制公钥字符串导入到javascript中?我可以使用下面的示例对签名/消息执行密码验证:https://github.com/mdn/dom-examples/tree/master/web-crypto

提前感谢

EN

回答 2

Stack Overflow用户

发布于 2021-04-14 03:37:44

我相信我自己解决了这个问题,我想在这里发布解决方案,以防将来有人碰到这个问题。这个问题是一个简单的格式化问题,但解决起来并不那么简单,因为我找不到这些信息。

芯片提供的64字节公钥包含密钥内的完整X和Y坐标。它唯一缺少的是一个0x04前缀,它是ECDSA格式规则所必需的:

https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm

公钥:与私钥相对应但不需要保密的数字。公钥可以从私钥中计算,但反之亦然。公钥可用于确定签名是否真实(换句话说,使用适当的密钥生成),而不要求泄露私钥。在比特币中,公钥要么被压缩,要么被解压缩。压缩公钥为33个字节,由前缀0x02或0x03和一个名为x. 的256位整数组成,旧的未压缩密钥为65个字节,由常数前缀(0x04)组成,后面是两个名为x和y的256位整数(2 * 32字节)。压缩键的前缀允许从x值导出y值。

将与_04_4B3489AB1BE24C84A474BE85D9CF99F112F15E136717B88C3DD854C470B01105B19E4E3DED39FAEDF3DB947AF6CE3A0F6CB186B1645D8AB8A2749FF242556762 API一起工作的公钥的正确版本如下(对于下面的懒散十六进制格式表示歉意,但它与问题相同,除了粗体的新前缀外):

票数 1
EN

Stack Overflow用户

发布于 2022-08-22 09:37:35

我写这篇文章是为了防止有人有同样的问题。上面的解决方案(将0x04添加到原始键中)对我来说非常有效。在我看来,这个问题很奇怪。我用OpenSSL生成密钥,然后通过微妙的密码导入它们。这一定意味着OpenSSL错误地对密钥进行了编码,这听起来很奇怪,因为它很受欢迎。如果我有时间,我会进一步研究这个问题。

谢谢你的提问和回答,帮了我很大的忙。

编辑:我用Python导入了读取密钥文件,并将其解码为字节,以查看它是否以0x04开头。结果为阳性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67083465

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档