使用证书RSA Javascript验证签名

5
我正在尝试使用证书验证签名。我们需要从CA下载所需的证书,验证证书,然后验证签名。我不知道该怎么做,希望有人能够帮忙解决。以下是我目前了解到的内容。
为了签署消息,我使用了以下代码:
function sign(sk, m, certname) {
var key = new RSAKey();
key.setPrivate(sk.n, sk.e, sk.d);
var h = CryptoJS.SHA256(JSON.stringify(m)).toString(CryptoJS.enc.Hex);
h = new BigInteger(h, 16);
var sig = key.doPrivate(h).toString(16);
var obj = { "type": "SIGNED", "msg": m, "certname": certname, "sig": sig };
return JSON.stringify(obj);
}

为了验证签名,我使用了以下代码:
function verify(pk, signed) {
var key = new RSAKey();
var s = JSON.stringify(signed.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(pk.n, pk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signed.msg)).toString(CryptoJS.enc.Hex);
return (v == h);
}

为了验证证书,我使用了以下代码:(编辑:这是新的证书验证函数)。
function verifyCertificate(signedCert, certname) {
var key = new RSAKey();
var s = JSON.stringify(signedCert.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(CApk.n, CApk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signedCert.msg)).toString(CryptoJS.enc.Hex);
return (v == h);
}

这就是全部内容了。能否有人帮忙一下,我不知道该怎么做。
编辑:好的,我想我已经解决了自己的问题(得到了回复的帮助)。这是返回所有正结果的代码:
function verifyWithCert(sig) {
// 1. Download the required certificate from the CA
// 2. Verify the certificate
// 3. Verify the message
var certKey = new RSAKey();
var loadedCert = loadCert(sig.certname);
var certS = JSON.stringify(loadedCert.sig).toString(CryptoJS.enc.Hex);
certS = new BigInteger(certS, 16);
certKey.setPublic(CApk.n, CApk.e);
var certV = certKey.doPublic(certS).toString(16);
var certH = CryptoJS.SHA256(JSON.stringify(loadedCert.msg)).toString(CryptoJS.enc.Hex);
var verifyResult;
if (certV == certH) {
    verifyResult = true;
}
var Sigkey = new RSAKey();
var s = JSON.stringify(sig.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
Sigkey.setPublic(loadedCert.msg.subject.pk.n, loadedCert.msg.subject.pk.e);
var v = Sigkey.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(sig.msg)).toString(CryptoJS.enc.Hex);
var verifySignature;
if (v == h) {
    verifySignature = true;
}
var result = { "certificateFound": loadedCert ,"certificateVerified": verifyResult ,"signatureVerified": verifySignature };
return result;
}

有什么样的课程教授JavaScript密码学?那是你不想让任何人做的最后一件事。http://www.matasano.com/articles/javascript-cryptography/ - ntoskrnl
@ntoskrnl 我知道,对吧?我讨厌这个。 - kathleenie.xx
4个回答

4

对于StackOverflow的其他成员,我也在这个类中,所以我提到的一些变量和其他引用可能会突然出现。

在verifyCertificate函数中:

function verifyCertificate(signedCert, certname) {
    var loadedCert = loadCert(certname);

    // signedCert is the same as loadedCert above, the button runs the
    // loadCert function and outputs the contents into the textarea,
    // so the following will always be true.

    var originalSig = JSON.stringify(signedCert.sig);
    var loadedSig = JSON.stringify(loadedCert.sig);
    log(loadedSig);
    return (originalSig == loadedSig);
}

我应该如何验证证书呢?我要将加载的CA证书与什么进行比较?我原以为是将证书中的公钥与用于签署消息的公钥进行比较,但是...我很困惑。
不过你已经在正确的方向上了,考虑一下verify()函数以及文件顶部包含的CApk变量中包含的细节。你能否对loadCert() JSON响应中的消息进行哈希处理,并将其与以下输出匹配:
function verify() {
    //[...]
    key.setPublic(pk.n, pk.e);
    //[...]
}

假设您更改了一些变量?

这类似于我至少使用的方法,所以我希望它是正确的。我认为如果您可以使用CApk中的详细信息对消息进行哈希处理,并将其与JSON响应中包含的消息的哈希进行比较,则可以验证证书。希望如此。


我已经调整了验证证书的功能,它可以工作了,但现在我正在尝试将其应用到验证RSA签名和证书上,但它就是无法工作。所以我又迷失方向了。我讨厌JavaScript。我几乎没有使用它的经验,这真是折磨人。 - kathleenie.xx
注意:刚刚编辑了原始问题以添加新的certverify函数。 - kathleenie.xx
好的,我想我已经解决了。它显示正在验证所有内容,没有错误等。所以我认为是正确的。除了...你知道他说他的核心任务解决方案在5到10行之间吗?这大约有20行代码,所以我不知道是否应该怀疑我的代码。我会将其添加到原始问题中。 - kathleenie.xx

2

“验证证书”方法中存在错误。 您需要使用在355a3_main中给出的CA的公钥测试证书的签名以进行验证。此处提供的代码仅验证您的证书,并将对其余部分产生误报。

我认为这应该可以解决问题。

var loadedCert = loadCert(certname);
var originalSig = JSON.stringify(signedCert.sig);
var loadedSig = JSON.stringify(loadedCert.sig);
log(loadedSig,originalSig);

var key = new RSAKey();
var s = JSON.stringify(signedCert.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(CApk.n, CApk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signedCert.msg)).toString(CryptoJS.enc.Hex);

if (originalSig == loadedSig && v==h)
return true;
else
return false;

0

话虽如此,那么对于任意长度的长消息呢?


是啊,我卡在那里了。我已经让短信工作了,但是长消息就不行了,哈哈。 - kathleenie.xx
如果我们对长消息的 s 取模 n,这样做可以吗? var m = asciiToHex(msg); var key = new RSAKey(); var s = JSON.stringify(m).toString(CryptoJS.enc.Hex); s = new BigInteger(s, 16); - Guest
我们本来可以……但是怎么做啊?你得编写所有的数学代码。我们曾经想过将消息分成单独的块,然后对这些块进行加密/解密,最后再将它们组合起来返回,但是……哇,这需要大量的工作,而且这个单元不是“编程单元”(或“数学单元”),他们一直这样告诉我们。所以现在我们正在尝试完全不同的东西,涉及到对称密码。但是它并没有奏效(加密还好,但是描述就不行了)。我们迷失了哈哈。 - kathleenie.xx

0
Except... you know how he says his solutions for the core tasks are between 5 and 10 lines? well this is about 20 lines of code, so i don't know if I should be suspicious of my code

我在RSA签名验证与证书函数中再次使用了verify和verifycertificate函数。这将使您的代码相当简短。我非常感激这篇文章,你们都是我的救命恩人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接