Cryptography 数字签名每次都不同

Cryptography 数字签名每次都不同,cryptography,blockchain,Cryptography,Blockchain,数字签名依赖于消息和密钥。假设接收者多次复制消息(这是我们唯一ID的原因),为什么签名会不同(因为消息和密钥是相同的)?比特币使用ECDSA,而同一消息和密钥的签名不同的原因是每次创建签名时生成的随机时值 ECDSA签名是一对(r,s),其中r是kG的X坐标,s=(m+r*X)/k(其中k=nonce,m=messagehash,X=private key,G=curve generator) 另请参见《比特币使用ECDSA》中的#3,同一消息和密钥的签名不同的原因是每次创建签名时都会生成随机的

数字签名依赖于消息和密钥。假设接收者多次复制消息(这是我们唯一ID的原因),为什么签名会不同(因为消息和密钥是相同的)?

比特币使用ECDSA,而同一消息和密钥的签名不同的原因是每次创建签名时生成的随机时值

ECDSA签名是一对(r,s),其中r是kG的X坐标,s=(m+r*X)/k(其中k=nonce,m=messagehash,X=private key,G=curve generator)


另请参见《比特币使用ECDSA》中的#3,同一消息和密钥的签名不同的原因是每次创建签名时都会生成随机的nonce

ECDSA签名是一对(r,s),其中r是kG的X坐标,s=(m+r*X)/k(其中k=nonce,m=messagehash,X=private key,G=curve generator)


另见#3 in

这一答案只是对上述理论答案的实际补充。此代码段使用相同的私钥在
for循环中反复对同一消息进行数字签名,每次都打印出不同的数字签名。每个签名都是有效的,并将使用签名者的公钥进行验证

import java.security.Security;
import java.security.Signature;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.KeyPairGenerator;
import java.security.KeyPair;

import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

class liptic
{
    static String the_message = "how are you, little tiger?";

    public static void main(String args[]) throws Exception
    {
        Security.addProvider(new BouncyCastleProvider());
        SecureRandom random = new SecureRandom();
        ECParameterSpec ecSpec
            = 
ECNamedCurveTable.getParameterSpec("secp256k1");

        KeyPairGenerator g = 
KeyPairGenerator.getInstance("ECDH", "BC");
        g.initialize(ecSpec, random);
        KeyPair keyPair = g.generateKeyPair();

        byte[] bob_pubkey = Hex.decode( "040581E4AEEEB1CEA57094D1AD97B8C721509B6E5D3690C70BBB8EB2C5FE8040"
        +  "FB2C9B0A77EA2AD05C5E8DB499F647BC9A8BE829961950D6F5A45952C097CCB0BC");
    Signature signer = Signature.getInstance("SHA256withECDSA", "BC");

    ECPublicKeySpec pubkSpec = new ECPublicKeySpec(
        ecSpec.getCurve().decodePoint(bob_pubkey), ecSpec);

    ECPublicKey publicKey
        = (ECPublicKey)KeyFactory.getInstance("ECDSA", "BC")
              .generatePublic(pubkSpec);

    byte[] signature = null;
    byte[] input = the_message.getBytes();
    signer.initSign(keyPair.getPrivate());
    signer.update(input);
    for (int i = 0; i < 5; i++) {
        signature = signer.sign();
        System.out.println(o(signature));
    }
  }

