nodejs webcrypto imporKey rsa error "error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long"

nodejs webcrypto imporKey rsa error "error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long"

好的,所以我正在构建一个应用程序并使用 RSA 来解密从浏览器的 webcrypto 加密的数据,甚至在网络端启动之前我就收到了一个奇怪的错误。我尝试搜索错误但我没有找到有什么帮助..我正在使用 nodejs(v16.10.0)

//failing nodejs example
var crypto=require('crypto')
var privateKeyStr=`-----BEGIN PRIVATE KEY-----
REAL_PRIVATE_KEY_HERE
-----END PRIVATE KEY-----`
function str2ab(str) {
    const buf = new ArrayBuffer(str.length);
    const bufView = new Uint8Array(buf);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}
function ab2str(buf,getOwnPropertyNames) {
    var buff=new Uint8Array(buf)
    return Object.getOwnPropertyNames(buff)
    .map(i=>String.fromCharCode(buff[i])).join('')
}

atob=(text)=>Buffer.from(text,'base64').toString()
btoa=(text)=>Buffer.from(text).toString('base64')

let pemHead1="-----BEGIN PRIVATE KEY-----", pemFoot1="-----END PRIVATE KEY-----"

var prvKeyText=atob(privateKeyStr.substring(pemHead1.length,privateKeyStr.length-pemFoot1.length));

(async()=>{
  prvKey=await crypto.webcrypto.subtle.importKey('pkcs8',str2ab(prvKeyText),{name:"RSA-OAEP",hash:"SHA-256"},true,['decrypt'])
  
  rsa_decrypt=async(secret_text)=>ab2str( await crypto.webcrypto.subtle.decrypt('RSA-OAEP',prvKey,str2ab(atob(secret_text))) )
})()

这种用于 webcrypto 的代码 确实 在浏览器中工作,但在 nodejs 中失败(v16.10.0)

//working web example(yes this is not a private key I'm using)
var privateKeyStr=`-----BEGIN PRIVATE KEY-----
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
PotgmE7pY/5T04uDwhpWK5TOFnCnXg==
-----END PRIVATE KEY-----`
function str2ab(str) {
    const buf = new ArrayBuffer(str.length);
    const bufView = new Uint8Array(buf);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}
function ab2str(buf,getOwnPropertyNames) {
    var buff=new Uint8Array(buf)
    return Object.getOwnPropertyNames(buff)
    .map(i=>String.fromCharCode(buff[i])).join('')
}

let pemHead1="-----BEGIN PRIVATE KEY-----", pemFoot1="-----END PRIVATE KEY-----"

var prvKeyText=atob(privateKeyStr.substring(pemHead1.length,privateKeyStr.length-pemFoot1.length));

(async()=>{
  prvKey=await crypto.subtle.importKey('pkcs8',str2ab(prvKeyText),{name:"RSA-OAEP",hash:"SHA-256"},true,['decrypt'])
  
  console.log("it works normally")
  console.log(prvKey) //so clearly I don't understand webcrypto in nodejs v16.10.0
  
  rsa_decrypt=async(secret_text)=>ab2str( await crypto.subtle.decrypt('RSA-OAEP',prvKey,str2ab(atob(secret_text))) )
})()
//if an error happened you would see it.. but in your browser it works normal

这是因为您为 NodeJS 定义的 atob()btoa() 方法。

Buffer.from() and Buffer#toString() 如果未指定其他编码,则默认应用 UTF-8。但是,UTF-8 通常会破坏任意二进制数据。使用 binary 而不是 UTF-8 作为编码:

atob = (text) => Buffer.from(text, 'base64').toString('binary')
btoa = (text) => Buffer.from(text, 'binary').toString('base64')

通过此修复,导入工作正常并且不再显示错误消息。