我有一个JavaScript客户端和一个Node服务器。JS.我试图在客户端签署一个简单的文本,并将签名与公钥一起发送到服务器,然后服务器可以验证公钥。
客户端的任何东西都可以!但我无法在服务器端验证签名。我认为您没有必要阅读客户机代码,但为了保证,我也会提供它。
客户代码:
let privateKey = 0;
let publicKey = 0;
let encoded = '';
let signatureAsBase64 = '';
let pemExported = ''
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
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;
}
let keygen = crypto.subtle.generateKey({
name: 'RSA-PSS',
modulusLength: 4096,
publicExponent: new Uint8Array([1,0,1]),
hash: 'SHA-256'
}, true, ['sign', 'verify']);
keygen.then((value)=>{
publicKey = value.publicKey;
privateKey = value.privateKey;
let exported = crypto.subtle.exportKey('spki', publicKey);
return exported
}).then((value)=>{
console.log('successful');
const exportedAsString = ab2str(value);
const exportedAsBase64 = btoa(exportedAsString);
pemExported = `-----BEGIN PUBLIC KEY-----\n${exportedAsBase64}\n-----END PUBLIC KEY-----`;
//signing:
encoded = new TextEncoder().encode('test');
let signing = crypto.subtle.sign({
name: "RSA-PSS",
saltLength: 32
},
privateKey,
encoded);
return signing;
}).then((signature)=>{
const signatureAsString = ab2str(signature);
signatureAsBase64 = btoa(signatureAsString);
//verifying just to be sure everything is OK:
return crypto.subtle.verify({
name: 'RSA-PSS',
saltLength: 32
},
publicKey,
signature,
encoded)
}).then((result)=>{
console.log(result);
//send information to server:
let toSend = new XMLHttpRequest();
toSend.onreadystatechange = ()=>{
console.log(this.status);
};
toSend.open("POST", "http://127.0.0.1:3000/authentication", true);
let data = {
signature: signatureAsBase64,
publicKey: pemExported
};
toSend.setRequestHeader('Content-Type', 'application/json');
toSend.send(JSON.stringify(data));
//to let you see the values, I'll print them to console in result:
console.log("signature is:\n", signatureAsBase64);
console.log("publicKey is:\n", pemExported);
}).catch((error)=>{
console.log("error",error.message);
})
服务器代码(为此我使用express):
const express = require('express');
const crypto = require('crypto');
const router = express.Router();
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;
}
router.post('/authentication', async (req, res)=>{
try{
const publicKey = crypto.createPublicKey({
key: req.body.publicKey,
format: 'pem',
type: 'spki'
});
console.log(publicKey.asymmetricKeyType, publicKey.asymmetricKeySize, publicKey.type);
let signature = Buffer.from(req.body.signature, 'base64').toString();
signature = str2ab(signature);
const result = crypto.verify('rsa-sha256', new TextEncoder().encode('test'),
publicKey, new Uint8Array(signature));
console.log(result);
}catch(error){
console.log('Error when autheticating user: ', error.message);
}
})
服务器控制台日志:
rsa undefined public
false
注:
pem
格式为什么要验证服务器中的公钥?
为什么不在客户端使用X库?
验证失败有两个原因:
>
必须显式地指定PSS填充,因为PKCS#1 v1.5填充是默认的。
签名转换会损坏数据:行:
let signature = Buffer.from(req.body.signature, 'base64').toString();
执行UTF8解码,s.here,这将不可逆地更改数据s.here。签名由通常与UTF8不兼容的二进制数据组成。只有使用合适的二进制到文本编码(如Base64、hex等),才能转换为字符串
但除此之外,实际上根本不需要进行转换,因为签名可以作为缓冲区直接传递。
以下NodeJS代码执行成功的验证(用于与客户端代码一起生成的签名和公钥):
const publicKey = crypto.createPublicKey(
{
key: req.body.publicKey,
format: 'pem',
type: 'spki'
});
const result = crypto.verify(
'rsa-sha256',
new TextEncoder().encode('test'),
{
key: publicKey,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING
},
Buffer.from(req.body.signature, 'base64'));
console.log(result); // true
我正在处理C RPC客户端。我需要使用OpenSSL对mime数据进行签名,并将公钥和签名发送到服务器。Java将尝试使用公钥验证签名。 问题是,JAVA无法验证OpenSSL生成的签名,但可以验证JAVA生成的签名。你知道如何修复我的c客户端代码吗? C客户端代码: JAVA代码:
我已经把它归结为我能做的最简单的测试用例。我需要获取Python中生成的RSASSA-PSS签名,并在Go中验证它们。创建RSA密钥对并用其签名的Python代码如下: 那里引用的pycrypto_keys库可以在这里找到,用于参考函数和的具体实现。 我的Go测试由两个简单的文件组成,这些文件只依赖于核心包。首先是验证功能,verify.go: 第二,一个测试用例。密钥对和签名是使用顶部的Pyth
我无法使用Crypt::RSA和Crypt::RSA::SS::PSS在Perl中验证PSS签名。 字符串“hello”是由设备签名的缓冲区。 “pubkey.pem”是设备的RSA公钥,用PEM_write_RSA_PUBKEY()从设备导出。 “hello.sig”包含由设备生成的二进制(原始)签名。(因为有填充,所以是128字节。) 我试图在Perl中使用crypt::rsa和crypt::
我已经使用Node rsa在Node中生成了一对私钥和公钥,并且可以在Node中使用这些密钥成功地进行签名和验证。 我尝试使用公钥的模和指数来验证中的签名(由节点中的私钥签名)。网 e、 g.我有一个string=“foo”,它有一个由Node生成的签名“abc123”。在里面NET我想使用公钥的模和指数来确认签名“abc123”对“foo”有效。 我想使用模数和指数而不是直接使用公钥的原因是因为
我们为RSA签名创建了调试公钥和私钥,并生成sha256哈希并保存在cp1.bin中。然后我们尝试验证签名,但总是失败。如果我们不使用pss填充,验证命令将通过。任何人都可以帮忙评论吗? 谢谢 C:\Project\pkc C:\Project\pkc
我在理解RSA签名和验证的概念方面有一个小问题。问题是我可以创建密钥对(公钥和私钥),这是完全好的。 签名和验证如下: 当我打印myPrivateKey和myPublicKey时,我看到公钥和私钥的模(n)和公钥指数(e)是相同的。 我已经将公钥和私钥转换为base64和hex,我得到了不同的值,这是非常好的。但是,我不能用base64或十六进制对消息进行签名。我只能用我从这里得到的东西来签名: