无法验证带有dsa密钥的openssl签名的字符串 [英] unable to verify string signed by openssl with dsa key

查看:112
本文介绍了无法验证带有dsa密钥的openssl签名的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

适应从Linux命令行创建DSA签名的说明我创建了DSA签名的消息:

Adapting the directions at Creating a DSA Signature from the Linux command line I created a DSA signed message:

echo "foobar" > foo.txt
openssl dgst -dss1 -sign dsa_priv.pem foo.txt > sigfile.bin

这些说明实际上使用的是foo.sha1而不是foo.txt,其中foo.sha1是由sha1sum生成的,但是对哈希进行签名似乎有点多余,因为DSA本身应该进行哈希处理.

The directions actually used foo.sha1 instead of foo.txt, where foo.sha1 was generated by sha1sum but signing a hash seems a bit redundant since DSA is, itself, supposed to do hashing.

所以,无论如何,我做到了.这是我使用的私钥(我专门出于测试目的而生成了它):

So, anyway, I did that. Here's the private key I used (I generated it specifically for testing purposes):

-----BEGIN DSA PRIVATE KEY-----
MIIBvAIBAAKBgQDsGAHAM16bsPlwl7jaec4QMynYa0YLiLiOZC4mvH4UW/tRJxTz
aV7eH1EtnP9D9J78x/07wKYs8zJEWCXmuq0UluQfjA47+pb68b/ucQTNeZHboNN9
5oEi+8BCSK0y8G3uf3Y89qHvqa9Si6rP374MinEMrbVFm+UpsGflFcd83wIVALtJ
ANi+lYG7xMKQ/bE4+bS8gemNAoGBAORowvirD7AB9x2SpdiME41+O4jVR8rs6+GX
Ml3Hif6Yt1kem0CeraX9SNoyBNAzjD5TVMGIdGlgRr6GNreHeXMGWlvdDkvCACER
ZEEtMsKZicm+yl6kR8AGHTCA/PBltHfyrFQd4n9I//UDqI4RjqzvpCXGQcVEsSDY
CCBGBQJRAoGBALnHTAZlpoLJZuSBVtnMuRM3cSX43IkE9w9FveDV1jX5mmfK7yBV
pQFV8eVJfk91ERQ4Dn6ePLUv2dRIt4a0S0qHqadgzyoFyqkmmUi1kNLyixtRqh+m
2gXx0t63HEpZDbEPppdpnlppZquVQh7TyrKSXW9MTzUkQjFI9UY7kZeKAhQXiJgI
kBniZHdFBAZBTE14YJUBkw==
-----END DSA PRIVATE KEY-----

这是sigfile.bin的十六进制编码输出:

Here's the hex encoded output of sigfile.bin:

302c021456d7e7da10d1538a6cd45dcb2b0ce15c28bac03402147e973a4de1e92e8a87ed5218c797952a3f854df5

我现在正尝试使用BouncyCastle在Java中进行验证,但无法验证.这是我的Java代码:

I'm now trying to verify this in Java with BouncyCastle and am unable to do so. Here's my Java code:

import java.io.StringReader;
import org.bouncycastle.openssl.PEMReader;
import java.security.interfaces.DSAPublicKey;
import org.bouncycastle.crypto.params.DSAPublicKeyParameters;

import org.bouncycastle.crypto.signers.DSADigestSigner;
import org.bouncycastle.crypto.signers.DSASigner;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.params.DSAParameters;

