├── LICENSE ├── README ├── bitecdsa ├── bitecdsa.go └── bitecdsa_test.go └── bitelliptic ├── bitelliptic.go └── bitelliptic_test.go /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | Copyright (c) 2011 ThePiachu. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | * The name of ThePiachu may not be used to endorse or promote products 18 | derived from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a modified ECDSA library for Google Go language. 2 | It is based on original code created by The Go Authors, modified to handle Koblitz curves (such as secp256k1 that is commonly used by Bitcoin applications). 3 | 4 | For more information on Koblitz curves, check out this link: 5 | http://www.secg.org/collateral/sec2_final.pdf 6 | 7 | For more information on Bitcoins, check out this link: 8 | http://bitcoin.org/ 9 | 10 | Code status: 11 | -The code is a beta version, it should work correctly, but it has not yet been thoroughly tested. 12 | 13 | TODO: 14 | -Add more test cases 15 | -Verify library's proper functionality on sample curves 16 | -Test library in an actual application 17 | -Verify copyright notices and other comments in the code -------------------------------------------------------------------------------- /bitecdsa/bitecdsa.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Copyright 2011 ThePiachu. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as 7 | // defined in FIPS 186-3. 8 | package bitecdsa 9 | 10 | // References: 11 | // [NSA]: Suite B implementor's guide to FIPS 186-3, 12 | // http://www.nsa.gov/ia/_files/ecdsa.pdf 13 | // [SECG]: SECG, SEC1 14 | // http://www.secg.org/download/aid-780/sec1-v2.pdf 15 | 16 | import ( 17 | "big" 18 | "bitelliptic" 19 | "io" 20 | "os" 21 | ) 22 | 23 | // PublicKey represents an ECDSA public key. 24 | type PublicKey struct { 25 | *bitelliptic.BitCurve 26 | X, Y *big.Int 27 | } 28 | 29 | // PrivateKey represents a ECDSA private key. 30 | type PrivateKey struct { 31 | PublicKey 32 | D *big.Int 33 | } 34 | 35 | var one = new(big.Int).SetInt64(1) 36 | 37 | // randFieldElement returns a random element of the field underlying the given 38 | // curve using the procedure given in [NSA] A.2.1. 39 | func randFieldElement(c *bitelliptic.BitCurve, rand io.Reader) (k *big.Int, err os.Error) { 40 | b := make([]byte, c.BitSize/8+8) 41 | _, err = io.ReadFull(rand, b) 42 | if err != nil { 43 | return 44 | } 45 | 46 | k = new(big.Int).SetBytes(b) 47 | n := new(big.Int).Sub(c.N, one) 48 | k.Mod(k, n) 49 | k.Add(k, one) 50 | return 51 | } 52 | 53 | // GenerateKey generates a public&private key pair. 54 | func GenerateKey(c *bitelliptic.BitCurve, rand io.Reader) (priv *PrivateKey, err os.Error) { 55 | k, err := randFieldElement(c, rand) 56 | if err != nil { 57 | return 58 | } 59 | 60 | priv = new(PrivateKey) 61 | priv.PublicKey.BitCurve = c 62 | priv.D = k 63 | priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) 64 | return 65 | } 66 | 67 | // hashToInt converts a hash value to an integer. There is some disagreement 68 | // about how this is done. [NSA] suggests that this is done in the obvious 69 | // manner, but [SECG] truncates the hash to the bit-length of the curve order 70 | // first. We follow [SECG] because that's what OpenSSL does. 71 | func hashToInt(hash []byte, c *bitelliptic.BitCurve) *big.Int { 72 | orderBits := c.N.BitLen() 73 | orderBytes := (orderBits + 7) / 8 74 | if len(hash) > orderBytes { 75 | hash = hash[:orderBytes] 76 | } 77 | 78 | ret := new(big.Int).SetBytes(hash) 79 | excess := orderBytes*8 - orderBits 80 | if excess > 0 { 81 | ret.Rsh(ret, uint(excess)) 82 | } 83 | return ret 84 | } 85 | 86 | // Sign signs an arbitrary length hash (which should be the result of hashing a 87 | // larger message) using the private key, priv. It returns the signature as a 88 | // pair of integers. The security of the private key depends on the entropy of 89 | // rand. 90 | func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.Error) { 91 | // See [NSA] 3.4.1 92 | c := priv.PublicKey.BitCurve 93 | 94 | var k, kInv *big.Int 95 | for { 96 | for { 97 | k, err = randFieldElement(c, rand) 98 | if err != nil { 99 | r = nil 100 | return 101 | } 102 | 103 | kInv = new(big.Int).ModInverse(k, c.N) 104 | r, _ = priv.BitCurve.ScalarBaseMult(k.Bytes()) 105 | r.Mod(r, priv.BitCurve.N) 106 | if r.Sign() != 0 { 107 | break 108 | } 109 | } 110 | 111 | e := hashToInt(hash, c) 112 | s = new(big.Int).Mul(priv.D, r) 113 | s.Add(s, e) 114 | s.Mul(s, kInv) 115 | s.Mod(s, priv.PublicKey.BitCurve.N) 116 | if s.Sign() != 0 { 117 | break 118 | } 119 | } 120 | 121 | return 122 | } 123 | 124 | // Verify verifies the signature in r, s of hash using the public key, pub. It 125 | // returns true iff the signature is valid. 126 | func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { 127 | // See [NSA] 3.4.2 128 | c := pub.BitCurve 129 | 130 | if r.Sign() == 0 || s.Sign() == 0 { 131 | return false 132 | } 133 | if r.Cmp(c.N) >= 0 || s.Cmp(c.N) >= 0 { 134 | return false 135 | } 136 | e := hashToInt(hash, c) 137 | w := new(big.Int).ModInverse(s, c.N) 138 | 139 | u1 := e.Mul(e, w) 140 | u2 := w.Mul(r, w) 141 | 142 | x1, y1 := c.ScalarBaseMult(u1.Bytes()) 143 | x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes()) 144 | if x1.Cmp(x2) == 0 { 145 | return false 146 | } 147 | x, _ := c.Add(x1, y1, x2, y2) 148 | x.Mod(x, c.N) 149 | return x.Cmp(r) == 0 150 | } 151 | -------------------------------------------------------------------------------- /bitecdsa/bitecdsa_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Copyright 2011 ThePiachu. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package bitecdsa 7 | 8 | import ( 9 | "big" 10 | "bitelliptic" 11 | "crypto/sha1" 12 | "crypto/rand" 13 | "encoding/hex" 14 | "testing" 15 | ) 16 | 17 | func testKeyGeneration(t *testing.T, c *bitelliptic.BitCurve, tag string) { 18 | priv, err := GenerateKey(c, rand.Reader) 19 | if err != nil { 20 | t.Errorf("%s: error: %s", tag, err) 21 | return 22 | } 23 | if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) { 24 | t.Errorf("%s: public key invalid: %s", tag, err) 25 | } 26 | } 27 | 28 | func TestKeyGeneration(t *testing.T) { 29 | testKeyGeneration(t, bitelliptic.S256(), "S256") 30 | if testing.Short() { 31 | return 32 | } 33 | testKeyGeneration(t, bitelliptic.S160(), "S160") 34 | testKeyGeneration(t, bitelliptic.S192(), "S192") 35 | testKeyGeneration(t, bitelliptic.S224(), "S224") 36 | } 37 | 38 | func testSignAndVerify(t *testing.T, c *bitelliptic.BitCurve, tag string) { 39 | priv, _ := GenerateKey(c, rand.Reader) 40 | 41 | hashed := []byte("testing") 42 | r, s, err := Sign(rand.Reader, priv, hashed) 43 | if err != nil { 44 | t.Errorf("%s: error signing: %s", tag, err) 45 | return 46 | } 47 | 48 | if !Verify(&priv.PublicKey, hashed, r, s) { 49 | t.Errorf("%s: Verify failed", tag) 50 | } 51 | 52 | hashed[0] ^= 0xff 53 | if Verify(&priv.PublicKey, hashed, r, s) { 54 | t.Errorf("%s: Verify always works!", tag) 55 | } 56 | } 57 | 58 | func TestSignAndVerify(t *testing.T) { 59 | testSignAndVerify(t, bitelliptic.S256(), "S256") 60 | if testing.Short() { 61 | return 62 | } 63 | testSignAndVerify(t, bitelliptic.S160(), "S160") 64 | testSignAndVerify(t, bitelliptic.S192(), "S192") 65 | testSignAndVerify(t, bitelliptic.S224(), "S224") 66 | } 67 | 68 | func fromHex(s string) *big.Int { 69 | r, ok := new(big.Int).SetString(s, 16) 70 | if !ok { 71 | panic("bad hex") 72 | } 73 | return r 74 | } 75 | 76 | // These test vectors were taken from 77 | // http://csrc.nist.gov/groups/STM/cavp/documents/dss/ecdsatestvectors.zip 78 | var testVectors = []struct { 79 | msg string 80 | Qx, Qy string 81 | r, s string 82 | ok bool 83 | }{ 84 | { 85 | "09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd", 86 | "9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40", 87 | "03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed", 88 | "81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1", 89 | "96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5", 90 | false, 91 | }, 92 | { 93 | "96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37", 94 | "851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8", 95 | "205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2", 96 | "4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0", 97 | "e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12", 98 | false, 99 | }, 100 | { 101 | "86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e", 102 | "ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc", 103 | "c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984", 104 | "de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9", 105 | "745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd", 106 | true, 107 | }, 108 | { 109 | "4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d", 110 | "cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8", 111 | "a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a", 112 | "67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836", 113 | "1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020", 114 | false, 115 | }, 116 | { 117 | "bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e", 118 | "6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855", 119 | "27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84", 120 | "e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f", 121 | "1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9", 122 | false, 123 | }, 124 | { 125 | "7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43", 126 | "9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1", 127 | "8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066", 128 | "6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54", 129 | "8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57", 130 | false, 131 | }, 132 | { 133 | "cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601", 134 | "a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4", 135 | "e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5", 136 | "387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1", 137 | "4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4", 138 | false, 139 | }, 140 | { 141 | "26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866", 142 | "9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d", 143 | "15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c", 144 | "929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0", 145 | "59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872", 146 | true, 147 | }, 148 | { 149 | "1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e", 150 | "d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b", 151 | "631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f", 152 | "65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129", 153 | "bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a", 154 | false, 155 | }, 156 | { 157 | "919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b", 158 | "269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574", 159 | "baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57", 160 | "cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008", 161 | "40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40", 162 | false, 163 | }, 164 | { 165 | "6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f", 166 | "6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd", 167 | "26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b", 168 | "9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad", 169 | "8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97", 170 | true, 171 | }, 172 | { 173 | "bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566", 174 | "14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40", 175 | "b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803", 176 | "4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145", 177 | "452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8", 178 | false, 179 | }, 180 | { 181 | "0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770", 182 | "d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac", 183 | "76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb", 184 | "bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca", 185 | "9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e", 186 | false, 187 | }, 188 | { 189 | "5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92", 190 | "7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6", 191 | "44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9", 192 | "084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8", 193 | "079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3", 194 | false, 195 | }, 196 | { 197 | "1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845", 198 | "31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493", 199 | "a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4", 200 | "bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c", 201 | "ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0", 202 | false, 203 | }, 204 | } 205 | 206 | func TestVectors(t *testing.T) { 207 | sha := sha1.New() 208 | 209 | for i, test := range testVectors { 210 | pub := PublicKey{ 211 | BitCurve: bitelliptic.S256(), 212 | X: fromHex(test.Qx), 213 | Y: fromHex(test.Qy), 214 | } 215 | msg, _ := hex.DecodeString(test.msg) 216 | sha.Reset() 217 | sha.Write(msg) 218 | hashed := sha.Sum() 219 | r := fromHex(test.r) 220 | s := fromHex(test.s) 221 | if Verify(&pub, hashed, r, s) != test.ok { 222 | t.Errorf("%d: bad result", i) 223 | } 224 | if testing.Short() { 225 | break 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /bitelliptic/bitelliptic.go: -------------------------------------------------------------------------------- 1 | package bitelliptic 2 | 3 | // Copyright 2010 The Go Authors. All rights reserved. 4 | // Copyright 2011 ThePiachu. All rights reserved. 5 | // Use of this source code is governed by a BSD-style 6 | // license that can be found in the LICENSE file. 7 | 8 | // Package bitelliptic implements several Koblitz elliptic curves over prime 9 | // fields. 10 | 11 | // This package operates, internally, on Jacobian coordinates. For a given 12 | // (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1) 13 | // where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole 14 | // calculation can be performed within the transform (as in ScalarMult and 15 | // ScalarBaseMult). But even for Add and Double, it's faster to apply and 16 | // reverse the transform than to operate in affine coordinates. 17 | 18 | import ( 19 | "big" 20 | "io" 21 | "os" 22 | "sync" 23 | ) 24 | 25 | // A BitCurve represents a Koblitz Curve with a=0. 26 | // See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html 27 | type BitCurve struct { 28 | P *big.Int // the order of the underlying field 29 | N *big.Int // the order of the base point 30 | B *big.Int // the constant of the BitCurve equation 31 | Gx, Gy *big.Int // (x,y) of the base point 32 | BitSize int // the size of the underlying field 33 | } 34 | 35 | // IsOnBitCurve returns true if the given (x,y) lies on the BitCurve. 36 | func (BitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool { 37 | // y² = x³ + b 38 | y2 := new(big.Int).Mul(y, y)//y² 39 | y2.Mod(y2, BitCurve.P)//y²%P 40 | 41 | x3 := new(big.Int).Mul(x, x)//x² 42 | x3.Mul(x3, x)//x³ 43 | 44 | x3.Add(x3, BitCurve.B)//x³+B 45 | x3.Mod(x3, BitCurve.P)//(x³+B)%P 46 | 47 | return x3.Cmp(y2) == 0 48 | } 49 | 50 | //TODO: double check if the function is okay 51 | // affineFromJacobian reverses the Jacobian transform. See the comment at the 52 | // top of the file. 53 | func (BitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) { 54 | zinv := new(big.Int).ModInverse(z, BitCurve.P) 55 | zinvsq := new(big.Int).Mul(zinv, zinv) 56 | 57 | xOut = new(big.Int).Mul(x, zinvsq) 58 | xOut.Mod(xOut, BitCurve.P) 59 | zinvsq.Mul(zinvsq, zinv) 60 | yOut = new(big.Int).Mul(y, zinvsq) 61 | yOut.Mod(yOut, BitCurve.P) 62 | return 63 | } 64 | 65 | // Add returns the sum of (x1,y1) and (x2,y2) 66 | func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { 67 | z := new(big.Int).SetInt64(1) 68 | return BitCurve.affineFromJacobian(BitCurve.addJacobian(x1, y1, z, x2, y2, z)) 69 | } 70 | 71 | // addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and 72 | // (x2, y2, z2) and returns their sum, also in Jacobian form. 73 | func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { 74 | // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl 75 | z1z1 := new(big.Int).Mul(z1, z1) 76 | z1z1.Mod(z1z1, BitCurve.P) 77 | z2z2 := new(big.Int).Mul(z2, z2) 78 | z2z2.Mod(z2z2, BitCurve.P) 79 | 80 | u1 := new(big.Int).Mul(x1, z2z2) 81 | u1.Mod(u1, BitCurve.P) 82 | u2 := new(big.Int).Mul(x2, z1z1) 83 | u2.Mod(u2, BitCurve.P) 84 | h := new(big.Int).Sub(u2, u1) 85 | if h.Sign() == -1 { 86 | h.Add(h, BitCurve.P) 87 | } 88 | i := new(big.Int).Lsh(h, 1) 89 | i.Mul(i, i) 90 | j := new(big.Int).Mul(h, i) 91 | 92 | s1 := new(big.Int).Mul(y1, z2) 93 | s1.Mul(s1, z2z2) 94 | s1.Mod(s1, BitCurve.P) 95 | s2 := new(big.Int).Mul(y2, z1) 96 | s2.Mul(s2, z1z1) 97 | s2.Mod(s2, BitCurve.P) 98 | r := new(big.Int).Sub(s2, s1) 99 | if r.Sign() == -1 { 100 | r.Add(r, BitCurve.P) 101 | } 102 | r.Lsh(r, 1) 103 | v := new(big.Int).Mul(u1, i) 104 | 105 | x3 := new(big.Int).Set(r) 106 | x3.Mul(x3, x3) 107 | x3.Sub(x3, j) 108 | x3.Sub(x3, v) 109 | x3.Sub(x3, v) 110 | x3.Mod(x3, BitCurve.P) 111 | 112 | y3 := new(big.Int).Set(r) 113 | v.Sub(v, x3) 114 | y3.Mul(y3, v) 115 | s1.Mul(s1, j) 116 | s1.Lsh(s1, 1) 117 | y3.Sub(y3, s1) 118 | y3.Mod(y3, BitCurve.P) 119 | 120 | z3 := new(big.Int).Add(z1, z2) 121 | z3.Mul(z3, z3) 122 | z3.Sub(z3, z1z1) 123 | if z3.Sign() == -1 { 124 | z3.Add(z3, BitCurve.P) 125 | } 126 | z3.Sub(z3, z2z2) 127 | if z3.Sign() == -1 { 128 | z3.Add(z3, BitCurve.P) 129 | } 130 | z3.Mul(z3, h) 131 | z3.Mod(z3, BitCurve.P) 132 | 133 | return x3, y3, z3 134 | } 135 | 136 | // Double returns 2*(x,y) 137 | func (BitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { 138 | z1 := new(big.Int).SetInt64(1) 139 | return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z1)) 140 | } 141 | 142 | // doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and 143 | // returns its double, also in Jacobian form. 144 | func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { 145 | // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l 146 | 147 | a := new(big.Int).Mul(x, x)//X1² 148 | b := new(big.Int).Mul(y, y)//Y1² 149 | c := new(big.Int).Mul(b, b)//B² 150 | 151 | d := new(big.Int).Add(x, b)//X1+B 152 | d.Mul(d, d)//(X1+B)² 153 | d.Sub(d, a)//(X1+B)²-A 154 | d.Sub(d, c)//(X1+B)²-A-C 155 | d.Mul(d, big.NewInt(2))//2*((X1+B)²-A-C) 156 | 157 | e := new(big.Int).Mul(big.NewInt(3), a)//3*A 158 | f := new(big.Int).Mul(e, e)//E² 159 | 160 | x3 := new(big.Int).Mul(big.NewInt(2), d)//2*D 161 | x3.Sub(f, x3)//F-2*D 162 | x3.Mod(x3, BitCurve.P) 163 | 164 | y3 := new(big.Int).Sub(d, x3)//D-X3 165 | y3.Mul(e, y3)//E*(D-X3) 166 | y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c))//E*(D-X3)-8*C 167 | y3.Mod(y3, BitCurve.P) 168 | 169 | z3 := new(big.Int).Mul(y, z)//Y1*Z1 170 | z3.Mul(big.NewInt(2), z3) //3*Y1*Z1 171 | z3.Mod(z3, BitCurve.P) 172 | 173 | return x3, y3, z3 174 | } 175 | 176 | //TODO: double check if it is okay 177 | // ScalarMult returns k*(Bx,By) where k is a number in big-endian form. 178 | func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { 179 | // We have a slight problem in that the identity of the group (the 180 | // point at infinity) cannot be represented in (x, y) form on a finite 181 | // machine. Thus the standard add/double algorithm has to be tweaked 182 | // slightly: our initial state is not the identity, but x, and we 183 | // ignore the first true bit in |k|. If we don't find any true bits in 184 | // |k|, then we return nil, nil, because we cannot return the identity 185 | // element. 186 | 187 | Bz := new(big.Int).SetInt64(1) 188 | x := Bx 189 | y := By 190 | z := Bz 191 | 192 | seenFirstTrue := false 193 | for _, byte := range k { 194 | for bitNum := 0; bitNum < 8; bitNum++ { 195 | if seenFirstTrue { 196 | x, y, z = BitCurve.doubleJacobian(x, y, z) 197 | } 198 | if byte&0x80 == 0x80 { 199 | if !seenFirstTrue { 200 | seenFirstTrue = true 201 | } else { 202 | x, y, z = BitCurve.addJacobian(Bx, By, Bz, x, y, z) 203 | } 204 | } 205 | byte <<= 1 206 | } 207 | } 208 | 209 | if !seenFirstTrue { 210 | return nil, nil 211 | } 212 | 213 | return BitCurve.affineFromJacobian(x, y, z) 214 | } 215 | 216 | // ScalarBaseMult returns k*G, where G is the base point of the group and k is 217 | // an integer in big-endian form. 218 | func (BitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { 219 | return BitCurve.ScalarMult(BitCurve.Gx, BitCurve.Gy, k) 220 | } 221 | 222 | var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f} 223 | 224 | //TODO: double check if it is okay 225 | // GenerateKey returns a public/private key pair. The private key is generated 226 | // using the given reader, which must return random data. 227 | func (BitCurve *BitCurve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err os.Error) { 228 | byteLen := (BitCurve.BitSize + 7) >> 3 229 | priv = make([]byte, byteLen) 230 | 231 | for x == nil { 232 | _, err = io.ReadFull(rand, priv) 233 | if err != nil { 234 | return 235 | } 236 | // We have to mask off any excess bits in the case that the size of the 237 | // underlying field is not a whole number of bytes. 238 | priv[0] &= mask[BitCurve.BitSize%8] 239 | // This is because, in tests, rand will return all zeros and we don't 240 | // want to get the point at infinity and loop forever. 241 | priv[1] ^= 0x42 242 | x, y = BitCurve.ScalarBaseMult(priv) 243 | } 244 | return 245 | } 246 | 247 | // Marshal converts a point into the form specified in section 4.3.6 of ANSI 248 | // X9.62. 249 | func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte { 250 | byteLen := (BitCurve.BitSize + 7) >> 3 251 | 252 | ret := make([]byte, 1+2*byteLen) 253 | ret[0] = 4 // uncompressed point 254 | 255 | xBytes := x.Bytes() 256 | copy(ret[1+byteLen-len(xBytes):], xBytes) 257 | yBytes := y.Bytes() 258 | copy(ret[1+2*byteLen-len(yBytes):], yBytes) 259 | return ret 260 | } 261 | 262 | // Unmarshal converts a point, serialised by Marshal, into an x, y pair. On 263 | // error, x = nil. 264 | func (BitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) { 265 | byteLen := (BitCurve.BitSize + 7) >> 3 266 | if len(data) != 1+2*byteLen { 267 | return 268 | } 269 | if data[0] != 4 { // uncompressed form 270 | return 271 | } 272 | x = new(big.Int).SetBytes(data[1 : 1+byteLen]) 273 | y = new(big.Int).SetBytes(data[1+byteLen:]) 274 | return 275 | } 276 | 277 | //curve parameters taken from: 278 | //http://www.secg.org/collateral/sec2_final.pdf 279 | 280 | var initonce sync.Once 281 | var secp160k1 *BitCurve 282 | var secp192k1 *BitCurve 283 | var secp224k1 *BitCurve 284 | var secp256k1 *BitCurve 285 | 286 | func initAll() { 287 | initS160() 288 | initS192() 289 | initS224() 290 | initS256() 291 | } 292 | 293 | func initS160() { 294 | // See SEC 2 section 2.4.1 295 | secp160k1 = new(BitCurve) 296 | secp160k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", 16) 297 | secp160k1.N, _ = new(big.Int).SetString("0100000000000000000001B8FA16DFAB9ACA16B6B3", 16) 298 | secp160k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000007", 16) 299 | secp160k1.Gx, _ = new(big.Int).SetString("3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", 16) 300 | secp160k1.Gy, _ = new(big.Int).SetString("938CF935318FDCED6BC28286531733C3F03C4FEE", 16) 301 | secp160k1.BitSize = 160 302 | } 303 | 304 | func initS192() { 305 | // See SEC 2 section 2.5.1 306 | secp192k1 = new(BitCurve) 307 | secp192k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", 16) 308 | secp192k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 16) 309 | secp192k1.B, _ = new(big.Int).SetString("000000000000000000000000000000000000000000000003", 16) 310 | secp192k1.Gx, _ = new(big.Int).SetString("DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", 16) 311 | secp192k1.Gy, _ = new(big.Int).SetString("9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", 16) 312 | secp192k1.BitSize = 192 313 | } 314 | 315 | func initS224() { 316 | // See SEC 2 section 2.6.1 317 | secp224k1 = new(BitCurve) 318 | secp224k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", 16) 319 | secp224k1.N, _ = new(big.Int).SetString("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 16) 320 | secp224k1.B, _ = new(big.Int).SetString("00000000000000000000000000000000000000000000000000000005", 16) 321 | secp224k1.Gx, _ = new(big.Int).SetString("A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", 16) 322 | secp224k1.Gy, _ = new(big.Int).SetString("7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", 16) 323 | secp224k1.BitSize = 224 324 | } 325 | 326 | func initS256() { 327 | // See SEC 2 section 2.7.1 328 | secp256k1 = new(BitCurve) 329 | secp256k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16) 330 | secp256k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16) 331 | secp256k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16) 332 | secp256k1.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16) 333 | secp256k1.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16) 334 | secp256k1.BitSize = 256 335 | } 336 | 337 | // S160 returns a BitCurve which implements secp160k1 (see SEC 2 section 2.4.1) 338 | func S160() *BitCurve { 339 | initonce.Do(initAll) 340 | return secp160k1 341 | } 342 | 343 | // S192 returns a BitCurve which implements secp192k1 (see SEC 2 section 2.5.1) 344 | func S192() *BitCurve { 345 | initonce.Do(initAll) 346 | return secp192k1 347 | } 348 | 349 | // S224 returns a BitCurve which implements secp224k1 (see SEC 2 section 2.6.1) 350 | func S224() *BitCurve { 351 | initonce.Do(initAll) 352 | return secp224k1 353 | } 354 | 355 | // S256 returns a BitCurve which implements secp256k1 (see SEC 2 section 2.7.1) 356 | func S256() *BitCurve { 357 | initonce.Do(initAll) 358 | return secp256k1 359 | } -------------------------------------------------------------------------------- /bitelliptic/bitelliptic_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Copyright 2011 ThePiachu. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package bitelliptic 7 | 8 | import ( 9 | "big" 10 | "crypto/rand" 11 | "fmt" 12 | "testing" 13 | ) 14 | 15 | func TestOnCurve(t *testing.T) { 16 | s160 := S160() 17 | if !s160.IsOnCurve(s160.Gx, s160.Gy) { 18 | t.Errorf("FAIL S160") 19 | } 20 | s192 := S192() 21 | if !s192.IsOnCurve(s192.Gx, s192.Gy) { 22 | t.Errorf("FAIL S192") 23 | } 24 | s224 := S224() 25 | if !s224.IsOnCurve(s224.Gx, s224.Gy) { 26 | t.Errorf("FAIL S224") 27 | } 28 | s256 := S256() 29 | if !s256.IsOnCurve(s256.Gx, s256.Gy) { 30 | t.Errorf("FAIL S256") 31 | } 32 | } 33 | 34 | type baseMultTest struct { 35 | k string 36 | x, y string 37 | } 38 | //TODO: add more test vectors 39 | var s256BaseMultTests = []baseMultTest{ 40 | { 41 | "AA5E28D6A97A2479A65527F7290311A3624D4CC0FA1578598EE3C2613BF99522", 42 | "34F9460F0E4F08393D192B3C5133A6BA099AA0AD9FD54EBCCFACDFA239FF49C6", 43 | "B71EA9BD730FD8923F6D25A7A91E7DD7728A960686CB5A901BB419E0F2CA232", 44 | }, 45 | { 46 | "7E2B897B8CEBC6361663AD410835639826D590F393D90A9538881735256DFAE3", 47 | "D74BF844B0862475103D96A611CF2D898447E288D34B360BC885CB8CE7C00575", 48 | "131C670D414C4546B88AC3FF664611B1C38CEB1C21D76369D7A7A0969D61D97D", 49 | }, 50 | { 51 | "6461E6DF0FE7DFD05329F41BF771B86578143D4DD1F7866FB4CA7E97C5FA945D", 52 | "E8AECC370AEDD953483719A116711963CE201AC3EB21D3F3257BB48668C6A72F", 53 | "C25CAF2F0EBA1DDB2F0F3F47866299EF907867B7D27E95B3873BF98397B24EE1", 54 | }, 55 | { 56 | "376A3A2CDCD12581EFFF13EE4AD44C4044B8A0524C42422A7E1E181E4DEECCEC", 57 | "14890E61FCD4B0BD92E5B36C81372CA6FED471EF3AA60A3E415EE4FE987DABA1", 58 | "297B858D9F752AB42D3BCA67EE0EB6DCD1C2B7B0DBE23397E66ADC272263F982", 59 | }, 60 | { 61 | "1B22644A7BE026548810C378D0B2994EEFA6D2B9881803CB02CEFF865287D1B9", 62 | "F73C65EAD01C5126F28F442D087689BFA08E12763E0CEC1D35B01751FD735ED3", 63 | "F449A8376906482A84ED01479BD18882B919C140D638307F0C0934BA12590BDE", 64 | }, 65 | } 66 | 67 | //TODO: test different curves as well? 68 | func TestBaseMult(t *testing.T) { 69 | s256 := S256() 70 | for i, e := range s256BaseMultTests { 71 | k, ok := new(big.Int).SetString(e.k, 16) 72 | if !ok { 73 | t.Errorf("%d: bad value for k: %s", i, e.k) 74 | } 75 | x, y := s256.ScalarBaseMult(k.Bytes()) 76 | if fmt.Sprintf("%X", x) != e.x || fmt.Sprintf("%X", y) != e.y { 77 | t.Errorf("%d: bad output for k=%s: got (%X, %X), want (%s, %s)", i, e.k, x, y, e.x, e.y) 78 | } 79 | if testing.Short() && i > 5 { 80 | break 81 | } 82 | } 83 | } 84 | 85 | //TODO: test more curves? 86 | func BenchmarkBaseMult(b *testing.B) { 87 | b.ResetTimer() 88 | s256 := S224() 89 | e := s256BaseMultTests[0]//TODO: check, used to be 25 instead of 0, but it's probably ok 90 | k, _ := new(big.Int).SetString(e.k, 16) 91 | b.StartTimer() 92 | for i := 0; i < b.N; i++ { 93 | s256.ScalarBaseMult(k.Bytes()) 94 | } 95 | } 96 | 97 | //TODO: test more curves? 98 | func TestMarshal(t *testing.T) { 99 | s256 := S256() 100 | _, x, y, err := s256.GenerateKey(rand.Reader) 101 | if err != nil { 102 | t.Error(err) 103 | return 104 | } 105 | serialised := s256.Marshal(x, y) 106 | xx, yy := s256.Unmarshal(serialised) 107 | if xx == nil { 108 | t.Error("failed to unmarshal") 109 | return 110 | } 111 | if xx.Cmp(x) != 0 || yy.Cmp(y) != 0 { 112 | t.Error("unmarshal returned different values") 113 | return 114 | } 115 | } --------------------------------------------------------------------------------