    public static String o(byte[] bytes)
    {
      int n = 0;
      StringBuilder sb = new StringBuilder();
      for (byte b : bytes) {
        sb.append(String.format("%02X", b));
        n++;
        if (n % 128 == 0) {
            sb.append("\n");
        }
      }
      return sb.toString();
   }
}
导入java.security.security;
导入java.security.Signature;
导入java.security.KeyFactory;
导入java.security.KeyPairGenerator;
导入java.security.SecureRandom;
导入java.security.KeyPairGenerator;
导入java.security.KeyPair;
导入org.bouncycastle.util.encoders.Hex;
导入org.bouncycastle.jce.ECNamedCurveTable;
导入org.bouncycastle.jce.spec.ECParameterSpec;
导入org.bouncycastle.jce.interfaces.ECPublicKey;
导入org.bouncycastle.jce.spec.ECPublicKeySpec;
导入org.bouncycastle.jce.provider.BouncyCastleProvider;
脂类
{
静态字符串_message=“你好吗,小老虎?”;
公共静态void main(字符串args[])引发异常
{
addProvider(新的BouncyCastleProvider());
SecureRandom=新的SecureRandom();
ECParameterSpec ecSpec
= 
ECNamedCurveTable.getParameterSpec(“secp256k1”);
键对发电机g=
getInstance(“ECDH”、“BC”);
g、 初始化(ecSpec,随机);
KeyPair KeyPair=g.generateKeyPair();
字节[]bob_pubkey=Hex.decode(“0405811E4AEEEB1CEA57094D1AD97B8C721509B6E5D3690C70BBB8EB2C5FE8040”
+“FB2C9B0A77EA2AD05C5E8DB499F647BC9A8BE829961950D6F5A45952C097CCB0BC”);
Signature signer=Signature.getInstance(“SHA256withECDSA”、“BC”);
ECPublicKeySpec pubkSpec=新的ECPublicKeySpec(
ecSpec.getCurve().decodePoint(bob_pubkey),ecSpec;
ECPublicKey公钥
=(ECPublicKey)KeyFactory.getInstance(“ECDSA”、“BC”)
.generatePublic(pubkSpec);
字节[]签名=null;
byte[]input=_message.getBytes();
signer.initSign(keyPair.getPrivate());
签名者更新(输入);
对于(int i=0;i<5;i++){
signature=signer.sign();
系统输出打印LN(o(签名));
}
}
公共静态字符串o(字节[]字节)
{
int n=0;
StringBuilder sb=新的StringBuilder();
for(字节b:字节){
sb.append(字符串格式(“%02X”,b));
n++;
如果(n%128==0){
某人附加(“\n”);
}
}
使某人返回字符串();
}
}
以下是数字签名:

  • 3046022100889CC42C4BAA07FF33AB34CADD8BCB0A44E77031D4A5F5A9849840DF3AB63FDA0221009CA5C49FC0EBE9F839A0CFAB18CEC91C9169FF439C1E2DFD724D06E2DB9FE258
  • 30460221009D30465EFD3676982CBE12B998D41D012322C255594D5037F156143AEC7E7305022100A7FE7DEB580837A1A5A5D1B74334C56E9F26BA1834EE3AC93ECEB01349A6F1C
  • 3045022100DF4AF153D808A9199C18C97E689F1214E7F59C621D6ECBAADFE206B83707CA2802203E592D0152E79E1408183206F4B6DBC95D68FBA23F65884A3B68FA79A4E04
  • 304502202E9FA22709308D08106F76CBB6278B3F485A3C706EDA3FFAF5CE744DB90E9510221009DD2370863D6C1CE36D828FF9B98347905F2D0856052C4A30B25DD00575B8921
  • 3045022100AA46FEA1A80498E481D46B17EFD7FBE665641CD719AF1F5DC0C77AD334729D0220471472117374E0284074EBC81172E6271CA9D86F54AFCE6E6CF6863814EBF824

这是使用椭圆曲线的数字签名算法

这个答案只是对上述理论答案的实际补充。此代码段使用相同的私钥在
for循环中反复对同一消息进行数字签名,每次都打印出不同的数字签名。每个签名都是有效的,并将使用签名者的公钥进行验证

import java.security.Security;
import java.security.Signature;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.KeyPairGenerator;
import java.security.KeyPair;

import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

class liptic
{
    static String the_message = "how are you, little tiger?";

    public static void main(String args[]) throws Exception
    {
        Security.addProvider(new BouncyCastleProvider());
        SecureRandom random = new SecureRandom();
        ECParameterSpec ecSpec
            = 
ECNamedCurveTable.getParameterSpec("secp256k1");

        KeyPairGenerator g = 
KeyPairGenerator.getInstance("ECDH", "BC");
        g.initialize(ecSpec, random);
        KeyPair keyPair = g.generateKeyPair();

        byte[] bob_pubkey = Hex.decode( "040581E4AEEEB1CEA57094D1AD97B8C721509B6E5D3690C70BBB8EB2C5FE8040"
        +  "FB2C9B0A77EA2AD05C5E8DB499F647BC9A8BE829961950D6F5A45952C097CCB0BC");
    Signature signer = Signature.getInstance("SHA256withECDSA", "BC");

    ECPublicKeySpec pubkSpec = new ECPublicKeySpec(
        ecSpec.getCurve().decodePoint(bob_pubkey), ecSpec);

    ECPublicKey publicKey
        = (ECPublicKey)KeyFactory.getInstance("ECDSA", "BC")
              .generatePublic(pubkSpec);

    byte[] signature = null;
    byte[] input = the_message.getBytes();
    signer.initSign(keyPair.getPrivate());
    signer.update(input);
    for (int i = 0; i < 5; i++) {
        signature = signer.sign();
        System.out.println(o(signature));
    }
  }

    public static String o(byte[] bytes)
    {
      int n = 0;
      StringBuilder sb = new StringBuilder();
      for (byte b : bytes) {
        sb.append(String.format("%02X", b));
        n++;
        if (n % 128 == 0) {
            sb.append("\n");
        }
      }
      return sb.toString();
   }
}
导入java.security.security;
导入java.security.Signature;
导入java.security.KeyFactory;
导入java.security.KeyPairGenerator;
导入java.security.SecureRandom;
导入java.security.KeyPairGenerator;
导入java.security.KeyPair;
导入org.bouncycastle.util.encoders.Hex;
导入org.bouncycastle.jce.ECNamedCurveTable;
导入org.bouncycastle.jce.spec.ECParameterSpec;
导入org.bouncycastle.jce.interfaces.ECPublicKey;
导入org.bouncycastle.jce.spec.ECPublicKeySpec;
导入org.bouncycastle.jce.provider.BouncyCastleProvider;
脂类
{
静态字符串_message=“你好吗,小老虎?”;
公共静态void main(字符串args[])引发异常
{
addProvider(新的BouncyCastleProvider());
SecureRandom=新的SecureRandom();
ECParameterSpec ecSpec
= 
ECNamedCurveTable.getParameterSpec(“secp256k1”);
键对发电机g=
getInstance(“ECDH”、“BC”);
g、 初始化(ecSpec,随机);
KeyPair KeyPair=g.generateKeyPair();
字节[]bob_pubkey=Hex.decode(“0405811E4AEEEB1CEA57094D1AD97B8C721509B6E5D3690C70BBB8EB2C5FE8040”
+“FB2C9B0A77EA2AD05C5E8DB499F647BC9A8BE829961950D6F5A45952C097CCB0BC”);
签名者=签名者