Pages:
Author

Topic: [SOLVED] Can someone explain the details of how OP_CHECKSIG operates? - page 2. (Read 9282 times)

Activity: -
Merit: -
Thanks again dirtyfilthy!  Amazingly, it turns out I'm generating keys, signing and verifying data the same way as you are.

So this means I'm misunderstanding something when creating the transaction copy or the sub-script to be used in the transaction copy.

I'm working with transaction 0f898c5494eaa468d12cf0630a0c0b238cc1149c1c53bbc592d16497094e95ff:
http://blk.bitcoinwatch.com/b?h=103958
http://blockexplorer.com/t/AgktCstTqJ

Code:
Here's a parsed version of this transaction (plain hexdump version below):

Tx:
01 00 00 00 - version
03 - TxIn count

TxIn:
  Outpoint:
    30 f3 70 1f 9b c4 64 55 2f 70 49 57 91 04 08 17
    ce 77 7a d5 ed e1 6e 52 9f cd 0c 0e 94 91 56 94 - prev tx hash
    00 00 00 00                                     - prev TxOut index

  8c                                                - scriptSig length
  49 30 46 02 21 00 f5 74 6b 0b 25 4f 5a 37 e7 52
  51 45 9c 7a 23 b6 df cb 86 8a c7 46 7e dd 9a 6f
  dd 1d 96 98 71 be 02 21 00 88 94 8a ea 29 b6 91
  61 ca 34 1c 49 c0 26 86 a8 1d 8c bb 73 94 0f 91
  7f a0 ed 71 54 68 6d 3e 5b 01 41 04 47 d4 90 56
  1f 39 6c 8a 9e fc 14 48 6b c1 98 88 4b a1 83 79
  bc ac 2e 0b e2 d8 52 51 34 ab 74 2f 30 1a 9a ca
  36 60 6e 5d 29 aa 23 8a 9e 29 93 00 31 50 42 3d
  f6 92 45 63 64 2d 4a fe 9b f4 fe 28               - scriptSig
  ff ff ff ff                                       - sequence

TxIn:
  Outpoint:
    72 14 2b f7 68 6c e9 2c 6d e5 b7 33 65 bf b9 d5
    9b b6 0c 2c 80 98 2d 59 58 c1 e6 a3 b0 8e a6 89 - prev tx hash
    00 00 00 00                                     - prev TxOut index
  4a                                                - scriptSig length
  49 30 46 02 21 00 bc e4 3a d3 ac bc 79 b0 24 7e
  54 c8 c9 1e ac 1c f9 03 75 05 00 0e 01 d1 fd 81
  18 54 d8 5b c2 1a 02 21 00 99 2a 6f 6f 2f eb 6f
  62 d3 70 6f 3b 9a aa b8 8d 9f 11 32 95 6a 1d ff
  a9 26 cd 55 6e d5 53 60 df 01                     - scriptSig
  ff ff ff ff                                       - sequence

TxIn:
  Outpoint:
    d2 81 28 bb b6 20 7c 1c 3d 0a 63 0c c6 19 dc 7e
    7b ea 56 ac 19 a1 da b1 27 c6 2c 78 fa 1b 63 2c - prev tx hash
    00 00 00 00                                     - prev TxOut index
  49                                                - scriptSig length
  48 30 45 02 20 20 97 57 36 81 61 53 77 08 fd 29
  d8 9b b1 e9 d6 48 00 79 49 ec fd ed 78 9b 51 a9
  63 24 cb 65 18 02 21 00 cd 0f 7c 30 21 39 16 48
  2b 6e 16 6d 8a 4f 2b 98 1f 77 7e b1 84 cd 8a 49
  5f 1b 3d 36 90 fb bf 2d 01                        - scriptSig
  ff ff ff ff                                       - sequence

01                                                  - TxOut count

TxOut:
  00 a6 f7 5f 02 00 00 00                           - value
  19                                                - scriptPubKey length
  76 a9 14 9e 35 d9 3c 77 92 bd ca ad 56 97 dd eb
  f0 43 53 d9 a5 e1 96 88 ac                        - scriptPubKey
00 00 00 00                                         - lock time


