github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/sig64/sigcompress.go (about) 1 package sig64 2 3 import "fmt" 4 5 // signatures are like 71 or 70 bytes, variable length... this really bugs me! 6 // But I've lived with it. But with this, the (txid, sig) pair is slightly over 7 // 100 bytes, so that bugs me even more, because it'd be really nice to have the 8 // state data be exactly 100 bytes. So these functions "compress" the signatures 9 // into 65 bytes, and restore back into the ~71 byte normal length. 10 11 func SigCompress(sig []byte) (csig [64]byte, err error) { 12 if len(sig) < 65 || len(sig) > 72 { 13 err = fmt.Errorf("Can't compress; sig length is %d", len(sig)) 14 return 15 } 16 if sig[0] != 0x30 { 17 err = fmt.Errorf("Can't compress; sig starts with %x instead of 30", sig[0]) 18 return 19 } 20 21 // on the web it says sigs can be 72 or even 73 bytes, which I guess means that 22 // s can also be 33 bytes? But I've never seen it. Maybe 73 is from the 23 // sighash byte at the end? Seems like 65 is enough. 24 25 var r [32]byte 26 var s [32]byte 27 28 // pop off first byte of signature which is always 30 29 sig = sig[1:] 30 31 // check reported length vs actual length 32 if int(sig[0]) != len(sig)-1 { 33 err = fmt.Errorf("length byte is %x (%d) but rest is %d bytes long", 34 sig[0], sig[0], len(sig)-1) 35 } 36 // pop off another byte (the length byte) 37 sig = sig[1:] 38 39 // 0x02 here just for fun 40 if sig[0] != 0x02 { 41 err = fmt.Errorf("should have an 0x02 byte, %x instead", sig[0]) 42 return 43 } 44 // and pop off that 45 sig = sig[1:] 46 47 // get length of R 48 rlen := sig[0] 49 // pop that off 50 sig = sig[1:] 51 // check rlen 52 if rlen < 22 || rlen > 33 { 53 err = fmt.Errorf("%d byte r is too long", rlen) 54 return 55 } 56 if int(rlen) > len(sig) { 57 err = fmt.Errorf("length of r value %d but only %d bytes left ", 58 rlen, len(sig)) 59 } 60 if rlen == 33 { //drop 0 byte if rlen is 33 61 sig = sig[1:] 62 rlen = 32 63 } 64 // copy r, leaving 0s at the MSB 65 copy(r[32-rlen:], sig[:rlen]) 66 // pop off r 67 sig = sig[rlen:] 68 69 // 0x02 again, just for fun 70 if sig[0] != 0x02 { 71 err = fmt.Errorf("should have an 0x02 byte, %x instead", sig[0]) 72 return 73 } 74 // and pop off that 75 sig = sig[1:] 76 77 // get length of s 78 slen := sig[0] 79 // pop that off 80 sig = sig[1:] 81 // check slen 82 if slen < 22 || slen > 33 { 83 err = fmt.Errorf("%d byte s is too long", slen) 84 return 85 } 86 if int(slen) > len(sig) { 87 err = fmt.Errorf("length of s value %d but only %d bytes left ", 88 slen, len(sig)) 89 } 90 if slen == 33 { //drop 0 byte if slen is 33 91 sig = sig[1:] 92 slen = 32 93 } 94 // copy s, leaving 0s at the MSB 95 copy(s[32-slen:], sig[:slen]) 96 // we're done with sig 97 // serialize compressed sig as r, s 98 copy(csig[0:32], r[:]) 99 copy(csig[32:64], s[:]) 100 101 return 102 } 103 104 /* 105 3045 0221 00b7cfe9d300b30f9705633c3b031f8312a189dde2be5aad2e28d73aa617d8ad42 0220 4ff09fd52705fee8733129466e9da417c17b99496360a9a202172b92b8bc78ef 106 3044 0220 77bd60f213f867e44c85810ebd69e0cf365cf2f20d45264d017b9dde366836d8 0220 00cf16a67d3ca7eee2297e7720e3c077a0a48a7dbbc649bea73d436e2f8c2af9 107 3045 0221 00bb6300be5526b13f901532c29ce9609e944c1124b13c96f86dd096ac50bafbea 0220 12d39d7a72ea859bd8d31e0a7ea96e2307da100d6ff9c86ab2a83cd17a8ef222 108 3045 0221 00e9dd01c5cf1b0fbb80af1949def0b226a232acace2a744a01fea73d4897bea9c 0220 526976d608f704e570687dc410edc1c885030ca3aa71f646590e1f0f482fc146 109 3045 0221 00b4053184157f00bdbf1ff67e411197dd0a46cf410c4abc0d8ea8c3155b0afec7 0220 425ddfe133ee43c3edb99834054db6d46b09b613ec3fea59dc35780fbd9ace72 110 3044 0220 6048246c95429555d265472d936b71e728f468a84412f9423941b4b9cbbab2f0 0220 4eb1bf82879c72adc3390a638a221792adecf74a097de9bd1257b5bc3e17a407 111 3045 0221 00b88e7a9137efe437cae4f3dd5e0d05bdf9cf519c10c36d2f657d6bbb0906a50f 0220 41c95b40dc5423864022f5d110a810c50c1dd72c4b679da75e0134f4f5903609 112 3044 0220 20797760653290231de963a89154a3977685357c2868ae0fb0d241522b62a5c2 0220 211c56e794bf8f04624898094cb4f6beaeff3055bede0c0e5be9cc78b17def22 113 3044 0220 7652fbfc921747befbcb4193a13b469ddecb767316f1470a01717d758666221f 0220 32131428c3801fd6fa7038b451e7adb4db281e7b38414a8cbc4c604c51574df5 114 115 3045 0220 59f28edc62e4b744ff7097717b7d4701614e4af6a30dfa2081ef3e8e27924184 0221 008279ca7eb40a4bd04c923b96110b00d472d648c67df09ad39945130b8f7e4dc8 116 117 3044 0220 3af596f8fbeed4c1e6222aecda133c229708c6982c6c98b69a3820331c64d3e0 0220 4f853d4ecea9c7ff0f30fd8e7b47ceddcc0ab2a4d49271062d4e63cc4181354f 118 119 3044 0220 57a56687d15830950a8b2b8c89507815d9bbd19d85497f5e68277f03eecb9262 0220 07c74cbb0491adc8bcc1d8dc13286eb5ec54925c582a6bce2b5743e2ccf69750 120 121 3045022059f28edc62e4b744ff7097717b7d4701614e4af6a30dfa2081ef3e8e279241840221008279ca7eb40a4bd04c923b96110b00d472d648c67df09ad39945130b8f7e4dc8 122 304402206048246c95429555d265472d936b71e728f468a84412f9423941b4b9cbbab2f002204eb1bf82879c72adc3390a638a221792adecf74a097de9bd1257b5bc3e17a407 123 3045022100b88e7a9137efe437cae4f3dd5e0d05bdf9cf519c10c36d2f657d6bbb0906a50f022041c95b40dc5423864022f5d110a810c50c1dd72c4b679da75e0134f4f5903609 124 125 */ 126 127 func SigDecompress(csig [64]byte) (sig []byte) { 128 // this never fails, which is nicer eh? 129 130 // check the beginning of r for 0s. weird padding. 131 rlen := 33 132 // chop down to 32 if msb is not set 133 if csig[0]&0x80 == 0 { 134 rlen-- 135 } 136 // keep chopping down as needed 137 i := 0 138 for rlen > 1 && csig[i] == 0 && csig[i+1]&0x80 == 0 { 139 rlen-- 140 i++ 141 } 142 padr := make([]byte, rlen) 143 copy(padr[rlen-(32-i):], csig[i:]) 144 145 // same with s. 146 slen := 33 147 // chop down to 32 if msb is not set 148 if csig[32]&0x80 == 0 { 149 slen-- 150 } 151 // keep chopping down as needed 152 i = 32 153 for slen > 1 && csig[i] == 0 && csig[i+1]&0x80 == 0 { 154 slen-- 155 i++ 156 } 157 pads := make([]byte, slen) 158 copy(pads[slen-(64-i):], csig[i:]) 159 160 fulllen := byte(len(padr) + len(pads) + 6) 161 sig = make([]byte, fulllen) 162 sig[0] = 0x30 163 sig[1] = fulllen - 2 // the 0x30, and this byte itself 164 sig[2] = 0x02 165 sig[3] = byte(len(padr)) 166 // got this copy / offset trick from koblitz/signature.go 167 endr := copy(sig[4:], padr) + 4 168 sig[endr] = 0x02 169 sig[endr+1] = byte(len(pads)) 170 copy(sig[endr+2:], pads) 171 172 return 173 }