public class DSA
{
    public static void main(String[] args)
    throws Exception
    {
        byte[] message = "foobar".getBytes();
        byte[] signature = hexStringToByteArray("302c021456d7e7da10d1538a6cd45dcb2b0ce15c28bac03402147e973a4de1e92e8a87ed5218c797952a3f854df5");

            String key = "-----BEGIN PUBLIC KEY-----\n" +
                "MIIBuDCCASwGByqGSM44BAEwggEfAoGBAOwYAcAzXpuw+XCXuNp5zhAzKdhrRguI\n" +
                "uI5kLia8fhRb+1EnFPNpXt4fUS2c/0P0nvzH/TvApizzMkRYJea6rRSW5B+MDjv6\n" +
                "lvrxv+5xBM15kdug033mgSL7wEJIrTLwbe5/djz2oe+pr1KLqs/fvgyKcQyttUWb\n" +
                "5SmwZ+UVx3zfAhUAu0kA2L6VgbvEwpD9sTj5tLyB6Y0CgYEA5GjC+KsPsAH3HZKl\n" +
                "2IwTjX47iNVHyuzr4ZcyXceJ/pi3WR6bQJ6tpf1I2jIE0DOMPlNUwYh0aWBGvoY2\n" +
                "t4d5cwZaW90OS8IAIRFkQS0ywpmJyb7KXqRHwAYdMID88GW0d/KsVB3if0j/9QOo\n" +
                "jhGOrO+kJcZBxUSxINgIIEYFAlEDgYUAAoGBALnHTAZlpoLJZuSBVtnMuRM3cSX4\n" +
                "3IkE9w9FveDV1jX5mmfK7yBVpQFV8eVJfk91ERQ4Dn6ePLUv2dRIt4a0S0qHqadg\n" +
                "zyoFyqkmmUi1kNLyixtRqh+m2gXx0t63HEpZDbEPppdpnlppZquVQh7TyrKSXW9M\n" +
                "TzUkQjFI9UY7kZeK\n" +
                "-----END PUBLIC KEY-----";
        PEMReader reader = new PEMReader(new StringReader(key));
        DSAPublicKey decoded = (DSAPublicKey) reader.readObject();

        DSADigestSigner dsa = new DSADigestSigner(new DSASigner(), new SHA1Digest());
        DSAParameters params = new DSAParameters(
            decoded.getParams().getP(),
            decoded.getParams().getQ(),
            decoded.getParams().getG()
        );
        DSAPublicKeyParameters publickey = new DSAPublicKeyParameters(decoded.getY(), params);
        dsa.init(false, publickey);
        dsa.update(message, 0, message.length);
        boolean result = dsa.verifySignature(signature);

        System.out.println(result ? "good" : "bad");
    }

    public static byte[] hexStringToByteArray(String s)
    {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2)
        {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
}

签名未验证.我的Java代码有问题吗?也许OpenSSL在dss1方面做得很奇怪?

The signature is not validating. Is there something wrong with my Java code? Maybe OpenSSL is doing something weird with dss1?

我能够使用OpenSSL验证签名:

I was able to validate the signature just fine with OpenSSL:

openssl dgst -dss1 -verify dsa_pub.pem -signature sigfile.bin foo.txt

推荐答案

(Unix)echo输出其参数,如果有多个,则以空格分隔,加上A NEWLINE .使用"foobar\n"作为要验证的数据.或者,在printf '%s' foobar >foo.txt的结果上签名,该结果便携式会省略换行符; 某些 版本为此目的支持-n,一些较旧的版本使用\c,而有些则完全不支持.

(Unix) echo outputs its arguments, space-separated if more than one, PLUS A NEWLINE. Use "foobar\n" as the data to verify. Alternatively sign the result of printf '%s' foobar >foo.txt which portably omits the newline; some versions of echo support -n for this purpose, some older ones use \c, and some don't support it at all.

FYI BouncyCastle自版本150(2013)起不再具有org.bouncycastle.openssl.PEMReader;相反,您需要PEMParser返回的org.bouncycastle.asn1.x509.SubjectPublicKeyInfo可以通过org.bouncycastle.openssl.jcajce.JcaPEMKeyConverterKeyFactory.getInstance(alg).generatePublicKey(new X509EncodedKey(spki.getEncoded()))转换为键对象,而JcaPEMKeyConverter实际上是这样做的.

FYI BouncyCastle as of version 150 (2013) no longer has org.bouncycastle.openssl.PEMReader; instead you need PEMParser which returns org.bouncycastle.asn1.x509.SubjectPublicKeyInfo which can be converted to key object by org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter or KeyFactory.getInstance(alg).generatePublicKey(new X509EncodedKey(spki.getEncoded())) which is what JcaPEMKeyConverter actually does.

OTOH,您可以使用org.bouncycastle.jcajce.provider.asymmetric.dsa.DSAUtil.generatePublicKeyParameter用参数件替换该摆弄;这就是BC提供程序界面(与轻量级界面相对)的作用.或者当然,您可以首先使用JCA,而实际上根本不需要BC,因为OpenSSL公钥格式(与私钥不同)始终与基本Java加密兼容.

OTOH you can use org.bouncycastle.jcajce.provider.asymmetric.dsa.DSAUtil.generatePublicKeyParameter to replace that fiddling with the parameter pieces; that's what the BC provider interface (as opposed to the lightweight interface) does. Or of course you could just use JCA in the first place and you don't really need BC at all, since OpenSSL publickey formats (unlike privatekey) are consistently compatible with basic Java crypto.

此外BTW openssl dgst仅通过0.9.8版才需要-dss1 hack;自2010年发布1.0.0版以来(由于实际或担心的不兼容性,许多发行版和产品都没有立即对其进行升级),因此您只需要-sha1和DSA公开密钥.

Also BTW openssl dgst needed the -dss1 hack only through version 0.9.8; since version 1.0.0 released 2010 (but not immediately upgraded by many distros and products due to actual or feared incompatibility) you only need -sha1 and a DSA pubkey.

这篇关于无法验证带有dsa密钥的openssl签名的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