Plain hexdump:
01 00 00 00 03 30 f3 70  1f 9b c4 64 55 2f 70 49   .....0.p...dU/pI
57 91 04 08 17 ce 77 7a  d5 ed e1 6e 52 9f cd 0c   W.....wz...nR...
0e 94 91 56 94 00 00 00  00 8c 49 30 46 02 21 00   ...V......I0F.!.
f5 74 6b 0b 25 4f 5a 37  e7 52 51 45 9c 7a 23 b6   .tk.%OZ7.RQE.z#.
df cb 86 8a c7 46 7e dd  9a 6f dd 1d 96 98 71 be   .....F~..o....q.
02 21 00 88 94 8a ea 29  b6 91 61 ca 34 1c 49 c0   .!.....)..a.4.I.
26 86 a8 1d 8c bb 73 94  0f 91 7f a0 ed 71 54 68   &.....s......qTh
6d 3e 5b 01 41 04 47 d4  90 56 1f 39 6c 8a 9e fc   m>[.A.G..V.9l...
14 48 6b c1 98 88 4b a1  83 79 bc ac 2e 0b e2 d8   .Hk...K..y......
52 51 34 ab 74 2f 30 1a  9a ca 36 60 6e 5d 29 aa   RQ4.t/0...6`n]).
23 8a 9e 29 93 00 31 50  42 3d f6 92 45 63 64 2d   #..)..1PB=..Ecd-
4a fe 9b f4 fe 28 ff ff  ff ff 72 14 2b f7 68 6c   J....(....r.+.hl
e9 2c 6d e5 b7 33 65 bf  b9 d5 9b b6 0c 2c 80 98   .,m..3e......,..
2d 59 58 c1 e6 a3 b0 8e  a6 89 00 00 00 00 4a 49   -YX...........JI
30 46 02 21 00 bc e4 3a  d3 ac bc 79 b0 24 7e 54   0F.!...:...y.$~T
c8 c9 1e ac 1c f9 03 75  05 00 0e 01 d1 fd 81 18   .......u........
54 d8 5b c2 1a 02 21 00  99 2a 6f 6f 2f eb 6f 62   T.[...!..*oo/.ob
d3 70 6f 3b 9a aa b8 8d  9f 11 32 95 6a 1d ff a9   .po;......2.j...
26 cd 55 6e d5 53 60 df  01 ff ff ff ff d2 81 28   &.Un.S`........(
bb b6 20 7c 1c 3d 0a 63  0c c6 19 dc 7e 7b ea 56   .. |.=.c....~{.V
ac 19 a1 da b1 27 c6 2c  78 fa 1b 63 2c 00 00 00   .....'.,x..c,...
00 49 48 30 45 02 20 20  97 57 36 81 61 53 77 08   .IH0E.  .W6.aSw.
fd 29 d8 9b b1 e9 d6 48  00 79 49 ec fd ed 78 9b   .).....H.yI...x.
51 a9 63 24 cb 65 18 02  21 00 cd 0f 7c 30 21 39   Q.c$.e..!...|0!9
16 48 2b 6e 16 6d 8a 4f  2b 98 1f 77 7e b1 84 cd   .H+n.m.O+..w~...
8a 49 5f 1b 3d 36 90 fb  bf 2d 01 ff ff ff ff 01   .I_.=6...-......
00 a6 f7 5f 02 00 00 00  19 76 a9 14 9e 35 d9 3c   ..._.....v...5.<
77 92 bd ca ad 56 97 dd  eb f0 43 53 d9 a5 e1 96   w....V....CS....
88 ac 00 00 00 00                                  ......


I'm attempting to verify the transaction input that points to the only output of transaction 30f3701f9bc464552f70495791040817ce777ad5ede16e529fcd0c0e94915694:
http://blk.bitcoinwatch.com/b?h=103640
http://blockexplorer.com/t/6d3E7ZWBDe

Code:
Parsed version of the transaction copy when trying to verify the input (plain hexdump version below):

Tx:
01 00 00 00                                          - version
03                                                   - TxIn count

TxIn:
  Outpoint:
    30 f3 70 1f 9b c4 64 55 2f 70 49 57 91 04 08 17
    ce 77 7a d5 ed e1 6e 52 9f cd 0c 0e 94 91 56 94  - prev TxOut hash
    00 00 00 00                                      - index

  5b                                                 - scriptSig length
  41 04 47 d4 90 56 1f 39 6c 8a 9e fc 14 48 6b c1
  98 88 4b a1 83 79 bc ac 2e 0b e2 d8 52 51 34 ab
  74 2f 30 1a 9a ca 36 60 6e 5d 29 aa 23 8a 9e 29
  93 00 31 50 42 3d f6 92 45 63 64 2d 4a fe 9b f4
  fe 28 76 a9 14 02 bf 4b 28 89 c6 ad a8 19 0c 25
  2e 70 bd e1 a1 90 9f 96 17 88 ac                   - scriptSig (includes scriptPubkey
                                                                  from prev TxOut)
  ff ff ff ff                                        - sequence

TxIn:
  Outpoint:
    72 14 2b f7 68 6c e9 2c 6d e5 b7 33 65 bf b9 d5
    9b b6 0c 2c 80 98 2d 59 58 c1 e6 a3 b0 8e a6 89  - prev TxOut hash
    00 00 00 00                                      - index
  00                                                 - scriptSig length
  ff ff ff ff                                        - sequence

TxIn:
  Outpoint:
    d2 81 28 bb b6 20 7c 1c 3d 0a 63 0c c6 19 dc 7e
    7b ea 56 ac 19 a1 da b1 27 c6 2c 78 fa 1b 63 2c  - prev TxOut hash
    00 00 00 00                                      - index
  00                                                 - scriptSig length
  ff ff ff ff                                        - sequence

TxOut Count
  01                                                 - TxOut count
  00 a6 f7 5f 02 00 00 00                            - Transaction Value
  19                                                 - scriptPubKey length
  76 a9 14 9e 35 d9 3c 77 92 bd ca ad 56 97 dd eb
  f0 43 53 d9 a5 e1 96 88 ac                         - scriptPubKey

00 00 00 00                                          - sequence


Plain hexdump:
01 00 00 00 03 30 f3 70  1f 9b c4 64 55 2f 70 49   .....0.p...dU/pI
57 91 04 08 17 ce 77 7a  d5 ed e1 6e 52 9f cd 0c   W.....wz...nR...
0e 94 91 56 94 00 00 00  00 5b 41 04 47 d4 90 56   ...V.....[A.G..V
1f 39 6c 8a 9e fc 14 48  6b c1 98 88 4b a1 83 79   .9l....Hk...K..y
bc ac 2e 0b e2 d8 52 51  34 ab 74 2f 30 1a 9a ca   ......RQ4.t/0...
36 60 6e 5d 29 aa 23 8a  9e 29 93 00 31 50 42 3d   6`n]).#..)..1PB=
f6 92 45 63 64 2d 4a fe  9b f4 fe 28 76 a9 14 02   ..Ecd-J....(v...
bf 4b 28 89 c6 ad a8 19  0c 25 2e 70 bd e1 a1 90   .K(......%.p....
9f 96 17 88 ac ff ff ff  ff 72 14 2b f7 68 6c e9   .........r.+.hl.
2c 6d e5 b7 33 65 bf b9  d5 9b b6 0c 2c 80 98 2d   ,m..3e......,..-
59 58 c1 e6 a3 b0 8e a6  89 00 00 00 00 00 ff ff   YX..............
ff ff d2 81 28 bb b6 20  7c 1c 3d 0a 63 0c c6 19   ....(.. |.=.c...
dc 7e 7b ea 56 ac 19 a1  da b1 27 c6 2c 78 fa 1b   .~{.V.....'.,x..
63 2c 00 00 00 00 00 ff  ff ff ff 01 00 a6 f7 5f   c,............._
02 00 00 00 19 76 a9 14  9e 35 d9 3c 77 92 bd ca   .....v...5.ad 56 97 dd eb f0 43 53  d9 a5 e1 96 88 ac 00 00   .V....CS........
00 00                                              ..


This is just a plain JVM-based client written in Clojure (http://clojure.org), not intended for Android use at this point.

P.S. dirtyfilthy, it looks like you've got an unnecessary line of code in your generateKeyPair() function:
Code:
ContentValues initialValues = new ContentValues();


EDIT: Changed byte-order of transaction hashes.
member
Activity: 77
Merit: 10
public class KeyTools {
   
   // encodes a public key into the form [0x04][32 bytes 'x' value][32 bytes 'y' value]
   
   public static byte[] encodePublicKey(ECPublicKey key){
      net.dirtyfilthy.bouncycastle.math.ec.ECPoint p=EC5Util.convertPoint(key.getParams(), key.getW(), false);
      return p.getEncoded();
   }
   
   // decodes a raw public key in the form [0x04][32 bytes 'x' value][32 bytes 'y' value]
   
   public static ECPublicKey decodePublicKey(byte[] encoded){
      ECNamedCurveParameterSpec params = ECNamedCurveTable.getParameterSpec("secp256k1");
      KeyFactory fact;
      try {
         fact = KeyFactory.getInstance("ECDSA", "DFBC");
      } catch (NoSuchAlgorithmException e) {
         throw new RuntimeException(e);
      } catch (NoSuchProviderException e) {
         throw new RuntimeException(e);
      }
      ECCurve curve = params.getCurve();
      java.security.spec.EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, params.getSeed());
       java.security.spec.ECPoint point=ECPointUtil.decodePoint(ellipticCurve, encoded);
       java.security.spec.ECParameterSpec params2=EC5Util.convertSpec(ellipticCurve, params);
       java.security.spec.ECPublicKeySpec keySpec = new java.security.spec.ECPublicKeySpec(point,params2);
       try {
         return (ECPublicKey) fact.generatePublic(keySpec);
      } catch (InvalidKeySpecException e) {
         throw new RuntimeException(e);
      }
      
   }
   

   public static byte[] signData(ECPrivateKey key,byte data[]){
      Signature s;
      try {
         s = Signature.getInstance("ECDSA", "DFBC");
         s.initSign(key);
         s.update(data);
         return s.sign();
      } catch (NoSuchAlgorithmException e) {
         throw new RuntimeException(e);
      } catch (NoSuchProviderException e) {
         throw new RuntimeException(e);
      } catch (InvalidKeyException e) {
         throw new RuntimeException(e);
      } catch (SignatureException e) {
         throw new RuntimeException(e);
      }
      
   }
   

   public static KeyPair generateKeyPair() {
      ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256k1");
      KeyPairGenerator generator;
      try {
         generator = KeyPairGenerator.getInstance("ECDSA", "DFBC");
         generator.initialize(ecSpec, new SecureRandom());
         KeyPair pair = generator.generateKeyPair();
         ContentValues initialValues = new ContentValues();
         return pair;
      } catch (NoSuchAlgorithmException e) {
         throw new RuntimeException(e);
      } catch (NoSuchProviderException e) {
         throw new RuntimeException(e);
      } catch (InvalidAlgorithmParameterException e) {
         throw new RuntimeException(e);
      }
      
   }

   public static boolean verifySignedData(ECPublicKey key,byte data[], byte sig[]){
      Signature s;
      try {
      s= Signature.getInstance("ECDSA", "DFBC");
      s.initVerify(key);
      s.update(data);
      return s.verify(sig);
      } catch (NoSuchAlgorithmException e) {
         throw new RuntimeException(e);
      } catch (NoSuchProviderException e) {
         throw new RuntimeException(e);
      } catch (InvalidKeyException e) {
         throw new RuntimeException(e);
      } catch (SignatureException e) {
         throw new RuntimeException(e);
      }
   }

}


I renamed the packages from org.bouncycastle to net.dirtyfilthy.bouncycastle so as not to conflict with the (incomplete) android bouncycastle libraries. Also renamed the provider string from "BC" to "DFBC" for the same reason. Not sure if your developing for android or just for the standard javavm, in which case you should rename these to their usual names.
Activity: -
Merit: -
Thanks dirtyfilthy and Hal!  I believe I now have it mostly figured out.  The opcodes, including OP_CHECKSIG, are running as expected, but my signature verification function is returning false, causing OP_CHECKSIG to return 0.

dirtyfilthy, I'm curious about your code for verifying signatures (and though not related to this current problem, I'd love to see your code for generating new key pairs, and signing data, too). Would you please share that?  This will help me narrow down where the problem is (I think either my signature verification function is incorrect or the temporary transactions I'm creating are incorrect, or both).

If I'm still having problems after I make sure my signature verification function is correct, I'll post hex dumps of the transaction I'm trying to verify as well as the temporary transaction created for signature verification to see if anyone can point out where I went wrong.

Thanks again!
Hal
vip
Activity: 314
Merit: 4276
I made some edits. It might be nice to explain what the various SIGHASH values are intended to be used for, and whether they will work at this time.
member
Activity: 77
Merit: 10
https://en.bitcoin.it/wiki/OP_CHECKSIG

Hope this helps, good luck with your implementation, look forward to seeing it.
Activity: -
Merit: -
This is one of my final major roadblocks I need to get past for my bitcoin implementation, and I'm having a hard time understanding everything that's going on in Satoshi's code, and haven't found any other implementations of bitcoin scripting, yet.  A couple weeks ago on IRC, ArtForz explained some of the scripting, but we didn't get into much detail about OP_CHECKSIG.  It was mentioned, however, that it creates a new transaction containing a subset of inputs/outputs, and that new transaction is then hashed.

Can/will anyone please explain this in further detail?

I created a link to a page solely about OP_CHECKSIG on the wiki, if anyone wants to add an explanation there: https://en.bitcoin.it/w/index.php?title=OP_CHECKSIG&action=edit&redlink=1

Thanks!
Pages:
Jump to: