3

Digital signatures depend upon message and the secret key. Suppose receiver copies the message several times ( the reason for which we unique ids) , why will the signature be different (since the message and secret key are same)?

  • This varies by the signature scheme. Non-textbook rsa has a random padding component which results in the signatures being different. – Thomas M. DuBuisson Jun 10 '19 at 04:40
  • I'm voting to close this question as off-topic because it had not to do with programming. – Thomas M. DuBuisson Jun 10 '19 at 04:41
  • You need to provide more details, like the signing algorithm you are using. Possible duplicate of [Why does RSA encrypted text give me different results for the same text](https://stackoverflow.com/q/16325057/608639) – jww Jun 10 '19 at 05:23
  • I am not using any algorithm now. I am studying about bitcoin and I saw this video - https://www.youtube.com/watch?v=bBC-nXj3Ng4 where at around 7 mins they say that use a unique id along with each message so that reciever cannot duplicate it and a different signature wil be required. My question is how can the signature be different if it only depends upon the message and secret key? – neha agarwal Jun 10 '19 at 07:21
  • Even today, most RSA signatures are PKCS#1 v1.5 which uses deterministic padding. The same data will give the same signature every time. Most libraries now have support for RSA PSS, which is randomized and has better security properties. – President James K. Polk Jun 10 '19 at 14:24

2 Answers2

6

Bitcoin uses ECDSA, and the reason the signature is different for the same message and key is the random nonce, which is generated each time a signature is created.

An ECDSA signature is a pair (r,s) where r is the X coordinate of kG, and s = (m+r*x)/k (where k=nonce, m=message hash, x=private key, G=curve generator).

See also #3 in https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Signature_generation_algorithm

JBaczuk
  • 13,886
  • 10
  • 58
  • 86
0

This answer is just a practical supplement to the theoretical answer provided above. This snippet digitally signs inside the for-loop the same message over and over again using the same private key and each time, it is printing out different digital signatures. Each of these signatures are valid and will verify using the signer's public key.

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();
   }
}

Here are the digital signatures:

  • 3046022100889CC42C4BAA07FF33AB34CADD8BCB0A44E77031D4A5F5A9849840DF3AB63FDA0221009CA5C49FC0EBE9F839A0CFAB18CEC91C9169FF439C1E2DFD724D06E2DB9FE258
  • 30460221009D30465EFD3676982CBE12B998D41D012322C255594D5037F156143AEC7E7305022100A77FE7DEB580837A1A5A5D1B74334C56E9F26BA1834EE3AC93ECEB01349A6F1C
  • 3045022100DF4AF153D808A9199C18C97E689F1214E7F59C621D6ECBAADFE206B83707CA2802203E592D0152E79E14084183206F4B6DBC95D68FBA2D23F65884A3B68FA79A4E04
  • 304502202E9FA22709308D08106F76CBB6278B3F485A3C706EDA3FFAF5CE744D4B90E9510221009DD2370863D6C1CE36D828FF9B98347905F2D0856052C4A30B25DD00575B8921
  • 3045022100AA46FEA1A80498E481D46B17EFD7FBE6656641CD719AF1F5DC0C77ADD334729D0220471472117374E0284074EBC81172E6271CA9D86F54AFCE6E6CF6863814EBF824

This is using the Elliptic Curve Digital Signature Algorithm.

daparic
  • 3,794
  • 2
  • 36
  • 38