java 使用 secp256r1 曲线和 SHA256 算法生成 ECDSA 签名 - BouncyCastle

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25261823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 07:42:35  来源:igfitidea点击:

ECDSA signature generation using secp256r1 curve and SHA256 algorithm - BouncyCastle

javabouncycastlesha256ecdsa

提问by dave_thompson_085

I am trying to generate signature using ECDSA with secp256r1 curve (P256) and SHA256 algorithm for message hash. Also i am using Bouncy Castle libraries. Code below,

我正在尝试使用带有 secp256r1 曲线(P256)和 SHA256 算法的 ECDSA 生成签名以进行消息哈希。我也在使用 Bouncy Castle 库。下面的代码,

public class MyTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        new MyTest().getSign();
    }

    void getSign() {
        // Get the instance of the Key Generator with "EC" algorithm

        try {
            KeyPairGenerator g = KeyPairGenerator.getInstance("EC");
            ECGenParameterSpec kpgparams = new ECGenParameterSpec("secp256r1");
            g.initialize(kpgparams);

            KeyPair pair = g.generateKeyPair();
            // Instance of signature class with SHA256withECDSA algorithm
            Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
            ecdsaSign.initSign(pair.getPrivate());

            System.out.println("Private Keys is::" + pair.getPrivate());
            System.out.println("Public Keys is::" + pair.getPublic());

            String msg = "text ecdsa with sha256";//getSHA256(msg)
            ecdsaSign.update((msg + pair.getPrivate().toString())
                    .getBytes("UTF-8"));

            byte[] signature = ecdsaSign.sign();
            System.out.println("Signature is::"
                    + new BigInteger(1, signature).toString(16));

            // Validation
            ecdsaSign.initVerify(pair.getPublic());
            ecdsaSign.update(signature);
            if (ecdsaSign.verify(signature))
                System.out.println("valid");
            else
                System.out.println("invalid!!!!");

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }

    }

}

Here key pairs are generated using KeyPair , but for my requirement I will be having a static privateKey and public key. Also, validation of signature is always returning false.

这里的密钥对是使用 KeyPair 生成的,但根据我的要求,我将拥有一个静态私钥和公钥。此外,签名验证总是返回 false。

Need help, how can I have static private key and on validation part.

需要帮助,我如何拥有静态私钥和验证部分。

回答by dave_thompson_085

Hymanpot - nothing in your title is a problem!

头奖 - 您的头衔中没有任何问题!

First, you probably aren't actually using BouncyCastle. Sun/Oracle Java 7 and 8 now includes an EC provider (earlier versions did not) and the one-arg form of getInstanceuses the first available provider, which is normally SunEC unless you or someone has altered the provider list.

首先,您可能实际上并未使用 BouncyCastle。Sun/Oracle Java 7 和 8 现在包含一个 EC 提供程序(早期版本没有),并且单参数形式getInstance使用第一个可用的提供程序,通常是 SunEC,除非您或某人更改了提供程序列表。

TO VERIFY A SIGNATURE:pass the samedata to the verifying Signature.update()as you passed to the signing Signature.update(). Exactlythe same, byte for byte. Pass the signature value onlyto Signature.verify(). Putting PrivateKey.toString()in the data is silly; this value is specific to the running Java process, so you'll have to send it to the receiving process (if different, as it normally should be) where it is useless and a waste of space.

验证签名:Signature.update()传递给签名相同的数据传递给验证Signature.update()完全一样,一个字节一个字节。将签名值传递给Signature.verify(). 把PrivateKey.toString()在数据是愚蠢; 此值特定于正在运行的 Java 进程,因此您必须将它发送到接收进程(如果不同,通常应该是),在那里它是无用的并且浪费空间。

TO USE A STATIC KEY:do just that. Create a keypair and store it someplace, then read it in and use it. The easiest secure (password protected) store is a Java KeyStore (JKS) file, but that requires a certificate chain (perhaps a dummy one) which is a nuisance to code yourself; fortunately the keytoolutility with -genkeypairgenerates a keypair with a dummy selfsigned certificate, and for -keyalg ec -keysize 256it uses the (very popular) secp256r1 curve. Also specify -alias nameof your choice, -keystore filename, any names you like for the dummy cert, and passwords. To use a keypair from a JKS file:

使用静态密钥:这样做。创建一个密钥对并将其存储在某个地方,然后读入并使用它。最简单的安全(受密码保护)存储是 Java KeyStore (JKS) 文件,但这需要一个证书链(可能是一个虚拟的),这对自己编写代码很麻烦;幸运的是,keytool实用程序 with-genkeypair生成了一个带有虚拟自签名证书的密钥对,-keyalg ec -keysize 256因此它使用(非常流行的)secp256r1 曲线。还要指定-alias name您的选择、-keystore filename您喜欢的虚拟证书名称和密码。要使用 JKS 文件中的密钥对:

  • use java.security.KeyStore.getInstance("JKS")to create a store object and pass .load(InputStream,char[])a FileInputStreamon the file, and the password.

  • use .getKey(String alias,char[] password)and cast to get the PrivateKey. Use for signing.

  • use .getCertificateChain(String alias)[0].getPublicKey()to get the PublicKey from the first (only) cert. Use for verifying.

  • 使用java.security.KeyStore.getInstance("JKS")创建存储对象,并通过.load(InputStream,char[])一个FileInputStream上的文件和密码。

  • 使用.getKey(String alias,char[] password)并强制转换以获取私钥。用于签名。

  • 用于.getCertificateChain(String alias)[0].getPublicKey()从第一个(唯一)证书中获取 PublicKey。用于验证。