diff --git a/.github/coverage/index.js b/.github/coverage/index.js index a636ad7..d36e492 100644 --- a/.github/coverage/index.js +++ b/.github/coverage/index.js @@ -1,5 +1,5 @@ var data = {files:[ -{"link":"run_coverage.78460cc2/index.html","title":"run_coverage","summary_name":"run_coverage","covered_class":"lineCov","covered":"97.9","covered_lines":"231","uncovered_lines":"5","total_lines" : "236"}, +{"link":"run_coverage.1398bb7a/index.html","title":"run_coverage","summary_name":"run_coverage","covered_class":"lineCov","covered":"97.5","covered_lines":"275","uncovered_lines":"7","total_lines" : "282"}, ], merged_files:[]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 236, "covered" : 231,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 282, "covered" : 275,}; diff --git a/.github/coverage/run_coverage b/.github/coverage/run_coverage index 8b6a729..16dbe65 120000 --- a/.github/coverage/run_coverage +++ b/.github/coverage/run_coverage @@ -1 +1 @@ -.github/coverage//run_coverage.78460cc2/ \ No newline at end of file +.github/coverage//run_coverage.1398bb7a/ \ No newline at end of file diff --git a/.github/coverage/run_coverage.78460cc2/amber.png b/.github/coverage/run_coverage.1398bb7a/amber.png similarity index 100% rename from .github/coverage/run_coverage.78460cc2/amber.png rename to .github/coverage/run_coverage.1398bb7a/amber.png diff --git a/.github/coverage/run_coverage.78460cc2/bcov.css b/.github/coverage/run_coverage.1398bb7a/bcov.css similarity index 100% rename from .github/coverage/run_coverage.78460cc2/bcov.css rename to .github/coverage/run_coverage.1398bb7a/bcov.css diff --git a/.github/coverage/run_coverage.1398bb7a/bitcoin.cr.6170de2.html b/.github/coverage/run_coverage.1398bb7a/bitcoin.cr.6170de2.html new file mode 100644 index 0000000..bbe91bb --- /dev/null +++ b/.github/coverage/run_coverage.1398bb7a/bitcoin.cr.6170de2.html @@ -0,0 +1,72 @@ + + + + + + ??? + + + + + + + + + + + + + + + +
Coverage Report
+ + + + + + + + + + + + + + + + + + + + +
Command:???Line number
Date: Instrumented lines:???Hits
Code covered:???Executed lines:???Order
+
+ + +
+ + + + +
Generated by: Kcov
+ + diff --git a/.github/coverage/run_coverage.1398bb7a/bitcoin.cr.6170de2.js b/.github/coverage/run_coverage.1398bb7a/bitcoin.cr.6170de2.js new file mode 100644 index 0000000..6402c8c --- /dev/null +++ b/.github/coverage/run_coverage.1398bb7a/bitcoin.cr.6170de2.js @@ -0,0 +1,144 @@ +var data = {lines:[ +{"lineNum":" 1","line":"# Copyright 2019-2022 Afr Schoe @q9f"}, +{"lineNum":" 2","line":"#"}, +{"lineNum":" 3","line":"# Licensed under the Apache License, Version 2.0 (the \"License\");"}, +{"lineNum":" 4","line":"# you may not use this file except in compliance with the License."}, +{"lineNum":" 5","line":"# You may obtain a copy of the License at"}, +{"lineNum":" 6","line":"#"}, +{"lineNum":" 7","line":"# http://www.apache.org/licenses/LICENSE-2.0"}, +{"lineNum":" 8","line":"#"}, +{"lineNum":" 9","line":"# Unless required by applicable law or agreed to in writing, software"}, +{"lineNum":" 10","line":"# distributed under the License is distributed on an \"AS IS\" BASIS,"}, +{"lineNum":" 11","line":"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied."}, +{"lineNum":" 12","line":"# See the License for the specific language governing permissions and"}, +{"lineNum":" 13","line":"# limitations under the License."}, +{"lineNum":" 14","line":""}, +{"lineNum":" 15","line":"require \"./secp256k1\""}, +{"lineNum":" 16","line":"include Secp256k1"}, +{"lineNum":" 17","line":""}, +{"lineNum":" 18","line":"# An example implementation of a `Bitcoin` account using an `Secp256k1`"}, +{"lineNum":" 19","line":"# key-pair and a Bitcoin network version identifier; only for educational"}, +{"lineNum":" 20","line":"# purposes and should not be used in production."}, +{"lineNum":" 21","line":"module Bitcoin"}, +{"lineNum":" 22","line":" # The Base-58 alphabet for `Bitcoin` addresses is a Base-64 alphabet without"}, +{"lineNum":" 23","line":" # `0`, `O`, `I`, and `l` to omit similar-looking letters."}, +{"lineNum":" 24","line":" BASE_58 = \"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\""}, +{"lineNum":" 25","line":""}, +{"lineNum":" 26","line":" # An example implementation of a `Bitcoin` account using an `Secp256k1`"}, +{"lineNum":" 27","line":" # key-pair and a Bitcoin network version identifier; only for educational"}, +{"lineNum":" 28","line":" # purposes and should not be used in production."}, +{"lineNum":" 29","line":" class Account"}, +{"lineNum":" 30","line":" # The `Secp256k1` keypair for the account."}, +{"lineNum":" 31","line":" getter key : Key"}, +{"lineNum":" 32","line":" # The network version indicator."}, +{"lineNum":" 33","line":" getter version : Num"}, +{"lineNum":" 34","line":" # The public, uncompressed Bitcoin account address."}, +{"lineNum":" 35","line":" getter address : String"}, +{"lineNum":" 36","line":" # The public, compressed Bitcoin account address."}, +{"lineNum":" 37","line":" getter address_compressed : String"}, +{"lineNum":" 38","line":" # The private, uncompressed wallet-import format."}, +{"lineNum":" 39","line":" getter wif : String"}, +{"lineNum":" 40","line":" # The private, compressed wallet-import format."}, +{"lineNum":" 41","line":" getter wif_compressed : String"}, +{"lineNum":" 42","line":""}, +{"lineNum":" 43","line":" # Creates a Bitcoin account from a given `Secp256k1::Key` keypay and for the"}, +{"lineNum":" 44","line":" # specified network version, e.g., `00` for Bitcoin main network. It creates"}, +{"lineNum":" 45","line":" # a random account if no parameters are supplied."}, +{"lineNum":" 46","line":" #"}, +{"lineNum":" 47","line":" # Parameters:"}, +{"lineNum":" 48","line":" # * `key` (`Secp256k1::Key`): the `Secp256k1` keypair for the account."}, +{"lineNum":" 49","line":" # * `version` (`Secp256k1::Num`): the network version indicator."}, +{"lineNum":" 50","line":" #"}, +{"lineNum":" 51","line":" # ```"}, +{"lineNum":" 52","line":" # priv = Secp256k1::Num.new \"18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725\""}, +{"lineNum":" 53","line":" # key = Secp256k1::Key.new priv"}, +{"lineNum":" 54","line":" # account = Bitcoin::Account.new key"}, +{"lineNum":" 55","line":" # # => #,"}, +{"lineNum":" 61","line":" # # @public_key=#,"}, +{"lineNum":" 66","line":" # # @y=#>>,"}, +{"lineNum":" 70","line":" # # @version=#,"}, +{"lineNum":" 74","line":" # # @address=\"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM\","}, +{"lineNum":" 75","line":" # # @address_compressed=\"1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\","}, +{"lineNum":" 76","line":" # # @wif=\"5J1F7GHadZG3sCCKHCwg8Jvys9xUbFsjLnGec4H125Ny1V9nR6V\","}, +{"lineNum":" 77","line":" # # @wif_compressed=\"Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C\">"}, +{"lineNum":" 78","line":" # ```"}, +{"lineNum":" 79","line":" def initialize(key = Key.new, version = Num.new \"0x00\")","class":"linePartCov","hits":"7","order":"89","possible_hits":"8",}, +{"lineNum":" 80","line":" if version.to_big < 0 || version.to_big > 127","class":"linePartCov","hits":"1","order":"94","possible_hits":"2",}, +{"lineNum":" 81","line":" raise \"Invalid version byte provided (out of range: #{version.to_prefixed_hex})\"","class":"lineNoCov","hits":"0","possible_hits":"1",}, +{"lineNum":" 82","line":" end"}, +{"lineNum":" 83","line":" @key = key","class":"lineCov","hits":"1","order":"95","possible_hits":"1",}, +{"lineNum":" 84","line":" @version = version","class":"lineCov","hits":"1","order":"96","possible_hits":"1",}, +{"lineNum":" 85","line":" @address = get_address","class":"lineCov","hits":"1","order":"97","possible_hits":"1",}, +{"lineNum":" 86","line":" @address_compressed = get_address true","class":"lineCov","hits":"1","order":"147","possible_hits":"1",}, +{"lineNum":" 87","line":" @wif = get_wif","class":"lineCov","hits":"1","order":"155","possible_hits":"1",}, +{"lineNum":" 88","line":" @wif_compressed = get_wif true","class":"lineCov","hits":"1","order":"168","possible_hits":"1",}, +{"lineNum":" 89","line":" end"}, +{"lineNum":" 90","line":""}, +{"lineNum":" 91","line":" # Generates the public address for this account."}, +{"lineNum":" 92","line":" private def get_address(compressed = false) : String","class":"lineCov","hits":"4","order":"98","possible_hits":"4",}, +{"lineNum":" 93","line":" pub_key = Num.new @key.public_bytes","class":"lineCov","hits":"1","order":"99","possible_hits":"1",}, +{"lineNum":" 94","line":" if compressed","class":"lineCov","hits":"1","order":"112","possible_hits":"1",}, +{"lineNum":" 95","line":" pub_key = Num.new @key.public_bytes_compressed","class":"lineCov","hits":"1","order":"148","possible_hits":"1",}, +{"lineNum":" 96","line":" end"}, +{"lineNum":" 97","line":" hash_0 = Util.sha256 pub_key.to_zpadded_bytes pub_key.bin.size","class":"lineCov","hits":"1","order":"113","possible_hits":"1",}, +{"lineNum":" 98","line":" hash_1 = Util.ripemd160 hash_0.to_zpadded_bytes","class":"lineCov","hits":"1","order":"120","possible_hits":"1",}, +{"lineNum":" 99","line":" versioned = Util.concat_bytes @version.to_bytes, hash_1.to_zpadded_bytes 20","class":"lineCov","hits":"1","order":"124","possible_hits":"1",}, +{"lineNum":" 100","line":" hash_2 = Util.sha256 versioned","class":"lineCov","hits":"1","order":"130","possible_hits":"1",}, +{"lineNum":" 101","line":" hash_3 = Util.sha256 hash_2.to_zpadded_bytes","class":"lineCov","hits":"1","order":"131","possible_hits":"1",}, +{"lineNum":" 102","line":" binary = Util.concat_bytes versioned, hash_3.to_zpadded_bytes[0, 4]","class":"lineCov","hits":"1","order":"132","possible_hits":"1",}, +{"lineNum":" 103","line":" encode_base58 Num.new binary","class":"lineCov","hits":"1","order":"133","possible_hits":"1",}, +{"lineNum":" 104","line":" end"}, +{"lineNum":" 105","line":""}, +{"lineNum":" 106","line":" # Generates the private wallet-import format for this account."}, +{"lineNum":" 107","line":" private def get_wif(compressed = false) : String","class":"lineCov","hits":"4","order":"156","possible_hits":"4",}, +{"lineNum":" 108","line":" wif_version = Num.new @version.dec + 128","class":"lineCov","hits":"1","order":"157","possible_hits":"1",}, +{"lineNum":" 109","line":" compression_byte = \"\"","class":"lineCov","hits":"1","order":"158","possible_hits":"1",}, +{"lineNum":" 110","line":" if compressed","class":"lineCov","hits":"1","order":"159","possible_hits":"1",}, +{"lineNum":" 111","line":" compression_byte = \"01\"","class":"lineCov","hits":"1","order":"169","possible_hits":"1",}, +{"lineNum":" 112","line":" end"}, +{"lineNum":" 113","line":" versioned = Num.new \"#{wif_version.to_hex}#{@key.private_hex}#{compression_byte}\"","class":"lineCov","hits":"1","order":"160","possible_hits":"1",}, +{"lineNum":" 114","line":" hash_0 = Util.sha256 versioned","class":"lineCov","hits":"1","order":"163","possible_hits":"1",}, +{"lineNum":" 115","line":" hash_1 = Util.sha256 hash_0","class":"lineCov","hits":"1","order":"165","possible_hits":"1",}, +{"lineNum":" 116","line":" binary = Util.concat_bytes versioned.to_bytes, hash_1.to_zpadded_bytes[0, 4]","class":"lineCov","hits":"1","order":"166","possible_hits":"1",}, +{"lineNum":" 117","line":" encode_base58 Num.new binary","class":"lineCov","hits":"1","order":"167","possible_hits":"1",}, +{"lineNum":" 118","line":" end"}, +{"lineNum":" 119","line":""}, +{"lineNum":" 120","line":" # Encode a given numeric with BASE58."}, +{"lineNum":" 121","line":" private def encode_base58(num : Num) : String","class":"lineCov","hits":"1","order":"134","possible_hits":"1",}, +{"lineNum":" 122","line":" big = num.to_big","class":"lineCov","hits":"1","order":"135","possible_hits":"1",}, +{"lineNum":" 123","line":" hex = num.to_hex","class":"lineCov","hits":"1","order":"136","possible_hits":"1",}, +{"lineNum":" 124","line":" encoded = String.new","class":"lineCov","hits":"1","order":"137","possible_hits":"1",}, +{"lineNum":" 125","line":" while big > 0","class":"lineCov","hits":"1","order":"138","possible_hits":"1",}, +{"lineNum":" 126","line":" big, rem = big.divmod 58","class":"lineCov","hits":"1","order":"139","possible_hits":"1",}, +{"lineNum":" 127","line":" encoded += BASE_58[rem.to_i % 58]","class":"lineCov","hits":"1","order":"140","possible_hits":"1",}, +{"lineNum":" 128","line":" end"}, +{"lineNum":" 129","line":" i, s = 0, 2","class":"lineCov","hits":"1","order":"141","possible_hits":"1",}, +{"lineNum":" 130","line":" current_byte = hex[i, s]","class":"lineCov","hits":"1","order":"142","possible_hits":"1",}, +{"lineNum":" 131","line":" while current_byte.to_i(16) === 0","class":"lineCov","hits":"1","order":"143","possible_hits":"1",}, +{"lineNum":" 132","line":" encoded = \"#{encoded}1\"","class":"lineCov","hits":"1","order":"144","possible_hits":"1",}, +{"lineNum":" 133","line":" i += s","class":"lineNoCov","hits":"0","possible_hits":"1",}, +{"lineNum":" 134","line":" current_byte = hex[i, s]","class":"lineCov","hits":"2","order":"145","possible_hits":"2",}, +{"lineNum":" 135","line":" end"}, +{"lineNum":" 136","line":" encoded.reverse","class":"lineCov","hits":"1","order":"146","possible_hits":"1",}, +{"lineNum":" 137","line":" end"}, +{"lineNum":" 138","line":" end"}, +{"lineNum":" 139","line":"end"}, +]}; +var percent_low = 25;var percent_high = 75; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 44, "covered" : 42,}; +var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/cobertura.xml b/.github/coverage/run_coverage.1398bb7a/cobertura.xml similarity index 75% rename from .github/coverage/run_coverage.78460cc2/cobertura.xml rename to .github/coverage/run_coverage.1398bb7a/cobertura.xml index 1626ae0..088fd1d 100644 --- a/.github/coverage/run_coverage.78460cc2/cobertura.xml +++ b/.github/coverage/run_coverage.1398bb7a/cobertura.xml @@ -1,13 +1,93 @@ - + - /home/user/.opt/q9f/secp256k1.cr/src/secp256k1/ + /home/user/.opt/q9f/secp256k1.cr/src/ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -17,14 +97,14 @@ - - + + - - - + + + - + @@ -55,7 +135,7 @@ - + @@ -115,39 +195,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -187,7 +235,7 @@ - + @@ -203,9 +251,11 @@ + + - + @@ -256,7 +306,7 @@ - + @@ -266,7 +316,7 @@ - + diff --git a/.github/coverage/run_coverage.78460cc2/context.cr.d435d9a9.html b/.github/coverage/run_coverage.1398bb7a/context.cr.d435d9a9.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/context.cr.d435d9a9.html rename to .github/coverage/run_coverage.1398bb7a/context.cr.d435d9a9.html diff --git a/.github/coverage/run_coverage.78460cc2/context.cr.d435d9a9.js b/.github/coverage/run_coverage.1398bb7a/context.cr.d435d9a9.js similarity index 84% rename from .github/coverage/run_coverage.78460cc2/context.cr.d435d9a9.js rename to .github/coverage/run_coverage.1398bb7a/context.cr.d435d9a9.js index 5c334d7..c03212f 100644 --- a/.github/coverage/run_coverage.78460cc2/context.cr.d435d9a9.js +++ b/.github/coverage/run_coverage.1398bb7a/context.cr.d435d9a9.js @@ -48,30 +48,30 @@ var data = {lines:[ {"lineNum":" 47","line":" # # @dec=0,"}, {"lineNum":" 48","line":" # # @bin=Bytes[0]>>"}, {"lineNum":" 49","line":" # ```"}, -{"lineNum":" 50","line":" def sign(key : Key, hash : Num) : Signature","class":"lineCov","hits":"2","order":"102","possible_hits":"2",}, -{"lineNum":" 51","line":" k = Util.deterministic_k key.private_key, hash","class":"lineCov","hits":"1","order":"103","possible_hits":"1",}, -{"lineNum":" 52","line":" hash = hash.to_big","class":"lineCov","hits":"1","order":"133","possible_hits":"1",}, -{"lineNum":" 53","line":" priv = key.private_key.to_big","class":"lineCov","hits":"1","order":"134","possible_hits":"1",}, -{"lineNum":" 54","line":" point = Curve.mul G, k","class":"lineCov","hits":"1","order":"135","possible_hits":"1",}, -{"lineNum":" 55","line":" r = point.x.to_big % N.to_big","class":"lineCov","hits":"1","order":"137","possible_hits":"1",}, -{"lineNum":" 56","line":" k_inv = Curve.mod_inv k, N","class":"lineCov","hits":"1","order":"138","possible_hits":"1",}, -{"lineNum":" 57","line":" s = ((hash + r * priv) * k_inv.to_big) % N.to_big","class":"lineCov","hits":"1","order":"139","possible_hits":"1",}, -{"lineNum":" 58","line":" x_mag = point.x.to_big > N.to_big","class":"lineCov","hits":"1","order":"140","possible_hits":"1",}, -{"lineNum":" 59","line":" y_parity = (point.y.to_big % 2) == 0","class":"lineCov","hits":"1","order":"141","possible_hits":"1",}, -{"lineNum":" 60","line":" rec_id : Int8 = -1","class":"lineCov","hits":"1","order":"142","possible_hits":"1",}, -{"lineNum":" 61","line":" if !y_parity && x_mag","class":"lineCov","hits":"2","order":"143","possible_hits":"2",}, +{"lineNum":" 50","line":" def sign(key : Key, hash : Num) : Signature","class":"lineCov","hits":"2","order":"170","possible_hits":"2",}, +{"lineNum":" 51","line":" k = Util.deterministic_k key.private_key, hash","class":"lineCov","hits":"1","order":"171","possible_hits":"1",}, +{"lineNum":" 52","line":" hash = hash.to_big","class":"lineCov","hits":"1","order":"192","possible_hits":"1",}, +{"lineNum":" 53","line":" priv = key.private_key.to_big","class":"lineCov","hits":"1","order":"193","possible_hits":"1",}, +{"lineNum":" 54","line":" point = Curve.mul G, k","class":"lineCov","hits":"1","order":"194","possible_hits":"1",}, +{"lineNum":" 55","line":" r = point.x.to_big % N.to_big","class":"lineCov","hits":"1","order":"196","possible_hits":"1",}, +{"lineNum":" 56","line":" k_inv = Curve.mod_inv k, N","class":"lineCov","hits":"1","order":"197","possible_hits":"1",}, +{"lineNum":" 57","line":" s = ((hash + r * priv) * k_inv.to_big) % N.to_big","class":"lineCov","hits":"1","order":"198","possible_hits":"1",}, +{"lineNum":" 58","line":" x_mag = point.x.to_big > N.to_big","class":"lineCov","hits":"1","order":"199","possible_hits":"1",}, +{"lineNum":" 59","line":" y_parity = (point.y.to_big % 2) == 0","class":"lineCov","hits":"1","order":"200","possible_hits":"1",}, +{"lineNum":" 60","line":" rec_id : Int8 = -1","class":"lineCov","hits":"1","order":"201","possible_hits":"1",}, +{"lineNum":" 61","line":" if !y_parity && x_mag","class":"lineCov","hits":"2","order":"202","possible_hits":"2",}, {"lineNum":" 62","line":" rec_id = 3","class":"lineNoCov","hits":"0","possible_hits":"1",}, -{"lineNum":" 63","line":" elsif y_parity && x_mag","class":"lineCov","hits":"2","order":"144","possible_hits":"2",}, +{"lineNum":" 63","line":" elsif y_parity && x_mag","class":"lineCov","hits":"2","order":"203","possible_hits":"2",}, {"lineNum":" 64","line":" rec_id = 2","class":"lineNoCov","hits":"0","possible_hits":"1",}, -{"lineNum":" 65","line":" elsif !y_parity && !x_mag","class":"lineCov","hits":"2","order":"145","possible_hits":"2",}, -{"lineNum":" 66","line":" rec_id = 1","class":"lineCov","hits":"1","order":"146","possible_hits":"1",}, +{"lineNum":" 65","line":" elsif !y_parity && !x_mag","class":"lineCov","hits":"2","order":"204","possible_hits":"2",}, +{"lineNum":" 66","line":" rec_id = 1","class":"lineCov","hits":"1","order":"205","possible_hits":"1",}, {"lineNum":" 67","line":" else"}, -{"lineNum":" 68","line":" rec_id = 0","class":"lineCov","hits":"4","order":"147","possible_hits":"4",}, +{"lineNum":" 68","line":" rec_id = 0","class":"lineCov","hits":"4","order":"206","possible_hits":"4",}, {"lineNum":" 69","line":" end"}, -{"lineNum":" 70","line":" r = Num.new r","class":"lineCov","hits":"1","order":"148","possible_hits":"1",}, -{"lineNum":" 71","line":" s = Num.new s","class":"lineCov","hits":"1","order":"149","possible_hits":"1",}, -{"lineNum":" 72","line":" v = Num.new BigInt.new rec_id","class":"lineCov","hits":"1","order":"150","possible_hits":"1",}, -{"lineNum":" 73","line":" Signature.new r, s, v","class":"lineCov","hits":"1","order":"151","possible_hits":"1",}, +{"lineNum":" 70","line":" r = Num.new r","class":"lineCov","hits":"1","order":"207","possible_hits":"1",}, +{"lineNum":" 71","line":" s = Num.new s","class":"lineCov","hits":"1","order":"208","possible_hits":"1",}, +{"lineNum":" 72","line":" v = Num.new BigInt.new rec_id","class":"lineCov","hits":"1","order":"209","possible_hits":"1",}, +{"lineNum":" 73","line":" Signature.new r, s, v","class":"lineCov","hits":"1","order":"210","possible_hits":"1",}, {"lineNum":" 74","line":" end"}, {"lineNum":" 75","line":""}, {"lineNum":" 76","line":" # Verifies that a given signature for a given message hash matches"}, @@ -95,15 +95,15 @@ var data = {lines:[ {"lineNum":" 94","line":" # ctx.verify sig, hash, publ"}, {"lineNum":" 95","line":" # # => true"}, {"lineNum":" 96","line":" # ```"}, -{"lineNum":" 97","line":" def verify(sig : Signature, hash : Num, publ : Point) : Bool","class":"lineCov","hits":"2","order":"156","possible_hits":"2",}, -{"lineNum":" 98","line":" s_inv = Curve.mod_inv sig.s, N","class":"lineCov","hits":"1","order":"157","possible_hits":"1",}, -{"lineNum":" 99","line":" p0 = Curve.mul G, (hash.to_big * s_inv.to_big) % N.to_big","class":"lineCov","hits":"1","order":"158","possible_hits":"1",}, -{"lineNum":" 100","line":" p1 = Curve.mul publ, (sig.r.to_big * s_inv.to_big) % N.to_big","class":"lineCov","hits":"1","order":"159","possible_hits":"1",}, -{"lineNum":" 101","line":" p = Curve.add p0, p1","class":"lineCov","hits":"1","order":"160","possible_hits":"1",}, -{"lineNum":" 102","line":" sig.r.to_big === p.x.to_big","class":"lineCov","hits":"1","order":"161","possible_hits":"1",}, +{"lineNum":" 97","line":" def verify(sig : Signature, hash : Num, publ : Point) : Bool","class":"lineCov","hits":"2","order":"215","possible_hits":"2",}, +{"lineNum":" 98","line":" s_inv = Curve.mod_inv sig.s, N","class":"lineCov","hits":"1","order":"216","possible_hits":"1",}, +{"lineNum":" 99","line":" p0 = Curve.mul G, (hash.to_big * s_inv.to_big) % N.to_big","class":"lineCov","hits":"1","order":"217","possible_hits":"1",}, +{"lineNum":" 100","line":" p1 = Curve.mul publ, (sig.r.to_big * s_inv.to_big) % N.to_big","class":"lineCov","hits":"1","order":"218","possible_hits":"1",}, +{"lineNum":" 101","line":" p = Curve.add p0, p1","class":"lineCov","hits":"1","order":"219","possible_hits":"1",}, +{"lineNum":" 102","line":" sig.r.to_big === p.x.to_big","class":"lineCov","hits":"1","order":"220","possible_hits":"1",}, {"lineNum":" 103","line":" end"}, {"lineNum":" 104","line":"end"}, ]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 28, "covered" : 26,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 28, "covered" : 26,}; var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/cov.xml b/.github/coverage/run_coverage.1398bb7a/cov.xml similarity index 75% rename from .github/coverage/run_coverage.78460cc2/cov.xml rename to .github/coverage/run_coverage.1398bb7a/cov.xml index 1626ae0..088fd1d 100644 --- a/.github/coverage/run_coverage.78460cc2/cov.xml +++ b/.github/coverage/run_coverage.1398bb7a/cov.xml @@ -1,13 +1,93 @@ - + - /home/user/.opt/q9f/secp256k1.cr/src/secp256k1/ + /home/user/.opt/q9f/secp256k1.cr/src/ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -17,14 +97,14 @@ - - + + - - - + + + - + @@ -55,7 +135,7 @@ - + @@ -115,39 +195,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -187,7 +235,7 @@ - + @@ -203,9 +251,11 @@ + + - + @@ -256,7 +306,7 @@ - + @@ -266,7 +316,7 @@ - + diff --git a/.github/coverage/run_coverage.78460cc2/coverage.db b/.github/coverage/run_coverage.1398bb7a/coverage.db similarity index 82% rename from .github/coverage/run_coverage.78460cc2/coverage.db rename to .github/coverage/run_coverage.1398bb7a/coverage.db index 73a6700..b055d3b 100644 Binary files a/.github/coverage/run_coverage.78460cc2/coverage.db and b/.github/coverage/run_coverage.1398bb7a/coverage.db differ diff --git a/.github/coverage/run_coverage.78460cc2/coverage.json b/.github/coverage/run_coverage.1398bb7a/coverage.json similarity index 78% rename from .github/coverage/run_coverage.78460cc2/coverage.json rename to .github/coverage/run_coverage.1398bb7a/coverage.json index 756fc4a..25b7ad8 100644 --- a/.github/coverage/run_coverage.78460cc2/coverage.json +++ b/.github/coverage/run_coverage.1398bb7a/coverage.json @@ -1,19 +1,20 @@ { "files": [ + {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/context.cr", "percent_covered": "92.86", "covered_lines": "26", "total_lines": "28"}, + {"file": "/home/user/.opt/q9f/secp256k1.cr/src/bitcoin.cr", "percent_covered": "95.45", "covered_lines": "42", "total_lines": "44"}, {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/util.cr", "percent_covered": "93.18", "covered_lines": "41", "total_lines": "44"}, {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/curve.cr", "percent_covered": "100.00", "covered_lines": "56", "total_lines": "56"}, - {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/context.cr", "percent_covered": "92.86", "covered_lines": "26", "total_lines": "28"}, {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/point.cr", "percent_covered": "100.00", "covered_lines": "36", "total_lines": "36"}, - {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/key.cr", "percent_covered": "100.00", "covered_lines": "14", "total_lines": "14"}, + {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/key.cr", "percent_covered": "100.00", "covered_lines": "16", "total_lines": "16"}, {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/num.cr", "percent_covered": "100.00", "covered_lines": "47", "total_lines": "47"}, {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1/signature.cr", "percent_covered": "100.00", "covered_lines": "6", "total_lines": "6"}, {"file": "/home/user/.opt/q9f/secp256k1.cr/src/secp256k1.cr", "percent_covered": "100.00", "covered_lines": "5", "total_lines": "5"} ], - "percent_covered": "97.88", - "covered_lines": 231, - "total_lines": 236, + "percent_covered": "97.52", + "covered_lines": 275, + "total_lines": 282, "percent_low": 25, "percent_high": 75, "command": "run_coverage", - "date": "2022-04-06 12:16:54" + "date": "2022-04-06 14:26:02" } diff --git a/.github/coverage/run_coverage.78460cc2/curve.cr.f05213da.html b/.github/coverage/run_coverage.1398bb7a/curve.cr.f05213da.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/curve.cr.f05213da.html rename to .github/coverage/run_coverage.1398bb7a/curve.cr.f05213da.html diff --git a/.github/coverage/run_coverage.78460cc2/curve.cr.f05213da.js b/.github/coverage/run_coverage.1398bb7a/curve.cr.f05213da.js similarity index 81% rename from .github/coverage/run_coverage.78460cc2/curve.cr.f05213da.js rename to .github/coverage/run_coverage.1398bb7a/curve.cr.f05213da.js index 10a7c4f..f86b73a 100644 --- a/.github/coverage/run_coverage.78460cc2/curve.cr.f05213da.js +++ b/.github/coverage/run_coverage.1398bb7a/curve.cr.f05213da.js @@ -35,25 +35,25 @@ var data = {lines:[ {"lineNum":" 34","line":" # # @dec=18547889042489459453149555262266367802647896593999507743600711803155665963719,"}, {"lineNum":" 35","line":" # # @bin=Bytes[41, 1, 187, 177, 47, 203, 100, 233, 136, 126, 105, 158, 105, 230, 176, 179, 129, 29, 177, 143, 107, 79, 148, 223, 178, 96, 132, 229, 203, 56, 202, 199]>"}, {"lineNum":" 36","line":" # ```"}, -{"lineNum":" 37","line":" def mod_inv(a : Num | BigInt, prime = P) : Num","class":"lineCov","hits":"8","order":"57","possible_hits":"8",}, -{"lineNum":" 38","line":" a = a.to_big if a.is_a? Num","class":"lineCov","hits":"1","order":"58","possible_hits":"1",}, -{"lineNum":" 39","line":" prime = prime.to_big if prime.is_a? Num","class":"lineCov","hits":"2","order":"59","possible_hits":"2",}, -{"lineNum":" 40","line":" m_low = 1","class":"lineCov","hits":"2","order":"60","possible_hits":"2",}, -{"lineNum":" 41","line":" m_high = 0","class":"lineCov","hits":"2","order":"61","possible_hits":"2",}, -{"lineNum":" 42","line":" v_low = a % prime","class":"lineCov","hits":"2","order":"62","possible_hits":"2",}, -{"lineNum":" 43","line":" v_high = prime","class":"lineCov","hits":"2","order":"63","possible_hits":"2",}, -{"lineNum":" 44","line":" while v_low > 1","class":"lineCov","hits":"2","order":"64","possible_hits":"2",}, -{"lineNum":" 45","line":" v_ratio = v_high // v_low","class":"lineCov","hits":"4","order":"65","possible_hits":"4",}, -{"lineNum":" 46","line":" m_low_r = m_low * v_ratio","class":"lineCov","hits":"4","order":"66","possible_hits":"4",}, -{"lineNum":" 47","line":" v_low_r = v_low * v_ratio","class":"lineCov","hits":"4","order":"67","possible_hits":"4",}, -{"lineNum":" 48","line":" m = m_high - m_low_r","class":"lineCov","hits":"4","order":"68","possible_hits":"4",}, -{"lineNum":" 49","line":" v = v_high - v_low_r","class":"lineCov","hits":"2","order":"69","possible_hits":"2",}, -{"lineNum":" 50","line":" m_high = m_low","class":"lineCov","hits":"2","order":"70","possible_hits":"2",}, -{"lineNum":" 51","line":" v_high = v_low","class":"lineCov","hits":"2","order":"71","possible_hits":"2",}, -{"lineNum":" 52","line":" m_low = m","class":"lineCov","hits":"2","order":"72","possible_hits":"2",}, -{"lineNum":" 53","line":" v_low = v","class":"lineCov","hits":"6","order":"73","possible_hits":"6",}, +{"lineNum":" 37","line":" def mod_inv(a : Num | BigInt, prime = P) : Num","class":"lineCov","hits":"8","order":"47","possible_hits":"8",}, +{"lineNum":" 38","line":" a = a.to_big if a.is_a? Num","class":"lineCov","hits":"1","order":"48","possible_hits":"1",}, +{"lineNum":" 39","line":" prime = prime.to_big if prime.is_a? Num","class":"lineCov","hits":"2","order":"49","possible_hits":"2",}, +{"lineNum":" 40","line":" m_low = 1","class":"lineCov","hits":"2","order":"50","possible_hits":"2",}, +{"lineNum":" 41","line":" m_high = 0","class":"lineCov","hits":"2","order":"51","possible_hits":"2",}, +{"lineNum":" 42","line":" v_low = a % prime","class":"lineCov","hits":"2","order":"52","possible_hits":"2",}, +{"lineNum":" 43","line":" v_high = prime","class":"lineCov","hits":"2","order":"53","possible_hits":"2",}, +{"lineNum":" 44","line":" while v_low > 1","class":"lineCov","hits":"2","order":"54","possible_hits":"2",}, +{"lineNum":" 45","line":" v_ratio = v_high // v_low","class":"lineCov","hits":"4","order":"55","possible_hits":"4",}, +{"lineNum":" 46","line":" m_low_r = m_low * v_ratio","class":"lineCov","hits":"4","order":"56","possible_hits":"4",}, +{"lineNum":" 47","line":" v_low_r = v_low * v_ratio","class":"lineCov","hits":"4","order":"57","possible_hits":"4",}, +{"lineNum":" 48","line":" m = m_high - m_low_r","class":"lineCov","hits":"4","order":"58","possible_hits":"4",}, +{"lineNum":" 49","line":" v = v_high - v_low_r","class":"lineCov","hits":"2","order":"59","possible_hits":"2",}, +{"lineNum":" 50","line":" m_high = m_low","class":"lineCov","hits":"2","order":"60","possible_hits":"2",}, +{"lineNum":" 51","line":" v_high = v_low","class":"lineCov","hits":"2","order":"61","possible_hits":"2",}, +{"lineNum":" 52","line":" m_low = m","class":"lineCov","hits":"2","order":"62","possible_hits":"2",}, +{"lineNum":" 53","line":" v_low = v","class":"lineCov","hits":"6","order":"63","possible_hits":"6",}, {"lineNum":" 54","line":" end"}, -{"lineNum":" 55","line":" Num.new m_low % prime","class":"lineCov","hits":"2","order":"74","possible_hits":"2",}, +{"lineNum":" 55","line":" Num.new m_low % prime","class":"lineCov","hits":"2","order":"64","possible_hits":"2",}, {"lineNum":" 56","line":" end"}, {"lineNum":" 57","line":""}, {"lineNum":" 58","line":" # Computes the elliptic curve jive addition of point `p(x, y)` and `q(x, y)`."}, @@ -80,21 +80,21 @@ var data = {lines:[ {"lineNum":" 79","line":" # # @dec=41035367046532706466310839850976742216202985567094126989716802462994340507300,"}, {"lineNum":" 80","line":" # # @bin=Bytes[90, 185, 49, 214, 114, 120, 114, 211, 62, 160, 73, 23, 5, 104, 15, 95, 188, 183, 64, 155, 168, 5, 65, 71, 6, 115, 196, 252, 228, 223, 238, 164]>>"}, {"lineNum":" 81","line":" # ```"}, -{"lineNum":" 82","line":" def add(p : Point, q : Point, prime = P) : Point","class":"lineCov","hits":"4","order":"82","possible_hits":"4",}, -{"lineNum":" 83","line":" prime = prime.to_big if prime.is_a? Num","class":"lineCov","hits":"1","order":"83","possible_hits":"1",}, -{"lineNum":" 84","line":" p_x = p.x.to_big","class":"lineCov","hits":"1","order":"84","possible_hits":"1",}, -{"lineNum":" 85","line":" p_y = p.y.to_big","class":"lineCov","hits":"1","order":"85","possible_hits":"1",}, -{"lineNum":" 86","line":" q_x = q.x.to_big","class":"lineCov","hits":"1","order":"86","possible_hits":"1",}, -{"lineNum":" 87","line":" q_y = q.y.to_big","class":"lineCov","hits":"1","order":"87","possible_hits":"1",}, -{"lineNum":" 88","line":" x_delta = q_x - p_x","class":"lineCov","hits":"1","order":"88","possible_hits":"1",}, -{"lineNum":" 89","line":" x_inv = mod_inv x_delta","class":"lineCov","hits":"1","order":"89","possible_hits":"1",}, -{"lineNum":" 90","line":" y_delta = q_y - p_y","class":"lineCov","hits":"1","order":"90","possible_hits":"1",}, -{"lineNum":" 91","line":" m = (y_delta * x_inv.to_big) % prime","class":"lineCov","hits":"1","order":"91","possible_hits":"1",}, -{"lineNum":" 92","line":" x = (m * m - p_x - q_x) % prime","class":"lineCov","hits":"1","order":"92","possible_hits":"1",}, -{"lineNum":" 93","line":" y = (m * (p_x - x) - p_y) % prime","class":"lineCov","hits":"1","order":"93","possible_hits":"1",}, -{"lineNum":" 94","line":" x = Num.new x","class":"lineCov","hits":"1","order":"94","possible_hits":"1",}, -{"lineNum":" 95","line":" y = Num.new y","class":"lineCov","hits":"1","order":"95","possible_hits":"1",}, -{"lineNum":" 96","line":" Point.new x, y","class":"lineCov","hits":"1","order":"96","possible_hits":"1",}, +{"lineNum":" 82","line":" def add(p : Point, q : Point, prime = P) : Point","class":"lineCov","hits":"4","order":"72","possible_hits":"4",}, +{"lineNum":" 83","line":" prime = prime.to_big if prime.is_a? Num","class":"lineCov","hits":"1","order":"73","possible_hits":"1",}, +{"lineNum":" 84","line":" p_x = p.x.to_big","class":"lineCov","hits":"1","order":"74","possible_hits":"1",}, +{"lineNum":" 85","line":" p_y = p.y.to_big","class":"lineCov","hits":"1","order":"75","possible_hits":"1",}, +{"lineNum":" 86","line":" q_x = q.x.to_big","class":"lineCov","hits":"1","order":"76","possible_hits":"1",}, +{"lineNum":" 87","line":" q_y = q.y.to_big","class":"lineCov","hits":"1","order":"77","possible_hits":"1",}, +{"lineNum":" 88","line":" x_delta = q_x - p_x","class":"lineCov","hits":"1","order":"78","possible_hits":"1",}, +{"lineNum":" 89","line":" x_inv = mod_inv x_delta","class":"lineCov","hits":"1","order":"79","possible_hits":"1",}, +{"lineNum":" 90","line":" y_delta = q_y - p_y","class":"lineCov","hits":"1","order":"80","possible_hits":"1",}, +{"lineNum":" 91","line":" m = (y_delta * x_inv.to_big) % prime","class":"lineCov","hits":"1","order":"81","possible_hits":"1",}, +{"lineNum":" 92","line":" x = (m * m - p_x - q_x) % prime","class":"lineCov","hits":"1","order":"82","possible_hits":"1",}, +{"lineNum":" 93","line":" y = (m * (p_x - x) - p_y) % prime","class":"lineCov","hits":"1","order":"83","possible_hits":"1",}, +{"lineNum":" 94","line":" x = Num.new x","class":"lineCov","hits":"1","order":"84","possible_hits":"1",}, +{"lineNum":" 95","line":" y = Num.new y","class":"lineCov","hits":"1","order":"85","possible_hits":"1",}, +{"lineNum":" 96","line":" Point.new x, y","class":"lineCov","hits":"1","order":"86","possible_hits":"1",}, {"lineNum":" 97","line":" end"}, {"lineNum":" 98","line":""}, {"lineNum":" 99","line":" # Computes the elliptic curve juke point doubling of `p(x, y)`."}, @@ -121,19 +121,19 @@ var data = {lines:[ {"lineNum":" 120","line":" # # @dec=7078265941949780810129057229376739925018916922271301049726817038887681467708,"}, {"lineNum":" 121","line":" # # @bin=Bytes[15, 166, 40, 19, 174, 73, 215, 29, 211, 161, 159, 189, 23, 81, 110, 126, 157, 205, 213, 117, 61, 105, 203, 19, 216, 112, 81, 216, 211, 39, 37, 60]>>"}, {"lineNum":" 122","line":" # ```"}, -{"lineNum":" 123","line":" def double(p : Point, prime = P) : Point","class":"lineCov","hits":"4","order":"44","possible_hits":"4",}, -{"lineNum":" 124","line":" prime = prime.to_big if prime.is_a? Num","class":"lineCov","hits":"1","order":"45","possible_hits":"1",}, -{"lineNum":" 125","line":" p_x = p.x.to_big","class":"lineCov","hits":"1","order":"46","possible_hits":"1",}, -{"lineNum":" 126","line":" p_y = p.y.to_big","class":"lineCov","hits":"1","order":"47","possible_hits":"1",}, -{"lineNum":" 127","line":" lam_numer = 3 * p_x * p_x","class":"lineCov","hits":"1","order":"48","possible_hits":"1",}, -{"lineNum":" 128","line":" lam_denom = 2 * p_y","class":"lineCov","hits":"1","order":"49","possible_hits":"1",}, -{"lineNum":" 129","line":" lam_inv = mod_inv Num.new lam_denom","class":"lineCov","hits":"1","order":"50","possible_hits":"1",}, -{"lineNum":" 130","line":" lam = (lam_numer * lam_inv.to_big) % prime","class":"lineCov","hits":"1","order":"75","possible_hits":"1",}, -{"lineNum":" 131","line":" x = (lam * lam - 2 * p_x) % prime","class":"lineCov","hits":"1","order":"76","possible_hits":"1",}, -{"lineNum":" 132","line":" y = (lam * (p_x - x) - p_y) % prime","class":"lineCov","hits":"1","order":"77","possible_hits":"1",}, -{"lineNum":" 133","line":" x = Num.new x","class":"lineCov","hits":"1","order":"78","possible_hits":"1",}, -{"lineNum":" 134","line":" y = Num.new y","class":"lineCov","hits":"1","order":"79","possible_hits":"1",}, -{"lineNum":" 135","line":" Point.new x, y","class":"lineCov","hits":"1","order":"80","possible_hits":"1",}, +{"lineNum":" 123","line":" def double(p : Point, prime = P) : Point","class":"lineCov","hits":"4","order":"34","possible_hits":"4",}, +{"lineNum":" 124","line":" prime = prime.to_big if prime.is_a? Num","class":"lineCov","hits":"1","order":"35","possible_hits":"1",}, +{"lineNum":" 125","line":" p_x = p.x.to_big","class":"lineCov","hits":"1","order":"36","possible_hits":"1",}, +{"lineNum":" 126","line":" p_y = p.y.to_big","class":"lineCov","hits":"1","order":"37","possible_hits":"1",}, +{"lineNum":" 127","line":" lam_numer = 3 * p_x * p_x","class":"lineCov","hits":"1","order":"38","possible_hits":"1",}, +{"lineNum":" 128","line":" lam_denom = 2 * p_y","class":"lineCov","hits":"1","order":"39","possible_hits":"1",}, +{"lineNum":" 129","line":" lam_inv = mod_inv Num.new lam_denom","class":"lineCov","hits":"1","order":"40","possible_hits":"1",}, +{"lineNum":" 130","line":" lam = (lam_numer * lam_inv.to_big) % prime","class":"lineCov","hits":"1","order":"65","possible_hits":"1",}, +{"lineNum":" 131","line":" x = (lam * lam - 2 * p_x) % prime","class":"lineCov","hits":"1","order":"66","possible_hits":"1",}, +{"lineNum":" 132","line":" y = (lam * (p_x - x) - p_y) % prime","class":"lineCov","hits":"1","order":"67","possible_hits":"1",}, +{"lineNum":" 133","line":" x = Num.new x","class":"lineCov","hits":"1","order":"68","possible_hits":"1",}, +{"lineNum":" 134","line":" y = Num.new y","class":"lineCov","hits":"1","order":"69","possible_hits":"1",}, +{"lineNum":" 135","line":" Point.new x, y","class":"lineCov","hits":"1","order":"70","possible_hits":"1",}, {"lineNum":" 136","line":" end"}, {"lineNum":" 137","line":""}, {"lineNum":" 138","line":" # Computes the elliptic curve sequence multiplication of point `p(x, y)`"}, @@ -160,18 +160,18 @@ var data = {lines:[ {"lineNum":" 159","line":" # # @dec=52247677450688090944696492452353217603423545532791062178926183551888078233207,"}, {"lineNum":" 160","line":" # # @bin=Bytes[115, 131, 35, 49, 151, 157, 137, 211, 149, 145, 32, 97, 227, 65, 248, 70, 140, 251, 62, 97, 157, 160, 106, 5, 126, 74, 92, 169, 91, 185, 94, 119]>>"}, {"lineNum":" 161","line":" # ```"}, -{"lineNum":" 162","line":" def mul(p : Point, s : Num | BigInt) : Point","class":"lineCov","hits":"4","order":"37","possible_hits":"4",}, -{"lineNum":" 163","line":" s = s.to_big if s.is_a? Num","class":"lineCov","hits":"1","order":"136","possible_hits":"1",}, -{"lineNum":" 164","line":" if s === 0 || s >= N.to_big","class":"linePartCov","hits":"3","order":"38","possible_hits":"4",}, -{"lineNum":" 165","line":" raise \"Invalid scalar: outside of Secp256k1 field dimension.\"","class":"linePartCov","hits":"1","order":"199","possible_hits":"2",}, +{"lineNum":" 162","line":" def mul(p : Point, s : Num | BigInt) : Point","class":"lineCov","hits":"4","order":"27","possible_hits":"4",}, +{"lineNum":" 163","line":" s = s.to_big if s.is_a? Num","class":"lineCov","hits":"1","order":"195","possible_hits":"1",}, +{"lineNum":" 164","line":" if s === 0 || s >= N.to_big","class":"linePartCov","hits":"3","order":"28","possible_hits":"4",}, +{"lineNum":" 165","line":" raise \"Invalid scalar: outside of Secp256k1 field dimension.\"","class":"linePartCov","hits":"1","order":"247","possible_hits":"2",}, {"lineNum":" 166","line":" end"}, -{"lineNum":" 167","line":" s_bin = s.to_s 2","class":"lineCov","hits":"2","order":"39","possible_hits":"2",}, -{"lineNum":" 168","line":" q = p","class":"lineCov","hits":"2","order":"40","possible_hits":"2",}, +{"lineNum":" 167","line":" s_bin = s.to_s 2","class":"lineCov","hits":"2","order":"29","possible_hits":"2",}, +{"lineNum":" 168","line":" q = p","class":"lineCov","hits":"2","order":"30","possible_hits":"2",}, {"lineNum":" 169","line":" s_bin.each_char_with_index do |char, index|"}, -{"lineNum":" 170","line":" next if index === 0","class":"linePartCov","hits":"2","order":"41","possible_hits":"6",}, -{"lineNum":" 171","line":" q = double q","class":"linePartCov","hits":"2","order":"43","possible_hits":"4",}, -{"lineNum":" 172","line":" if char === \'1\'","class":"linePartCov","hits":"4","order":"81","possible_hits":"8",}, -{"lineNum":" 173","line":" q = add q, p","class":"linePartCov","hits":"4","order":"42","possible_hits":"8",}, +{"lineNum":" 170","line":" next if index === 0","class":"linePartCov","hits":"2","order":"31","possible_hits":"6",}, +{"lineNum":" 171","line":" q = double q","class":"linePartCov","hits":"2","order":"33","possible_hits":"4",}, +{"lineNum":" 172","line":" if char === \'1\'","class":"linePartCov","hits":"4","order":"71","possible_hits":"8",}, +{"lineNum":" 173","line":" q = add q, p","class":"linePartCov","hits":"4","order":"32","possible_hits":"8",}, {"lineNum":" 174","line":" end"}, {"lineNum":" 175","line":" end"}, {"lineNum":" 176","line":" q"}, @@ -179,5 +179,5 @@ var data = {lines:[ {"lineNum":" 178","line":"end"}, ]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 56, "covered" : 56,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 56, "covered" : 56,}; var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/data/amber.png b/.github/coverage/run_coverage.1398bb7a/data/amber.png similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/amber.png rename to .github/coverage/run_coverage.1398bb7a/data/amber.png diff --git a/.github/coverage/run_coverage.78460cc2/data/bcov.css b/.github/coverage/run_coverage.1398bb7a/data/bcov.css similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/bcov.css rename to .github/coverage/run_coverage.1398bb7a/data/bcov.css diff --git a/.github/coverage/run_coverage.78460cc2/data/glass.png b/.github/coverage/run_coverage.1398bb7a/data/glass.png similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/glass.png rename to .github/coverage/run_coverage.1398bb7a/data/glass.png diff --git a/.github/coverage/run_coverage.78460cc2/data/js/handlebars.js b/.github/coverage/run_coverage.1398bb7a/data/js/handlebars.js similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/js/handlebars.js rename to .github/coverage/run_coverage.1398bb7a/data/js/handlebars.js diff --git a/.github/coverage/run_coverage.78460cc2/data/js/jquery.min.js b/.github/coverage/run_coverage.1398bb7a/data/js/jquery.min.js similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/js/jquery.min.js rename to .github/coverage/run_coverage.1398bb7a/data/js/jquery.min.js diff --git a/.github/coverage/run_coverage.78460cc2/data/js/jquery.tablesorter.widgets.min.js b/.github/coverage/run_coverage.1398bb7a/data/js/jquery.tablesorter.widgets.min.js similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/js/jquery.tablesorter.widgets.min.js rename to .github/coverage/run_coverage.1398bb7a/data/js/jquery.tablesorter.widgets.min.js diff --git a/.github/coverage/run_coverage.78460cc2/data/js/kcov.js b/.github/coverage/run_coverage.1398bb7a/data/js/kcov.js similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/js/kcov.js rename to .github/coverage/run_coverage.1398bb7a/data/js/kcov.js diff --git a/.github/coverage/run_coverage.78460cc2/data/js/tablesorter.min.js b/.github/coverage/run_coverage.1398bb7a/data/js/tablesorter.min.js similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/js/tablesorter.min.js rename to .github/coverage/run_coverage.1398bb7a/data/js/tablesorter.min.js diff --git a/.github/coverage/run_coverage.78460cc2/data/tablesorter-theme.css b/.github/coverage/run_coverage.1398bb7a/data/tablesorter-theme.css similarity index 100% rename from .github/coverage/run_coverage.78460cc2/data/tablesorter-theme.css rename to .github/coverage/run_coverage.1398bb7a/data/tablesorter-theme.css diff --git a/.github/coverage/run_coverage.78460cc2/glass.png b/.github/coverage/run_coverage.1398bb7a/glass.png similarity index 100% rename from .github/coverage/run_coverage.78460cc2/glass.png rename to .github/coverage/run_coverage.1398bb7a/glass.png diff --git a/.github/coverage/run_coverage.78460cc2/index.html b/.github/coverage/run_coverage.1398bb7a/index.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/index.html rename to .github/coverage/run_coverage.1398bb7a/index.html diff --git a/.github/coverage/run_coverage.1398bb7a/index.js b/.github/coverage/run_coverage.1398bb7a/index.js new file mode 100644 index 0000000..830c8ce --- /dev/null +++ b/.github/coverage/run_coverage.1398bb7a/index.js @@ -0,0 +1,14 @@ +var data = {files:[ +{"link":"context.cr.d435d9a9.html","title":"context.cr","summary_name":"[...]/secp256k1.cr/src/secp256k1/context.cr","covered_class":"lineCov","covered":"92.9","covered_lines":"26","uncovered_lines":"2","total_lines" : "28"}, +{"link":"bitcoin.cr.6170de2.html","title":"bitcoin.cr","summary_name":"[...]/secp256k1.cr/src/bitcoin.cr","covered_class":"lineCov","covered":"95.5","covered_lines":"42","uncovered_lines":"2","total_lines" : "44"}, +{"link":"util.cr.e684f666.html","title":"util.cr","summary_name":"[...]/secp256k1.cr/src/secp256k1/util.cr","covered_class":"lineCov","covered":"93.2","covered_lines":"41","uncovered_lines":"3","total_lines" : "44"}, +{"link":"curve.cr.f05213da.html","title":"curve.cr","summary_name":"[...]/secp256k1.cr/src/secp256k1/curve.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"56","uncovered_lines":"0","total_lines" : "56"}, +{"link":"point.cr.10ecf873.html","title":"point.cr","summary_name":"[...]/secp256k1.cr/src/secp256k1/point.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"36","uncovered_lines":"0","total_lines" : "36"}, +{"link":"key.cr.80fcd549.html","title":"key.cr","summary_name":"[...]/secp256k1.cr/src/secp256k1/key.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"16","uncovered_lines":"0","total_lines" : "16"}, +{"link":"num.cr.6faa13b0.html","title":"num.cr","summary_name":"[...]/secp256k1.cr/src/secp256k1/num.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"47","uncovered_lines":"0","total_lines" : "47"}, +{"link":"signature.cr.25065a1d.html","title":"signature.cr","summary_name":"[...]/secp256k1.cr/src/secp256k1/signature.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"6","uncovered_lines":"0","total_lines" : "6"}, +{"link":"secp256k1.cr.30592eb4.html","title":"secp256k1.cr","summary_name":"[...]/secp256k1.cr/src/secp256k1.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"5","uncovered_lines":"0","total_lines" : "5"}, +]}; +var percent_low = 25;var percent_high = 75; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 282, "covered" : 275,}; +var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/key.cr.80fcd549.html b/.github/coverage/run_coverage.1398bb7a/key.cr.80fcd549.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/key.cr.80fcd549.html rename to .github/coverage/run_coverage.1398bb7a/key.cr.80fcd549.html diff --git a/.github/coverage/run_coverage.78460cc2/key.cr.80fcd549.js b/.github/coverage/run_coverage.1398bb7a/key.cr.80fcd549.js similarity index 90% rename from .github/coverage/run_coverage.78460cc2/key.cr.80fcd549.js rename to .github/coverage/run_coverage.1398bb7a/key.cr.80fcd549.js index b6c4751..91a7acb 100644 --- a/.github/coverage/run_coverage.78460cc2/key.cr.80fcd549.js +++ b/.github/coverage/run_coverage.1398bb7a/key.cr.80fcd549.js @@ -21,9 +21,9 @@ var data = {lines:[ {"lineNum":" 20","line":"# * `public_key` (`Point`): the point on the elliptic curve representing the public key."}, {"lineNum":" 21","line":"class Secp256k1::Key"}, {"lineNum":" 22","line":" # The secret number representing the private key."}, -{"lineNum":" 23","line":" property private_key : Num"}, +{"lineNum":" 23","line":" getter private_key : Num"}, {"lineNum":" 24","line":" # The point on the elliptic curve representing the public key."}, -{"lineNum":" 25","line":" property public_key : Point"}, +{"lineNum":" 25","line":" getter public_key : Point"}, {"lineNum":" 26","line":""}, {"lineNum":" 27","line":" # Creates a new, random `Secp256k1` keypair."}, {"lineNum":" 28","line":" #"}, @@ -44,9 +44,9 @@ var data = {lines:[ {"lineNum":" 43","line":" # # @dec=58444189335609256006902338825877424261513225250255958585656342678587884156524,"}, {"lineNum":" 44","line":" # # @bin=Bytes[129, 54, 61, 41, 142, 74, 64, 235, 203, 19, 241, 175, 168, 90, 11, 148, 185, 103, 242, 67, 238, 89, 165, 144, 16, 203, 93, 234, 240, 215, 182, 108]>>>"}, {"lineNum":" 45","line":" # ```"}, -{"lineNum":" 46","line":" def initialize","class":"lineCov","hits":"3","order":"167","possible_hits":"3",}, -{"lineNum":" 47","line":" @private_key = Num.new","class":"lineCov","hits":"1","order":"168","possible_hits":"1",}, -{"lineNum":" 48","line":" @public_key = Point.new @private_key","class":"lineCov","hits":"1","order":"178","possible_hits":"1",}, +{"lineNum":" 46","line":" def initialize","class":"lineCov","hits":"3","order":"226","possible_hits":"3",}, +{"lineNum":" 47","line":" @private_key = Num.new","class":"lineCov","hits":"1","order":"227","possible_hits":"1",}, +{"lineNum":" 48","line":" @public_key = Point.new @private_key","class":"lineCov","hits":"1","order":"237","possible_hits":"1",}, {"lineNum":" 49","line":" end"}, {"lineNum":" 50","line":""}, {"lineNum":" 51","line":" # Creates a public-private keypair from an existing private key."}, @@ -72,9 +72,9 @@ var data = {lines:[ {"lineNum":" 71","line":" # # @dec=58444189335609256006902338825877424261513225250255958585656342678587884156524,"}, {"lineNum":" 72","line":" # # @bin=Bytes[129, 54, 61, 41, 142, 74, 64, 235, 203, 19, 241, 175, 168, 90, 11, 148, 185, 103, 242, 67, 238, 89, 165, 144, 16, 203, 93, 234, 240, 215, 182, 108]>>>"}, {"lineNum":" 73","line":" # ```"}, -{"lineNum":" 74","line":" def initialize(priv : Num)","class":"lineCov","hits":"3","order":"32","possible_hits":"3",}, -{"lineNum":" 75","line":" @private_key = priv","class":"lineCov","hits":"1","order":"33","possible_hits":"1",}, -{"lineNum":" 76","line":" @public_key = Point.new @private_key","class":"lineCov","hits":"1","order":"34","possible_hits":"1",}, +{"lineNum":" 74","line":" def initialize(priv : Num)","class":"lineCov","hits":"3","order":"22","possible_hits":"3",}, +{"lineNum":" 75","line":" @private_key = priv","class":"lineCov","hits":"1","order":"23","possible_hits":"1",}, +{"lineNum":" 76","line":" @public_key = Point.new @private_key","class":"lineCov","hits":"1","order":"24","possible_hits":"1",}, {"lineNum":" 77","line":" end"}, {"lineNum":" 78","line":""}, {"lineNum":" 79","line":" # Returns the private key as hexadecimal string literal."}, @@ -83,8 +83,8 @@ var data = {lines:[ {"lineNum":" 82","line":" # Key.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_hex"}, {"lineNum":" 83","line":" # # => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\""}, {"lineNum":" 84","line":" # ```"}, -{"lineNum":" 85","line":" def private_hex : String","class":"lineCov","hits":"2","order":"179","possible_hits":"2",}, -{"lineNum":" 86","line":" @private_key.to_zpadded_hex","class":"lineCov","hits":"1","order":"180","possible_hits":"1",}, +{"lineNum":" 85","line":" def private_hex : String","class":"lineCov","hits":"2","order":"161","possible_hits":"2",}, +{"lineNum":" 86","line":" @private_key.to_zpadded_hex","class":"lineCov","hits":"1","order":"162","possible_hits":"1",}, {"lineNum":" 87","line":" end"}, {"lineNum":" 88","line":""}, {"lineNum":" 89","line":" # Returns the private key as binary byte slice."}, @@ -93,8 +93,8 @@ var data = {lines:[ {"lineNum":" 92","line":" # Key.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_bytes"}, {"lineNum":" 93","line":" # # => Bytes[60, 207, 132, 130, 12, 32, 213, 232, 197, 54, 186, 132, 197, 43, 164, 16, 55, 91, 41, 177, 129, 43, 95, 126, 114, 36, 69, 201, 105, 160, 251, 48]"}, {"lineNum":" 94","line":" # ```"}, -{"lineNum":" 95","line":" def private_bytes : Bytes","class":"lineCov","hits":"2","order":"181","possible_hits":"2",}, -{"lineNum":" 96","line":" @private_key.to_zpadded_bytes","class":"lineCov","hits":"1","order":"182","possible_hits":"1",}, +{"lineNum":" 95","line":" def private_bytes : Bytes","class":"lineCov","hits":"2","order":"238","possible_hits":"2",}, +{"lineNum":" 96","line":" @private_key.to_zpadded_bytes","class":"lineCov","hits":"1","order":"239","possible_hits":"1",}, {"lineNum":" 97","line":" end"}, {"lineNum":" 98","line":""}, {"lineNum":" 99","line":" # Returns the public key as uncompressed, hexadecimal string literal."}, @@ -103,8 +103,8 @@ var data = {lines:[ {"lineNum":" 102","line":" # Key.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex"}, {"lineNum":" 103","line":" # # => \"04cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba281363d298e4a40ebcb13f1afa85a0b94b967f243ee59a59010cb5deaf0d7b66c\""}, {"lineNum":" 104","line":" # ```"}, -{"lineNum":" 105","line":" def public_hex : String","class":"lineCov","hits":"2","order":"186","possible_hits":"2",}, -{"lineNum":" 106","line":" @public_key.uncompressed","class":"lineCov","hits":"1","order":"187","possible_hits":"1",}, +{"lineNum":" 105","line":" def public_hex : String","class":"lineCov","hits":"2","order":"240","possible_hits":"2",}, +{"lineNum":" 106","line":" @public_key.uncompressed","class":"lineCov","hits":"1","order":"241","possible_hits":"1",}, {"lineNum":" 107","line":" end"}, {"lineNum":" 108","line":""}, {"lineNum":" 109","line":" # Returns the public key as compressed, hexadecimal string literal."}, @@ -123,8 +123,8 @@ var data = {lines:[ {"lineNum":" 122","line":" # Key.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes"}, {"lineNum":" 123","line":" # # => Bytes[4, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162, 129, 54, 61, 41, 142, 74, 64, 235, 203, 19, 241, 175, 168, 90, 11, 148, 185, 103, 242, 67, 238, 89, 165, 144, 16, 203, 93, 234, 240, 215, 182, 108]"}, {"lineNum":" 124","line":" # ```"}, -{"lineNum":" 125","line":" def public_bytes : Bytes","class":"lineCov","hits":"2","order":"188","possible_hits":"2",}, -{"lineNum":" 126","line":" Num.new(@public_key.uncompressed).to_bytes","class":"lineCov","hits":"1","order":"189","possible_hits":"1",}, +{"lineNum":" 125","line":" def public_bytes : Bytes","class":"lineCov","hits":"2","order":"100","possible_hits":"2",}, +{"lineNum":" 126","line":" Num.new(@public_key.uncompressed).to_bytes","class":"lineCov","hits":"1","order":"101","possible_hits":"1",}, {"lineNum":" 127","line":" end"}, {"lineNum":" 128","line":""}, {"lineNum":" 129","line":" # Returns the public key as compressed, binary byte slice."}, @@ -133,11 +133,11 @@ var data = {lines:[ {"lineNum":" 132","line":" # Key.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes_compressed"}, {"lineNum":" 133","line":" # # => Bytes[2, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162]"}, {"lineNum":" 134","line":" # ```"}, -{"lineNum":" 135","line":" def public_bytes_compressed : Bytes"}, -{"lineNum":" 136","line":" Num.new(@public_key.compressed).to_bytes"}, +{"lineNum":" 135","line":" def public_bytes_compressed : Bytes","class":"lineCov","hits":"2","order":"149","possible_hits":"2",}, +{"lineNum":" 136","line":" Num.new(@public_key.compressed).to_bytes","class":"lineCov","hits":"1","order":"150","possible_hits":"1",}, {"lineNum":" 137","line":" end"}, {"lineNum":" 138","line":"end"}, ]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 14, "covered" : 14,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 16, "covered" : 16,}; var merged_data = []; diff --git a/.github/coverage/run_coverage.1398bb7a/metadata/06170de2 b/.github/coverage/run_coverage.1398bb7a/metadata/06170de2 new file mode 100644 index 0000000..5940729 Binary files /dev/null and b/.github/coverage/run_coverage.1398bb7a/metadata/06170de2 differ diff --git a/.github/coverage/run_coverage.1398bb7a/metadata/10ecf873 b/.github/coverage/run_coverage.1398bb7a/metadata/10ecf873 new file mode 100644 index 0000000..bfbdf7a Binary files /dev/null and b/.github/coverage/run_coverage.1398bb7a/metadata/10ecf873 differ diff --git a/.github/coverage/run_coverage.78460cc2/metadata/25065a1d b/.github/coverage/run_coverage.1398bb7a/metadata/25065a1d similarity index 71% rename from .github/coverage/run_coverage.78460cc2/metadata/25065a1d rename to .github/coverage/run_coverage.1398bb7a/metadata/25065a1d index d6174f6..d6defa2 100644 Binary files a/.github/coverage/run_coverage.78460cc2/metadata/25065a1d and b/.github/coverage/run_coverage.1398bb7a/metadata/25065a1d differ diff --git a/.github/coverage/run_coverage.78460cc2/metadata/30592eb4 b/.github/coverage/run_coverage.1398bb7a/metadata/30592eb4 similarity index 67% rename from .github/coverage/run_coverage.78460cc2/metadata/30592eb4 rename to .github/coverage/run_coverage.1398bb7a/metadata/30592eb4 index 94f65a0..ee48322 100644 Binary files a/.github/coverage/run_coverage.78460cc2/metadata/30592eb4 and b/.github/coverage/run_coverage.1398bb7a/metadata/30592eb4 differ diff --git a/.github/coverage/run_coverage.1398bb7a/metadata/6faa13b0 b/.github/coverage/run_coverage.1398bb7a/metadata/6faa13b0 new file mode 100644 index 0000000..e9a4c89 Binary files /dev/null and b/.github/coverage/run_coverage.1398bb7a/metadata/6faa13b0 differ diff --git a/.github/coverage/run_coverage.1398bb7a/metadata/80fcd549 b/.github/coverage/run_coverage.1398bb7a/metadata/80fcd549 new file mode 100644 index 0000000..c93e8ac Binary files /dev/null and b/.github/coverage/run_coverage.1398bb7a/metadata/80fcd549 differ diff --git a/.github/coverage/run_coverage.78460cc2/metadata/d435d9a9 b/.github/coverage/run_coverage.1398bb7a/metadata/d435d9a9 similarity index 90% rename from .github/coverage/run_coverage.78460cc2/metadata/d435d9a9 rename to .github/coverage/run_coverage.1398bb7a/metadata/d435d9a9 index b3fc577..4097142 100644 Binary files a/.github/coverage/run_coverage.78460cc2/metadata/d435d9a9 and b/.github/coverage/run_coverage.1398bb7a/metadata/d435d9a9 differ diff --git a/.github/coverage/run_coverage.1398bb7a/metadata/e684f666 b/.github/coverage/run_coverage.1398bb7a/metadata/e684f666 new file mode 100644 index 0000000..50bfda1 Binary files /dev/null and b/.github/coverage/run_coverage.1398bb7a/metadata/e684f666 differ diff --git a/.github/coverage/run_coverage.78460cc2/metadata/f05213da b/.github/coverage/run_coverage.1398bb7a/metadata/f05213da similarity index 94% rename from .github/coverage/run_coverage.78460cc2/metadata/f05213da rename to .github/coverage/run_coverage.1398bb7a/metadata/f05213da index 1fd9524..121041c 100644 Binary files a/.github/coverage/run_coverage.78460cc2/metadata/f05213da and b/.github/coverage/run_coverage.1398bb7a/metadata/f05213da differ diff --git a/.github/coverage/run_coverage.78460cc2/num.cr.6faa13b0.html b/.github/coverage/run_coverage.1398bb7a/num.cr.6faa13b0.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/num.cr.6faa13b0.html rename to .github/coverage/run_coverage.1398bb7a/num.cr.6faa13b0.html diff --git a/.github/coverage/run_coverage.78460cc2/num.cr.6faa13b0.js b/.github/coverage/run_coverage.1398bb7a/num.cr.6faa13b0.js similarity index 87% rename from .github/coverage/run_coverage.78460cc2/num.cr.6faa13b0.js rename to .github/coverage/run_coverage.1398bb7a/num.cr.6faa13b0.js index c11a725..f13a505 100644 --- a/.github/coverage/run_coverage.78460cc2/num.cr.6faa13b0.js +++ b/.github/coverage/run_coverage.1398bb7a/num.cr.6faa13b0.js @@ -25,11 +25,11 @@ var data = {lines:[ {"lineNum":" 24","line":"# * `bin` (`Bytes`): the binary bytes-slice represenation of the number."}, {"lineNum":" 25","line":"class Secp256k1::Num"}, {"lineNum":" 26","line":" # The hexadecimal string representation of the number."}, -{"lineNum":" 27","line":" property hex : String"}, +{"lineNum":" 27","line":" getter hex : String"}, {"lineNum":" 28","line":" # The decimal big-integer representation of the number."}, -{"lineNum":" 29","line":" property dec : BigInt"}, +{"lineNum":" 29","line":" getter dec : BigInt"}, {"lineNum":" 30","line":" # The binary bytes-slice represenation of the number."}, -{"lineNum":" 31","line":" property bin : Slice(UInt8)"}, +{"lineNum":" 31","line":" getter bin : Slice(UInt8)"}, {"lineNum":" 32","line":""}, {"lineNum":" 33","line":" # Creates a random number using `Random::Secure` that can be used as"}, {"lineNum":" 34","line":" # a secret (private key)."}, @@ -41,16 +41,16 @@ var data = {lines:[ {"lineNum":" 40","line":" # # @dec=39142835565766237398843902819171565157710677457569850027793715608438337348717,"}, {"lineNum":" 41","line":" # # @bin=Bytes[86, 138, 15, 80, 91, 222, 144, 45, 180, 166, 175, 210, 7, 199, 148, 199, 132, 95, 231, 113, 93, 165, 153, 155, 178, 118, 212, 83, 199, 2, 164, 109]>"}, {"lineNum":" 42","line":" # ```"}, -{"lineNum":" 43","line":" def initialize","class":"lineCov","hits":"3","order":"169","possible_hits":"3",}, -{"lineNum":" 44","line":" hex = \"0\"","class":"lineCov","hits":"1","order":"170","possible_hits":"1",}, -{"lineNum":" 45","line":" key = 0","class":"lineCov","hits":"1","order":"171","possible_hits":"1",}, -{"lineNum":" 46","line":" until key > 0 && key < N.to_big","class":"lineCov","hits":"2","order":"172","possible_hits":"2",}, -{"lineNum":" 47","line":" hex = Random::Secure.hex 32","class":"lineCov","hits":"1","order":"173","possible_hits":"1",}, -{"lineNum":" 48","line":" key = BigInt.new hex, 16","class":"lineCov","hits":"1","order":"174","possible_hits":"1",}, +{"lineNum":" 43","line":" def initialize","class":"lineCov","hits":"3","order":"228","possible_hits":"3",}, +{"lineNum":" 44","line":" hex = \"0\"","class":"lineCov","hits":"1","order":"229","possible_hits":"1",}, +{"lineNum":" 45","line":" key = 0","class":"lineCov","hits":"1","order":"230","possible_hits":"1",}, +{"lineNum":" 46","line":" until key > 0 && key < N.to_big","class":"lineCov","hits":"2","order":"231","possible_hits":"2",}, +{"lineNum":" 47","line":" hex = Random::Secure.hex 32","class":"lineCov","hits":"1","order":"232","possible_hits":"1",}, +{"lineNum":" 48","line":" key = BigInt.new hex, 16","class":"lineCov","hits":"1","order":"233","possible_hits":"1",}, {"lineNum":" 49","line":" end"}, -{"lineNum":" 50","line":" @hex = hex","class":"linePartCov","hits":"1","order":"175","possible_hits":"2",}, -{"lineNum":" 51","line":" @dec = BigInt.new key","class":"linePartCov","hits":"1","order":"176","possible_hits":"2",}, -{"lineNum":" 52","line":" @bin = hex.hexbytes","class":"lineCov","hits":"1","order":"177","possible_hits":"1",}, +{"lineNum":" 50","line":" @hex = hex","class":"linePartCov","hits":"1","order":"234","possible_hits":"2",}, +{"lineNum":" 51","line":" @dec = BigInt.new key","class":"linePartCov","hits":"1","order":"235","possible_hits":"2",}, +{"lineNum":" 52","line":" @bin = hex.hexbytes","class":"lineCov","hits":"1","order":"236","possible_hits":"1",}, {"lineNum":" 53","line":" end"}, {"lineNum":" 54","line":""}, {"lineNum":" 55","line":" # Creates a number from a hexadecimal string literal."}, @@ -85,12 +85,12 @@ var data = {lines:[ {"lineNum":" 84","line":" # # @dec=39142835565766237398843902819171565157710677457569850027793715608438337348717,"}, {"lineNum":" 85","line":" # # @bin=Bytes[86, 138, 15, 80, 91, 222, 144, 45, 180, 166, 175, 210, 7, 199, 148, 199, 132, 95, 231, 113, 93, 165, 153, 155, 178, 118, 212, 83, 199, 2, 164, 109]>"}, {"lineNum":" 86","line":" # ```"}, -{"lineNum":" 87","line":" def initialize(num : BigInt)","class":"lineCov","hits":"4","order":"51","possible_hits":"4",}, -{"lineNum":" 88","line":" hex = num.to_s 16","class":"lineCov","hits":"1","order":"52","possible_hits":"1",}, -{"lineNum":" 89","line":" hex = \"0#{hex}\" if hex.size % 2 != 0","class":"lineCov","hits":"1","order":"53","possible_hits":"1",}, -{"lineNum":" 90","line":" @hex = hex","class":"lineCov","hits":"1","order":"54","possible_hits":"1",}, -{"lineNum":" 91","line":" @dec = num","class":"lineCov","hits":"1","order":"55","possible_hits":"1",}, -{"lineNum":" 92","line":" @bin = hex.hexbytes","class":"lineCov","hits":"1","order":"56","possible_hits":"1",}, +{"lineNum":" 87","line":" def initialize(num : BigInt)","class":"lineCov","hits":"4","order":"41","possible_hits":"4",}, +{"lineNum":" 88","line":" hex = num.to_s 16","class":"lineCov","hits":"1","order":"42","possible_hits":"1",}, +{"lineNum":" 89","line":" hex = \"0#{hex}\" if hex.size % 2 != 0","class":"lineCov","hits":"1","order":"43","possible_hits":"1",}, +{"lineNum":" 90","line":" @hex = hex","class":"lineCov","hits":"1","order":"44","possible_hits":"1",}, +{"lineNum":" 91","line":" @dec = num","class":"lineCov","hits":"1","order":"45","possible_hits":"1",}, +{"lineNum":" 92","line":" @bin = hex.hexbytes","class":"lineCov","hits":"1","order":"46","possible_hits":"1",}, {"lineNum":" 93","line":" end"}, {"lineNum":" 94","line":""}, {"lineNum":" 95","line":" # Creates a number from a binary bytes slice."}, @@ -105,10 +105,10 @@ var data = {lines:[ {"lineNum":" 104","line":" # # @dec=39142835565766237398843902819171565157710677457569850027793715608438337348717,"}, {"lineNum":" 105","line":" # # @bin=Bytes[86, 138, 15, 80, 91, 222, 144, 45, 180, 166, 175, 210, 7, 199, 148, 199, 132, 95, 231, 113, 93, 165, 153, 155, 178, 118, 212, 83, 199, 2, 164, 109]>"}, {"lineNum":" 106","line":" # ```"}, -{"lineNum":" 107","line":" def initialize(bin : Slice(UInt8))","class":"lineCov","hits":"4","order":"107","possible_hits":"4",}, -{"lineNum":" 108","line":" @hex = bin.hexstring","class":"lineCov","hits":"1","order":"108","possible_hits":"1",}, -{"lineNum":" 109","line":" @dec = BigInt.new bin.hexstring, 16","class":"lineCov","hits":"1","order":"109","possible_hits":"1",}, -{"lineNum":" 110","line":" @bin = bin","class":"lineCov","hits":"1","order":"110","possible_hits":"1",}, +{"lineNum":" 107","line":" def initialize(bin : Slice(UInt8))","class":"lineCov","hits":"4","order":"108","possible_hits":"4",}, +{"lineNum":" 108","line":" @hex = bin.hexstring","class":"lineCov","hits":"1","order":"109","possible_hits":"1",}, +{"lineNum":" 109","line":" @dec = BigInt.new bin.hexstring, 16","class":"lineCov","hits":"1","order":"110","possible_hits":"1",}, +{"lineNum":" 110","line":" @bin = bin","class":"lineCov","hits":"1","order":"111","possible_hits":"1",}, {"lineNum":" 111","line":" end"}, {"lineNum":" 112","line":""}, {"lineNum":" 113","line":" # Returns an unprefixed hexadecimal string representation."}, @@ -127,8 +127,8 @@ var data = {lines:[ {"lineNum":" 126","line":" # Num.new(Bytes[137]).to_prefixed_hex"}, {"lineNum":" 127","line":" # # => \"0x89\""}, {"lineNum":" 128","line":" # ```"}, -{"lineNum":" 129","line":" def to_prefixed_hex : String","class":"lineCov","hits":"2","order":"191","possible_hits":"2",}, -{"lineNum":" 130","line":" \"0x#{@hex}\"","class":"lineCov","hits":"1","order":"192","possible_hits":"1",}, +{"lineNum":" 129","line":" def to_prefixed_hex : String","class":"lineCov","hits":"2","order":"243","possible_hits":"2",}, +{"lineNum":" 130","line":" \"0x#{@hex}\"","class":"lineCov","hits":"1","order":"244","possible_hits":"1",}, {"lineNum":" 131","line":" end"}, {"lineNum":" 132","line":""}, {"lineNum":" 133","line":" # Returns a z-padded hexadecimal string representation."}, @@ -140,10 +140,10 @@ var data = {lines:[ {"lineNum":" 139","line":" # Num.new(Bytes[137]).to_zpadded_hex"}, {"lineNum":" 140","line":" # # => \"0000000000000000000000000000000000000000000000000000000000000089\""}, {"lineNum":" 141","line":" # ```"}, -{"lineNum":" 142","line":" def to_zpadded_hex(length = 32) : String","class":"lineCov","hits":"4","order":"25","possible_hits":"4",}, -{"lineNum":" 143","line":" zpadded_hex = @hex","class":"lineCov","hits":"1","order":"26","possible_hits":"1",}, -{"lineNum":" 144","line":" while zpadded_hex.size < length * 2","class":"linePartCov","hits":"1","order":"27","possible_hits":"2",}, -{"lineNum":" 145","line":" zpadded_hex = \"0#{zpadded_hex}\"","class":"lineCov","hits":"1","order":"193","possible_hits":"1",}, +{"lineNum":" 142","line":" def to_zpadded_hex(length = 32) : String","class":"lineCov","hits":"4","order":"105","possible_hits":"4",}, +{"lineNum":" 143","line":" zpadded_hex = @hex","class":"lineCov","hits":"1","order":"106","possible_hits":"1",}, +{"lineNum":" 144","line":" while zpadded_hex.size < length * 2","class":"linePartCov","hits":"1","order":"107","possible_hits":"2",}, +{"lineNum":" 145","line":" zpadded_hex = \"0#{zpadded_hex}\"","class":"lineCov","hits":"1","order":"245","possible_hits":"1",}, {"lineNum":" 146","line":" end"}, {"lineNum":" 147","line":" zpadded_hex"}, {"lineNum":" 148","line":" end"}, @@ -177,10 +177,10 @@ var data = {lines:[ {"lineNum":" 176","line":" # Num.new(Bytes[137]).to_zpadded_bytes"}, {"lineNum":" 177","line":" # # => Bytes[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137]"}, {"lineNum":" 178","line":" # ```"}, -{"lineNum":" 179","line":" def to_zpadded_bytes(length = 32) : Bytes","class":"lineCov","hits":"3","order":"183","possible_hits":"3",}, -{"lineNum":" 180","line":" zpadded_bytes = @bin","class":"lineCov","hits":"1","order":"184","possible_hits":"1",}, -{"lineNum":" 181","line":" while zpadded_bytes.size < length","class":"lineCov","hits":"1","order":"185","possible_hits":"1",}, -{"lineNum":" 182","line":" zpadded_bytes = Util.concat_bytes Bytes[0x00], zpadded_bytes","class":"lineCov","hits":"1","order":"190","possible_hits":"1",}, +{"lineNum":" 179","line":" def to_zpadded_bytes(length = 32) : Bytes","class":"lineCov","hits":"3","order":"114","possible_hits":"3",}, +{"lineNum":" 180","line":" zpadded_bytes = @bin","class":"lineCov","hits":"1","order":"115","possible_hits":"1",}, +{"lineNum":" 181","line":" while zpadded_bytes.size < length","class":"lineCov","hits":"1","order":"116","possible_hits":"1",}, +{"lineNum":" 182","line":" zpadded_bytes = Util.concat_bytes Bytes[0x00], zpadded_bytes","class":"lineCov","hits":"1","order":"242","possible_hits":"1",}, {"lineNum":" 183","line":" end"}, {"lineNum":" 184","line":" zpadded_bytes"}, {"lineNum":" 185","line":" end"}, @@ -196,9 +196,9 @@ var data = {lines:[ {"lineNum":" 195","line":" end"}, {"lineNum":" 196","line":""}, {"lineNum":" 197","line":" # Assists to remove a `0x`-hex prefix."}, -{"lineNum":" 198","line":" private def remove_prefix(hex : String) : String","class":"lineCov","hits":"1","order":"195","possible_hits":"1",}, -{"lineNum":" 199","line":" if is_prefixed? hex","class":"lineCov","hits":"1","order":"196","possible_hits":"1",}, -{"lineNum":" 200","line":" return hex[2..-1]","class":"lineCov","hits":"1","order":"197","possible_hits":"1",}, +{"lineNum":" 198","line":" private def remove_prefix(hex : String) : String","class":"lineCov","hits":"1","order":"91","possible_hits":"1",}, +{"lineNum":" 199","line":" if is_prefixed? hex","class":"lineCov","hits":"1","order":"92","possible_hits":"1",}, +{"lineNum":" 200","line":" return hex[2..-1]","class":"lineCov","hits":"1","order":"93","possible_hits":"1",}, {"lineNum":" 201","line":" else"}, {"lineNum":" 202","line":" return hex"}, {"lineNum":" 203","line":" end"}, @@ -207,17 +207,17 @@ var data = {lines:[ {"lineNum":" 206","line":" # Assists to assert wether a `String` is hexadecimal or not."}, {"lineNum":" 207","line":" private def assert_hexadecimal(hex : String) : String","class":"lineCov","hits":"2","order":"4","possible_hits":"2",}, {"lineNum":" 208","line":" if is_prefixed? hex","class":"lineCov","hits":"1","order":"5","possible_hits":"1",}, -{"lineNum":" 209","line":" hex = remove_prefix hex","class":"lineCov","hits":"1","order":"194","possible_hits":"1",}, +{"lineNum":" 209","line":" hex = remove_prefix hex","class":"lineCov","hits":"1","order":"90","possible_hits":"1",}, {"lineNum":" 210","line":" end"}, {"lineNum":" 211","line":" hex_match = /\\A[0-9a-fA-F]*\\z/.match hex","class":"lineCov","hits":"2","order":"9","possible_hits":"2",}, {"lineNum":" 212","line":" unless hex_match.nil?","class":"lineCov","hits":"1","order":"10","possible_hits":"1",}, {"lineNum":" 213","line":" return hex_match.string"}, {"lineNum":" 214","line":" else"}, -{"lineNum":" 215","line":" raise \"Invalid hex data provided: \'#{hex}\'\"","class":"lineCov","hits":"1","order":"198","possible_hits":"1",}, +{"lineNum":" 215","line":" raise \"Invalid hex data provided: \'#{hex}\'\"","class":"lineCov","hits":"1","order":"246","possible_hits":"1",}, {"lineNum":" 216","line":" end"}, {"lineNum":" 217","line":" end"}, {"lineNum":" 218","line":"end"}, ]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 47, "covered" : 47,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 47, "covered" : 47,}; var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/point.cr.10ecf873.html b/.github/coverage/run_coverage.1398bb7a/point.cr.10ecf873.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/point.cr.10ecf873.html rename to .github/coverage/run_coverage.1398bb7a/point.cr.10ecf873.html diff --git a/.github/coverage/run_coverage.78460cc2/point.cr.10ecf873.js b/.github/coverage/run_coverage.1398bb7a/point.cr.10ecf873.js similarity index 86% rename from .github/coverage/run_coverage.78460cc2/point.cr.10ecf873.js rename to .github/coverage/run_coverage.1398bb7a/point.cr.10ecf873.js index aa156ae..c4794a9 100644 --- a/.github/coverage/run_coverage.78460cc2/point.cr.10ecf873.js +++ b/.github/coverage/run_coverage.1398bb7a/point.cr.10ecf873.js @@ -82,10 +82,10 @@ var data = {lines:[ {"lineNum":" 81","line":" # # @dec=15358791661898278541670676806913272995387450360720708081975214114817468371819,"}, {"lineNum":" 82","line":" # # @bin=Bytes[33, 244, 196, 156, 254, 144, 218, 57, 194, 84, 165, 27, 142, 232, 175, 205, 216, 192, 45, 213, 102, 241, 53, 130, 194, 62, 16, 76, 126, 213, 147, 107]>>"}, {"lineNum":" 83","line":" # ```"}, -{"lineNum":" 84","line":" def initialize(priv : Num)","class":"lineCov","hits":"3","order":"35","possible_hits":"3",}, -{"lineNum":" 85","line":" pub = Curve.mul G, priv.to_big","class":"lineCov","hits":"1","order":"36","possible_hits":"1",}, -{"lineNum":" 86","line":" @x = pub.x","class":"lineCov","hits":"1","order":"97","possible_hits":"1",}, -{"lineNum":" 87","line":" @y = pub.y","class":"lineCov","hits":"1","order":"98","possible_hits":"1",}, +{"lineNum":" 84","line":" def initialize(priv : Num)","class":"lineCov","hits":"3","order":"25","possible_hits":"3",}, +{"lineNum":" 85","line":" pub = Curve.mul G, priv.to_big","class":"lineCov","hits":"1","order":"26","possible_hits":"1",}, +{"lineNum":" 86","line":" @x = pub.x","class":"lineCov","hits":"1","order":"87","possible_hits":"1",}, +{"lineNum":" 87","line":" @y = pub.y","class":"lineCov","hits":"1","order":"88","possible_hits":"1",}, {"lineNum":" 88","line":" end"}, {"lineNum":" 89","line":""}, {"lineNum":" 90","line":" # Provides a public point in the two-dimensional space on the given `Secp256k1`"}, @@ -107,34 +107,34 @@ var data = {lines:[ {"lineNum":" 106","line":" # # @dec=15358791661898278541670676806913272995387450360720708081975214114817468371819,"}, {"lineNum":" 107","line":" # # @bin=Bytes[33, 244, 196, 156, 254, 144, 218, 57, 194, 84, 165, 27, 142, 232, 175, 205, 216, 192, 45, 213, 102, 241, 53, 130, 194, 62, 16, 76, 126, 213, 147, 107]>>"}, {"lineNum":" 108","line":" # ```"}, -{"lineNum":" 109","line":" def initialize(pub : String)","class":"lineCov","hits":"4","order":"200","possible_hits":"4",}, -{"lineNum":" 110","line":" case pub.size","class":"lineCov","hits":"1","order":"201","possible_hits":"1",}, -{"lineNum":" 111","line":" when 130, 128","class":"lineCov","hits":"2","order":"202","possible_hits":"2",}, -{"lineNum":" 112","line":" pub = pub[2, 128] if pub.size === 130","class":"lineCov","hits":"2","order":"203","possible_hits":"2",}, -{"lineNum":" 113","line":" @x = Num.new pub[0, 64]","class":"lineCov","hits":"1","order":"204","possible_hits":"1",}, -{"lineNum":" 114","line":" @y = Num.new pub[64, 64]","class":"lineCov","hits":"1","order":"205","possible_hits":"1",}, -{"lineNum":" 115","line":" when 66","class":"lineCov","hits":"2","order":"207","possible_hits":"2",}, -{"lineNum":" 116","line":" prefix = pub[0, 2]","class":"lineCov","hits":"1","order":"208","possible_hits":"1",}, -{"lineNum":" 117","line":" if prefix === \"02\" || prefix === \"03\"","class":"lineCov","hits":"2","order":"209","possible_hits":"2",}, -{"lineNum":" 118","line":" prime = P.to_big","class":"lineCov","hits":"1","order":"210","possible_hits":"1",}, -{"lineNum":" 119","line":" x = Num.new(pub[2, 64]).to_big","class":"lineCov","hits":"1","order":"211","possible_hits":"1",}, +{"lineNum":" 109","line":" def initialize(pub : String)","class":"lineCov","hits":"4","order":"248","possible_hits":"4",}, +{"lineNum":" 110","line":" case pub.size","class":"lineCov","hits":"1","order":"249","possible_hits":"1",}, +{"lineNum":" 111","line":" when 130, 128","class":"lineCov","hits":"2","order":"250","possible_hits":"2",}, +{"lineNum":" 112","line":" pub = pub[2, 128] if pub.size === 130","class":"lineCov","hits":"2","order":"251","possible_hits":"2",}, +{"lineNum":" 113","line":" @x = Num.new pub[0, 64]","class":"lineCov","hits":"1","order":"252","possible_hits":"1",}, +{"lineNum":" 114","line":" @y = Num.new pub[64, 64]","class":"lineCov","hits":"1","order":"253","possible_hits":"1",}, +{"lineNum":" 115","line":" when 66","class":"lineCov","hits":"2","order":"255","possible_hits":"2",}, +{"lineNum":" 116","line":" prefix = pub[0, 2]","class":"lineCov","hits":"1","order":"256","possible_hits":"1",}, +{"lineNum":" 117","line":" if prefix === \"02\" || prefix === \"03\"","class":"lineCov","hits":"2","order":"257","possible_hits":"2",}, +{"lineNum":" 118","line":" prime = P.to_big","class":"lineCov","hits":"1","order":"258","possible_hits":"1",}, +{"lineNum":" 119","line":" x = Num.new(pub[2, 64]).to_big","class":"lineCov","hits":"1","order":"259","possible_hits":"1",}, {"lineNum":" 120","line":""}, -{"lineNum":" 121","line":" a = x ** 3 % prime","class":"lineCov","hits":"1","order":"212","possible_hits":"1",}, -{"lineNum":" 122","line":" a = (a + 7) % prime","class":"lineCov","hits":"1","order":"213","possible_hits":"1",}, -{"lineNum":" 123","line":" e = ((prime + 1) // 4) % prime","class":"lineCov","hits":"1","order":"214","possible_hits":"1",}, -{"lineNum":" 124","line":" y = BigInt.new","class":"lineCov","hits":"1","order":"215","possible_hits":"1",}, -{"lineNum":" 125","line":" LibGMP.mpz_powm_sec(y, a, e, prime)","class":"lineCov","hits":"1","order":"216","possible_hits":"1",}, +{"lineNum":" 121","line":" a = x ** 3 % prime","class":"lineCov","hits":"1","order":"260","possible_hits":"1",}, +{"lineNum":" 122","line":" a = (a + 7) % prime","class":"lineCov","hits":"1","order":"261","possible_hits":"1",}, +{"lineNum":" 123","line":" e = ((prime + 1) // 4) % prime","class":"lineCov","hits":"1","order":"262","possible_hits":"1",}, +{"lineNum":" 124","line":" y = BigInt.new","class":"lineCov","hits":"1","order":"263","possible_hits":"1",}, +{"lineNum":" 125","line":" LibGMP.mpz_powm_sec(y, a, e, prime)","class":"lineCov","hits":"1","order":"264","possible_hits":"1",}, {"lineNum":" 126","line":""}, -{"lineNum":" 127","line":" y_parity = prefix.to_i - 2","class":"linePartCov","hits":"1","order":"217","possible_hits":"2",}, -{"lineNum":" 128","line":" y = -y % prime if y % 2 != y_parity","class":"lineCov","hits":"1","order":"218","possible_hits":"1",}, +{"lineNum":" 127","line":" y_parity = prefix.to_i - 2","class":"linePartCov","hits":"1","order":"265","possible_hits":"2",}, +{"lineNum":" 128","line":" y = -y % prime if y % 2 != y_parity","class":"lineCov","hits":"1","order":"266","possible_hits":"1",}, {"lineNum":" 129","line":""}, -{"lineNum":" 130","line":" @x = Num.new x","class":"lineCov","hits":"1","order":"219","possible_hits":"1",}, -{"lineNum":" 131","line":" @y = Num.new y","class":"lineCov","hits":"2","order":"220","possible_hits":"2",}, +{"lineNum":" 130","line":" @x = Num.new x","class":"lineCov","hits":"1","order":"267","possible_hits":"1",}, +{"lineNum":" 131","line":" @y = Num.new y","class":"lineCov","hits":"2","order":"268","possible_hits":"2",}, {"lineNum":" 132","line":" else"}, -{"lineNum":" 133","line":" raise \"Invalid prefix for compressed public point: #{prefix}\"","class":"lineCov","hits":"2","order":"221","possible_hits":"2",}, +{"lineNum":" 133","line":" raise \"Invalid prefix for compressed public point: #{prefix}\"","class":"lineCov","hits":"2","order":"269","possible_hits":"2",}, {"lineNum":" 134","line":" end"}, {"lineNum":" 135","line":" else"}, -{"lineNum":" 136","line":" raise \"Unknown public point format (Invalid size: #{pub.size})\"","class":"lineCov","hits":"3","order":"206","possible_hits":"3",}, +{"lineNum":" 136","line":" raise \"Unknown public point format (Invalid size: #{pub.size})\"","class":"lineCov","hits":"3","order":"254","possible_hits":"3",}, {"lineNum":" 137","line":" end"}, {"lineNum":" 138","line":" end"}, {"lineNum":" 139","line":""}, @@ -146,9 +146,9 @@ var data = {lines:[ {"lineNum":" 145","line":" # Point.new(priv).uncompressed"}, {"lineNum":" 146","line":" # # => \"04aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f21f4c49cfe90da39c254a51b8ee8afcdd8c02dd566f13582c23e104c7ed5936b\""}, {"lineNum":" 147","line":" # ```"}, -{"lineNum":" 148","line":" def uncompressed : String","class":"lineCov","hits":"1","order":"22","possible_hits":"1",}, -{"lineNum":" 149","line":" prefix = \"04\"","class":"lineCov","hits":"1","order":"23","possible_hits":"1",}, -{"lineNum":" 150","line":" \"#{prefix}#{@x.to_zpadded_hex}#{@y.to_zpadded_hex}\"","class":"lineCov","hits":"1","order":"24","possible_hits":"1",}, +{"lineNum":" 148","line":" def uncompressed : String","class":"lineCov","hits":"1","order":"102","possible_hits":"1",}, +{"lineNum":" 149","line":" prefix = \"04\"","class":"lineCov","hits":"1","order":"103","possible_hits":"1",}, +{"lineNum":" 150","line":" \"#{prefix}#{@x.to_zpadded_hex}#{@y.to_zpadded_hex}\"","class":"lineCov","hits":"1","order":"104","possible_hits":"1",}, {"lineNum":" 151","line":" end"}, {"lineNum":" 152","line":""}, {"lineNum":" 153","line":" # Returns a prefixed, compressed public key string for the given point"}, @@ -159,13 +159,13 @@ var data = {lines:[ {"lineNum":" 158","line":" # Point.new(priv).compressed"}, {"lineNum":" 159","line":" # # => \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\""}, {"lineNum":" 160","line":" # ```"}, -{"lineNum":" 161","line":" def compressed : String","class":"lineCov","hits":"2","order":"28","possible_hits":"2",}, -{"lineNum":" 162","line":" prefix = 2 + @y.to_big % 2","class":"lineCov","hits":"1","order":"29","possible_hits":"1",}, -{"lineNum":" 163","line":" prefix = \"0#{prefix}\"","class":"lineCov","hits":"1","order":"30","possible_hits":"1",}, -{"lineNum":" 164","line":" \"#{prefix}#{@x.to_zpadded_hex}\"","class":"lineCov","hits":"1","order":"31","possible_hits":"1",}, +{"lineNum":" 161","line":" def compressed : String","class":"lineCov","hits":"2","order":"151","possible_hits":"2",}, +{"lineNum":" 162","line":" prefix = 2 + @y.to_big % 2","class":"lineCov","hits":"1","order":"152","possible_hits":"1",}, +{"lineNum":" 163","line":" prefix = \"0#{prefix}\"","class":"lineCov","hits":"1","order":"153","possible_hits":"1",}, +{"lineNum":" 164","line":" \"#{prefix}#{@x.to_zpadded_hex}\"","class":"lineCov","hits":"1","order":"154","possible_hits":"1",}, {"lineNum":" 165","line":" end"}, {"lineNum":" 166","line":"end"}, ]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 36, "covered" : 36,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 36, "covered" : 36,}; var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/secp256k1.cr.30592eb4.html b/.github/coverage/run_coverage.1398bb7a/secp256k1.cr.30592eb4.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/secp256k1.cr.30592eb4.html rename to .github/coverage/run_coverage.1398bb7a/secp256k1.cr.30592eb4.html diff --git a/.github/coverage/run_coverage.78460cc2/secp256k1.cr.30592eb4.js b/.github/coverage/run_coverage.1398bb7a/secp256k1.cr.30592eb4.js similarity index 98% rename from .github/coverage/run_coverage.78460cc2/secp256k1.cr.30592eb4.js rename to .github/coverage/run_coverage.1398bb7a/secp256k1.cr.30592eb4.js index 55cb109..299756b 100644 --- a/.github/coverage/run_coverage.78460cc2/secp256k1.cr.30592eb4.js +++ b/.github/coverage/run_coverage.1398bb7a/secp256k1.cr.30592eb4.js @@ -52,5 +52,5 @@ var data = {lines:[ {"lineNum":" 51","line":"end"}, ]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 5, "covered" : 5,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 5, "covered" : 5,}; var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/signature.cr.25065a1d.html b/.github/coverage/run_coverage.1398bb7a/signature.cr.25065a1d.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/signature.cr.25065a1d.html rename to .github/coverage/run_coverage.1398bb7a/signature.cr.25065a1d.html diff --git a/.github/coverage/run_coverage.78460cc2/signature.cr.25065a1d.js b/.github/coverage/run_coverage.1398bb7a/signature.cr.25065a1d.js similarity index 92% rename from .github/coverage/run_coverage.78460cc2/signature.cr.25065a1d.js rename to .github/coverage/run_coverage.1398bb7a/signature.cr.25065a1d.js index 3efb683..855bf1c 100644 --- a/.github/coverage/run_coverage.78460cc2/signature.cr.25065a1d.js +++ b/.github/coverage/run_coverage.1398bb7a/signature.cr.25065a1d.js @@ -22,13 +22,13 @@ var data = {lines:[ {"lineNum":" 21","line":"# * `v` (`Num`): the recovery id or `v` value."}, {"lineNum":" 22","line":"class Secp256k1::Signature"}, {"lineNum":" 23","line":" # The `x` coordinate of a random point `R` on the curve."}, -{"lineNum":" 24","line":" property r : Num"}, +{"lineNum":" 24","line":" getter r : Num"}, {"lineNum":" 25","line":""}, {"lineNum":" 26","line":" # The signature proof of a message."}, -{"lineNum":" 27","line":" property s : Num"}, +{"lineNum":" 27","line":" getter s : Num"}, {"lineNum":" 28","line":""}, {"lineNum":" 29","line":" # The recovery id or `v` value."}, -{"lineNum":" 30","line":" property v : Num"}, +{"lineNum":" 30","line":" getter v : Num"}, {"lineNum":" 31","line":""}, {"lineNum":" 32","line":" # Provides an ECDSA Signature containing the random point `r`, the"}, {"lineNum":" 33","line":" # signature proof `s`, and the recovery id or `v` value."}, @@ -57,10 +57,10 @@ var data = {lines:[ {"lineNum":" 56","line":" # # @dec=0,"}, {"lineNum":" 57","line":" # # @bin=Bytes[0]>>"}, {"lineNum":" 58","line":" # ```"}, -{"lineNum":" 59","line":" def initialize(r : Num, s : Num, v : Num)","class":"lineCov","hits":"3","order":"152","possible_hits":"3",}, -{"lineNum":" 60","line":" @r = r","class":"lineCov","hits":"1","order":"153","possible_hits":"1",}, -{"lineNum":" 61","line":" @s = s","class":"lineCov","hits":"1","order":"154","possible_hits":"1",}, -{"lineNum":" 62","line":" @v = v","class":"lineCov","hits":"1","order":"155","possible_hits":"1",}, +{"lineNum":" 59","line":" def initialize(r : Num, s : Num, v : Num)","class":"lineCov","hits":"3","order":"211","possible_hits":"3",}, +{"lineNum":" 60","line":" @r = r","class":"lineCov","hits":"1","order":"212","possible_hits":"1",}, +{"lineNum":" 61","line":" @s = s","class":"lineCov","hits":"1","order":"213","possible_hits":"1",}, +{"lineNum":" 62","line":" @v = v","class":"lineCov","hits":"1","order":"214","possible_hits":"1",}, {"lineNum":" 63","line":" end"}, {"lineNum":" 64","line":""}, {"lineNum":" 65","line":" # Returns a compact `String` containing the concatenated signature"}, @@ -73,11 +73,11 @@ var data = {lines:[ {"lineNum":" 72","line":" # Signature.new(r, s, v).compact"}, {"lineNum":" 73","line":" # # => \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae000\""}, {"lineNum":" 74","line":" # ```"}, -{"lineNum":" 75","line":" def compact : String","class":"lineCov","hits":"2","order":"165","possible_hits":"2",}, -{"lineNum":" 76","line":" \"#{r.to_zpadded_hex}#{s.to_zpadded_hex}#{v.to_hex}\"","class":"lineCov","hits":"1","order":"166","possible_hits":"1",}, +{"lineNum":" 75","line":" def compact : String","class":"lineCov","hits":"2","order":"224","possible_hits":"2",}, +{"lineNum":" 76","line":" \"#{r.to_zpadded_hex}#{s.to_zpadded_hex}#{v.to_hex}\"","class":"lineCov","hits":"1","order":"225","possible_hits":"1",}, {"lineNum":" 77","line":" end"}, {"lineNum":" 78","line":"end"}, ]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 6, "covered" : 6,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 6, "covered" : 6,}; var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/sonarqube.xml b/.github/coverage/run_coverage.1398bb7a/sonarqube.xml similarity index 84% rename from .github/coverage/run_coverage.78460cc2/sonarqube.xml rename to .github/coverage/run_coverage.1398bb7a/sonarqube.xml index fdff24d..5e819c4 100644 --- a/.github/coverage/run_coverage.78460cc2/sonarqube.xml +++ b/.github/coverage/run_coverage.1398bb7a/sonarqube.xml @@ -1,5 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -104,36 +180,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -187,6 +233,8 @@ + + diff --git a/.github/coverage/run_coverage.78460cc2/summary.db b/.github/coverage/run_coverage.1398bb7a/summary.db similarity index 76% rename from .github/coverage/run_coverage.78460cc2/summary.db rename to .github/coverage/run_coverage.1398bb7a/summary.db index 2eb2ee6..a1e3ff8 100644 Binary files a/.github/coverage/run_coverage.78460cc2/summary.db and b/.github/coverage/run_coverage.1398bb7a/summary.db differ diff --git a/.github/coverage/run_coverage.78460cc2/util.cr.e684f666.html b/.github/coverage/run_coverage.1398bb7a/util.cr.e684f666.html similarity index 100% rename from .github/coverage/run_coverage.78460cc2/util.cr.e684f666.html rename to .github/coverage/run_coverage.1398bb7a/util.cr.e684f666.html diff --git a/.github/coverage/run_coverage.78460cc2/util.cr.e684f666.js b/.github/coverage/run_coverage.1398bb7a/util.cr.e684f666.js similarity index 75% rename from .github/coverage/run_coverage.78460cc2/util.cr.e684f666.js rename to .github/coverage/run_coverage.1398bb7a/util.cr.e684f666.js index 96317b3..a265713 100644 --- a/.github/coverage/run_coverage.78460cc2/util.cr.e684f666.js +++ b/.github/coverage/run_coverage.1398bb7a/util.cr.e684f666.js @@ -21,7 +21,7 @@ var data = {lines:[ {"lineNum":" 20","line":" # Operating a Keccak hash on a binary/number or string literal."}, {"lineNum":" 21","line":" #"}, {"lineNum":" 22","line":" # Parameters:"}, -{"lineNum":" 23","line":" # * `data` (`Num | String`): the binary numeric or string literal to be hashed."}, +{"lineNum":" 23","line":" # * `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed."}, {"lineNum":" 24","line":" # * `entropy` (`Int32`): the required entropy (default `256`)."}, {"lineNum":" 25","line":" #"}, {"lineNum":" 26","line":" # Returns a `Num` representing the Keccak hash."}, @@ -33,19 +33,19 @@ var data = {lines:[ {"lineNum":" 32","line":" # Util.keccak(\"0xdeadbeef\").hex"}, {"lineNum":" 33","line":" # # => \"4f440a001006a49f24a7de53c04eca3f79aef851ac58e460c9630d044277c8b0\""}, {"lineNum":" 34","line":" # ```"}, -{"lineNum":" 35","line":" def keccak(data : Num | String, entropy = 256) : Num","class":"lineCov","hits":"6","order":"162","possible_hits":"6",}, -{"lineNum":" 36","line":" keccak = Digest::Keccak3.new entropy","class":"lineCov","hits":"2","order":"163","possible_hits":"2",}, -{"lineNum":" 37","line":" if data.is_a? String"}, -{"lineNum":" 38","line":" return Num.new keccak.update(data).hexdigest","class":"lineCov","hits":"1","order":"164","possible_hits":"1",}, +{"lineNum":" 35","line":" def keccak(data : Num | Bytes | String, entropy = 256) : Num","class":"lineCov","hits":"6","order":"221","possible_hits":"6",}, +{"lineNum":" 36","line":" keccak = Digest::Keccak3.new entropy","class":"lineCov","hits":"2","order":"222","possible_hits":"2",}, +{"lineNum":" 37","line":" if data.is_a? Num"}, +{"lineNum":" 38","line":" return Num.new keccak.update(data.to_bytes).hexdigest","class":"lineCov","hits":"1","order":"270","possible_hits":"1",}, {"lineNum":" 39","line":" else"}, -{"lineNum":" 40","line":" return Num.new keccak.update(data.to_bytes).hexdigest","class":"lineCov","hits":"1","order":"222","possible_hits":"1",}, +{"lineNum":" 40","line":" return Num.new keccak.update(data).hexdigest","class":"lineCov","hits":"1","order":"223","possible_hits":"1",}, {"lineNum":" 41","line":" end"}, {"lineNum":" 42","line":" end"}, {"lineNum":" 43","line":""}, {"lineNum":" 44","line":" # Operating a SHA3 hash on a binary/number or string literal."}, {"lineNum":" 45","line":" #"}, {"lineNum":" 46","line":" # Parameters:"}, -{"lineNum":" 47","line":" # * `data` (`Num | String`): the binary numeric or string literal to be hashed."}, +{"lineNum":" 47","line":" # * `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed."}, {"lineNum":" 48","line":" # * `entropy` (`Int32`): the required entropy (default `256`)."}, {"lineNum":" 49","line":" #"}, {"lineNum":" 50","line":" # Returns a `Num` representing the SHA3 hash."}, @@ -57,19 +57,19 @@ var data = {lines:[ {"lineNum":" 56","line":" # Util.sha3(\"0xdeadbeef\").hex"}, {"lineNum":" 57","line":" # # => \"c12811e13ed75afe3e0945ef34e8a25b9d321a46e131c6463731de25a21b39eb\""}, {"lineNum":" 58","line":" # ```"}, -{"lineNum":" 59","line":" def sha3(data : Num | String, entropy = 256) : Num","class":"lineCov","hits":"6","order":"223","possible_hits":"6",}, -{"lineNum":" 60","line":" sha3 = Digest::SHA3.new entropy","class":"lineCov","hits":"2","order":"224","possible_hits":"2",}, -{"lineNum":" 61","line":" if data.is_a? String"}, -{"lineNum":" 62","line":" return Num.new sha3.update(data).hexdigest","class":"lineCov","hits":"1","order":"225","possible_hits":"1",}, +{"lineNum":" 59","line":" def sha3(data : Num | Bytes | String, entropy = 256) : Num","class":"lineCov","hits":"6","order":"271","possible_hits":"6",}, +{"lineNum":" 60","line":" sha3 = Digest::SHA3.new entropy","class":"lineCov","hits":"2","order":"272","possible_hits":"2",}, +{"lineNum":" 61","line":" if data.is_a? Num"}, +{"lineNum":" 62","line":" return Num.new sha3.update(data.to_bytes).hexdigest","class":"lineCov","hits":"1","order":"274","possible_hits":"1",}, {"lineNum":" 63","line":" else"}, -{"lineNum":" 64","line":" return Num.new sha3.update(data.to_bytes).hexdigest","class":"lineCov","hits":"1","order":"226","possible_hits":"1",}, +{"lineNum":" 64","line":" return Num.new sha3.update(data).hexdigest","class":"lineCov","hits":"1","order":"273","possible_hits":"1",}, {"lineNum":" 65","line":" end"}, {"lineNum":" 66","line":" end"}, {"lineNum":" 67","line":""}, {"lineNum":" 68","line":" # Operating a SHA2-256 hash on a binary/number or string literal."}, {"lineNum":" 69","line":" #"}, {"lineNum":" 70","line":" # Parameters:"}, -{"lineNum":" 71","line":" # * `data` (`Num | String`): the binary numeric or string literal to be hashed."}, +{"lineNum":" 71","line":" # * `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed."}, {"lineNum":" 72","line":" #"}, {"lineNum":" 73","line":" # Returns a `Num` representing the SHA2 hash."}, {"lineNum":" 74","line":" #"}, @@ -80,19 +80,19 @@ var data = {lines:[ {"lineNum":" 79","line":" # Util.sha256(\"0xdeadbeef\").hex"}, {"lineNum":" 80","line":" # # => \"4142710b9b4caaeb000b8e5de271bbebac7f509aab2f5e61d1ed1958bfe6d583\""}, {"lineNum":" 81","line":" # ```"}, -{"lineNum":" 82","line":" def sha256(data : Num | String) : Num","class":"lineCov","hits":"2","order":"99","possible_hits":"2",}, -{"lineNum":" 83","line":" sha2 = OpenSSL::Digest.new \"SHA256\"","class":"lineCov","hits":"2","order":"100","possible_hits":"2",}, -{"lineNum":" 84","line":" if data.is_a? String"}, -{"lineNum":" 85","line":" return Num.new sha2.update(data).final.hexstring","class":"lineCov","hits":"1","order":"101","possible_hits":"1",}, +{"lineNum":" 82","line":" def sha256(data : Num | Bytes | String) : Num","class":"lineCov","hits":"4","order":"117","possible_hits":"4",}, +{"lineNum":" 83","line":" sha2 = OpenSSL::Digest.new \"SHA256\"","class":"lineCov","hits":"3","order":"118","possible_hits":"3",}, +{"lineNum":" 84","line":" if data.is_a? Num"}, +{"lineNum":" 85","line":" return Num.new sha2.update(data.to_bytes).final.hexstring","class":"lineCov","hits":"1","order":"164","possible_hits":"1",}, {"lineNum":" 86","line":" else"}, -{"lineNum":" 87","line":" return Num.new sha2.update(data.to_bytes).final.hexstring","class":"lineCov","hits":"1","order":"227","possible_hits":"1",}, +{"lineNum":" 87","line":" return Num.new sha2.update(data).final.hexstring","class":"lineCov","hits":"2","order":"119","possible_hits":"2",}, {"lineNum":" 88","line":" end"}, {"lineNum":" 89","line":" end"}, {"lineNum":" 90","line":""}, {"lineNum":" 91","line":" # Operating a RIPEMD-160 hash on a binary/number or string literal."}, {"lineNum":" 92","line":" #"}, {"lineNum":" 93","line":" # Parameters:"}, -{"lineNum":" 94","line":" # * `data` (`Num | String`): the binary numeric or string literal to be hashed."}, +{"lineNum":" 94","line":" # * `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed."}, {"lineNum":" 95","line":" #"}, {"lineNum":" 96","line":" # Returns a `Num` representing the RIPEMD hash."}, {"lineNum":" 97","line":" #"}, @@ -103,12 +103,12 @@ var data = {lines:[ {"lineNum":" 102","line":" # Util.ripemd160(\"0xdeadbeef\").hex"}, {"lineNum":" 103","line":" # # => \"4caf817f14e84b564e47afd19966e5d123ee0183\""}, {"lineNum":" 104","line":" # ```"}, -{"lineNum":" 105","line":" def ripemd160(data : Num | String) : Num","class":"lineCov","hits":"2","order":"228","possible_hits":"2",}, -{"lineNum":" 106","line":" ripemd = OpenSSL::Digest.new \"RIPEMD160\"","class":"lineCov","hits":"2","order":"229","possible_hits":"2",}, -{"lineNum":" 107","line":" if data.is_a? String"}, -{"lineNum":" 108","line":" return Num.new ripemd.update(data).final.hexstring","class":"lineCov","hits":"1","order":"231","possible_hits":"1",}, +{"lineNum":" 105","line":" def ripemd160(data : Num | Bytes | String) : Num","class":"lineCov","hits":"4","order":"121","possible_hits":"4",}, +{"lineNum":" 106","line":" ripemd = OpenSSL::Digest.new \"RIPEMD160\"","class":"lineCov","hits":"3","order":"122","possible_hits":"3",}, +{"lineNum":" 107","line":" if data.is_a? Num"}, +{"lineNum":" 108","line":" return Num.new ripemd.update(data.to_bytes).final.hexstring","class":"lineCov","hits":"1","order":"275","possible_hits":"1",}, {"lineNum":" 109","line":" else"}, -{"lineNum":" 110","line":" return Num.new ripemd.update(data.to_bytes).final.hexstring","class":"lineCov","hits":"1","order":"230","possible_hits":"1",}, +{"lineNum":" 110","line":" return Num.new ripemd.update(data).final.hexstring","class":"lineCov","hits":"2","order":"123","possible_hits":"2",}, {"lineNum":" 111","line":" end"}, {"lineNum":" 112","line":" end"}, {"lineNum":" 113","line":""}, @@ -133,28 +133,28 @@ var data = {lines:[ {"lineNum":" 132","line":" # # @dec=83193606619515454920331057246310791124858301167609726617990890481932799590618,"}, {"lineNum":" 133","line":" # # @bin=Bytes[183, 237, 233, 165, 181, 179, 40, 172, 104, 11, 230, 118, 82, 19, 199, 181, 178, 146, 4, 105, 189, 170, 248, 7, 12, 31, 180, 60, 181, 196, 64, 218]>"}, {"lineNum":" 134","line":" # ```"}, -{"lineNum":" 135","line":" def deterministic_k(priv : Num, hash : Num, order = N) : Num","class":"lineCov","hits":"4","order":"104","possible_hits":"4",}, -{"lineNum":" 136","line":" order_size = order.hex.size // 2","class":"lineCov","hits":"1","order":"105","possible_hits":"1",}, -{"lineNum":" 137","line":" v = Num.new Bytes.new order_size, 0x01","class":"lineCov","hits":"1","order":"106","possible_hits":"1",}, -{"lineNum":" 138","line":" k = Num.new Bytes.new order_size, 0x00","class":"lineCov","hits":"1","order":"111","possible_hits":"1",}, -{"lineNum":" 139","line":" concat = Util.concat_bytes v.bin, Bytes[0x00]","class":"lineCov","hits":"2","order":"112","possible_hits":"2",}, -{"lineNum":" 140","line":" concat = Util.concat_bytes concat, priv.bin","class":"lineCov","hits":"3","order":"118","possible_hits":"3",}, -{"lineNum":" 141","line":" concat = Util.concat_bytes concat, hash.bin","class":"lineCov","hits":"3","order":"119","possible_hits":"3",}, -{"lineNum":" 142","line":" k = OpenSSL::HMAC.digest(:sha256, k.bin, concat)","class":"lineCov","hits":"3","order":"120","possible_hits":"3",}, -{"lineNum":" 143","line":" v = OpenSSL::HMAC.digest(:sha256, k, v.bin)","class":"lineCov","hits":"2","order":"121","possible_hits":"2",}, -{"lineNum":" 144","line":" concat = Util.concat_bytes v, Bytes[0x00]","class":"lineCov","hits":"2","order":"122","possible_hits":"2",}, -{"lineNum":" 145","line":" concat = Util.concat_bytes concat, priv.bin","class":"lineCov","hits":"3","order":"123","possible_hits":"3",}, -{"lineNum":" 146","line":" concat = Util.concat_bytes concat, hash.bin","class":"lineCov","hits":"3","order":"124","possible_hits":"3",}, -{"lineNum":" 147","line":" k = OpenSSL::HMAC.digest(:sha256, k, concat)","class":"lineCov","hits":"3","order":"125","possible_hits":"3",}, -{"lineNum":" 148","line":" v = OpenSSL::HMAC.digest(:sha256, k, v)","class":"lineCov","hits":"2","order":"126","possible_hits":"2",}, +{"lineNum":" 135","line":" def deterministic_k(priv : Num, hash : Num, order = N) : Num","class":"lineCov","hits":"4","order":"172","possible_hits":"4",}, +{"lineNum":" 136","line":" order_size = order.hex.size // 2","class":"lineCov","hits":"1","order":"173","possible_hits":"1",}, +{"lineNum":" 137","line":" v = Num.new Bytes.new order_size, 0x01","class":"lineCov","hits":"1","order":"174","possible_hits":"1",}, +{"lineNum":" 138","line":" k = Num.new Bytes.new order_size, 0x00","class":"lineCov","hits":"1","order":"175","possible_hits":"1",}, +{"lineNum":" 139","line":" concat = Util.concat_bytes v.bin, Bytes[0x00]","class":"lineCov","hits":"2","order":"176","possible_hits":"2",}, +{"lineNum":" 140","line":" concat = Util.concat_bytes concat, priv.bin","class":"lineCov","hits":"3","order":"177","possible_hits":"3",}, +{"lineNum":" 141","line":" concat = Util.concat_bytes concat, hash.bin","class":"lineCov","hits":"3","order":"178","possible_hits":"3",}, +{"lineNum":" 142","line":" k = OpenSSL::HMAC.digest(:sha256, k.bin, concat)","class":"lineCov","hits":"3","order":"179","possible_hits":"3",}, +{"lineNum":" 143","line":" v = OpenSSL::HMAC.digest(:sha256, k, v.bin)","class":"lineCov","hits":"2","order":"180","possible_hits":"2",}, +{"lineNum":" 144","line":" concat = Util.concat_bytes v, Bytes[0x00]","class":"lineCov","hits":"2","order":"181","possible_hits":"2",}, +{"lineNum":" 145","line":" concat = Util.concat_bytes concat, priv.bin","class":"lineCov","hits":"3","order":"182","possible_hits":"3",}, +{"lineNum":" 146","line":" concat = Util.concat_bytes concat, hash.bin","class":"lineCov","hits":"3","order":"183","possible_hits":"3",}, +{"lineNum":" 147","line":" k = OpenSSL::HMAC.digest(:sha256, k, concat)","class":"lineCov","hits":"3","order":"184","possible_hits":"3",}, +{"lineNum":" 148","line":" v = OpenSSL::HMAC.digest(:sha256, k, v)","class":"lineCov","hits":"2","order":"185","possible_hits":"2",}, {"lineNum":" 149","line":" while true"}, -{"lineNum":" 150","line":" t = IO::Memory.new.to_slice","class":"lineCov","hits":"1","order":"127","possible_hits":"1",}, -{"lineNum":" 151","line":" while t.size < order_size","class":"lineCov","hits":"2","order":"128","possible_hits":"2",}, -{"lineNum":" 152","line":" v = OpenSSL::HMAC.digest(:sha256, k, v)","class":"lineCov","hits":"3","order":"129","possible_hits":"3",}, -{"lineNum":" 153","line":" t = Util.concat_bytes t, v","class":"lineCov","hits":"2","order":"130","possible_hits":"2",}, +{"lineNum":" 150","line":" t = IO::Memory.new.to_slice","class":"lineCov","hits":"1","order":"186","possible_hits":"1",}, +{"lineNum":" 151","line":" while t.size < order_size","class":"lineCov","hits":"2","order":"187","possible_hits":"2",}, +{"lineNum":" 152","line":" v = OpenSSL::HMAC.digest(:sha256, k, v)","class":"lineCov","hits":"3","order":"188","possible_hits":"3",}, +{"lineNum":" 153","line":" t = Util.concat_bytes t, v","class":"lineCov","hits":"2","order":"189","possible_hits":"2",}, {"lineNum":" 154","line":" end"}, -{"lineNum":" 155","line":" secret = Num.new t","class":"lineCov","hits":"1","order":"131","possible_hits":"1",}, -{"lineNum":" 156","line":" if secret.dec < order.dec && secret.dec > 0","class":"lineCov","hits":"2","order":"132","possible_hits":"2",}, +{"lineNum":" 155","line":" secret = Num.new t","class":"lineCov","hits":"1","order":"190","possible_hits":"1",}, +{"lineNum":" 156","line":" if secret.dec < order.dec && secret.dec > 0","class":"lineCov","hits":"2","order":"191","possible_hits":"2",}, {"lineNum":" 157","line":" return secret"}, {"lineNum":" 158","line":" end"}, {"lineNum":" 159","line":" increment = Util.concat_bytes v, Bytes[0x00]","class":"lineNoCov","hits":"0","possible_hits":"2",}, @@ -175,18 +175,18 @@ var data = {lines:[ {"lineNum":" 174","line":" # Util.concat_bytes Bytes[1, 2, 3], Bytes[9, 8, 7]"}, {"lineNum":" 175","line":" # # => Bytes[1, 2, 3, 9, 8, 7]"}, {"lineNum":" 176","line":" # ```"}, -{"lineNum":" 177","line":" def concat_bytes(x : Bytes, y : Bytes) : Bytes","class":"lineCov","hits":"2","order":"113","possible_hits":"2",}, -{"lineNum":" 178","line":" z = IO::Memory.new x.bytesize + y.bytesize","class":"lineCov","hits":"1","order":"114","possible_hits":"1",}, +{"lineNum":" 177","line":" def concat_bytes(x : Bytes, y : Bytes) : Bytes","class":"lineCov","hits":"2","order":"125","possible_hits":"2",}, +{"lineNum":" 178","line":" z = IO::Memory.new x.bytesize + y.bytesize","class":"lineCov","hits":"1","order":"126","possible_hits":"1",}, {"lineNum":" 179","line":" x.each do |b|"}, -{"lineNum":" 180","line":" z.write_bytes UInt8.new b","class":"lineCov","hits":"1","order":"115","possible_hits":"1",}, +{"lineNum":" 180","line":" z.write_bytes UInt8.new b","class":"lineCov","hits":"1","order":"127","possible_hits":"1",}, {"lineNum":" 181","line":" end"}, {"lineNum":" 182","line":" y.each do |b|"}, -{"lineNum":" 183","line":" z.write_bytes UInt8.new b","class":"lineCov","hits":"1","order":"116","possible_hits":"1",}, +{"lineNum":" 183","line":" z.write_bytes UInt8.new b","class":"lineCov","hits":"1","order":"128","possible_hits":"1",}, {"lineNum":" 184","line":" end"}, -{"lineNum":" 185","line":" return z.to_slice","class":"lineCov","hits":"1","order":"117","possible_hits":"1",}, +{"lineNum":" 185","line":" return z.to_slice","class":"lineCov","hits":"1","order":"129","possible_hits":"1",}, {"lineNum":" 186","line":" end"}, {"lineNum":" 187","line":"end"}, ]}; var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 44, "covered" : 41,}; +var header = { "command" : "run_coverage", "date" : "2022-04-06 14:26:02", "instrumented" : 44, "covered" : 41,}; var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/index.js b/.github/coverage/run_coverage.78460cc2/index.js deleted file mode 100644 index 9fda395..0000000 --- a/.github/coverage/run_coverage.78460cc2/index.js +++ /dev/null @@ -1,13 +0,0 @@ -var data = {files:[ -{"link":"util.cr.e684f666.html","title":"util.cr","summary_name":"[...]/src/secp256k1/util.cr","covered_class":"lineCov","covered":"93.2","covered_lines":"41","uncovered_lines":"3","total_lines" : "44"}, -{"link":"curve.cr.f05213da.html","title":"curve.cr","summary_name":"[...]/src/secp256k1/curve.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"56","uncovered_lines":"0","total_lines" : "56"}, -{"link":"context.cr.d435d9a9.html","title":"context.cr","summary_name":"[...]/src/secp256k1/context.cr","covered_class":"lineCov","covered":"92.9","covered_lines":"26","uncovered_lines":"2","total_lines" : "28"}, -{"link":"point.cr.10ecf873.html","title":"point.cr","summary_name":"[...]/src/secp256k1/point.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"36","uncovered_lines":"0","total_lines" : "36"}, -{"link":"key.cr.80fcd549.html","title":"key.cr","summary_name":"[...]/src/secp256k1/key.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"14","uncovered_lines":"0","total_lines" : "14"}, -{"link":"num.cr.6faa13b0.html","title":"num.cr","summary_name":"[...]/src/secp256k1/num.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"47","uncovered_lines":"0","total_lines" : "47"}, -{"link":"signature.cr.25065a1d.html","title":"signature.cr","summary_name":"[...]/src/secp256k1/signature.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"6","uncovered_lines":"0","total_lines" : "6"}, -{"link":"secp256k1.cr.30592eb4.html","title":"secp256k1.cr","summary_name":"[...]/src/secp256k1.cr","covered_class":"lineCov","covered":"100.0","covered_lines":"5","uncovered_lines":"0","total_lines" : "5"}, -]}; -var percent_low = 25;var percent_high = 75; -var header = { "command" : "run_coverage", "date" : "2022-04-06 12:16:54", "instrumented" : 236, "covered" : 231,}; -var merged_data = []; diff --git a/.github/coverage/run_coverage.78460cc2/metadata/10ecf873 b/.github/coverage/run_coverage.78460cc2/metadata/10ecf873 deleted file mode 100644 index d9cdbd0..0000000 Binary files a/.github/coverage/run_coverage.78460cc2/metadata/10ecf873 and /dev/null differ diff --git a/.github/coverage/run_coverage.78460cc2/metadata/6faa13b0 b/.github/coverage/run_coverage.78460cc2/metadata/6faa13b0 deleted file mode 100644 index 3e6d19a..0000000 Binary files a/.github/coverage/run_coverage.78460cc2/metadata/6faa13b0 and /dev/null differ diff --git a/.github/coverage/run_coverage.78460cc2/metadata/80fcd549 b/.github/coverage/run_coverage.78460cc2/metadata/80fcd549 deleted file mode 100644 index 5d877ef..0000000 Binary files a/.github/coverage/run_coverage.78460cc2/metadata/80fcd549 and /dev/null differ diff --git a/.github/coverage/run_coverage.78460cc2/metadata/e684f666 b/.github/coverage/run_coverage.78460cc2/metadata/e684f666 deleted file mode 100644 index 960e48b..0000000 Binary files a/.github/coverage/run_coverage.78460cc2/metadata/e684f666 and /dev/null differ diff --git a/.github/run_coverage.cr b/.github/run_coverage.cr index f2fc202..acdc43b 100644 --- a/.github/run_coverage.cr +++ b/.github/run_coverage.cr @@ -1,5 +1,7 @@ # wrapper to compile all tests into one binary for code coverage reporting require "../spec/spec_helper.cr" +require "../spec/bitcoin_spec.cr" +require "../spec/ethereum_spec.cr" require "../spec/secp256k1_spec.cr" require "../spec/secp256k1/context_spec.cr" require "../spec/secp256k1/curve_spec.cr" diff --git a/docs/404.html b/docs/404.html index 3f2394b..391dd17 100644 --- a/docs/404.html +++ b/docs/404.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - secp256k1 q9f/rewrite-dev + secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

- q9f/rewrite-dev + q9f/examples-dev @@ -51,6 +51,26 @@

    +
  • + Bitcoin + + + + +
  • + +
  • + Ethereum + +
  • +
  • Secp256k1 diff --git a/docs/Bitcoin.html b/docs/Bitcoin.html new file mode 100644 index 0000000..0dd8c92 --- /dev/null +++ b/docs/Bitcoin.html @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + Bitcoin - secp256k1 q9f/examples-dev + + + + + + + + +
    +

    + + module Bitcoin + +

    + + + + + +

    + + + + Overview +

    + +

    An example implementation of a Bitcoin account using an Secp256k1 +key-pair and a Bitcoin network version identifier; only for educational +purposes and should not be used in production.

    + + + + + + + + + + + + + + +

    + + + + Defined in: +

    + + + bitcoin.cr + +
    + + + + + +

    + + + + Constant Summary +

    + +
    + +
    + BASE_58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" +
    + +
    +

    The Base-58 alphabet for Bitcoin addresses is a Base-64 alphabet without +0, O, I, and l to omit similar-looking letters.

    +
    + + +
    + + + + + + + + + + + +
    + +
    + + + + + + + + + +
    + + + diff --git a/docs/Bitcoin/Account.html b/docs/Bitcoin/Account.html new file mode 100644 index 0000000..ae2d06a --- /dev/null +++ b/docs/Bitcoin/Account.html @@ -0,0 +1,485 @@ + + + + + + + + + + + + + + + + Bitcoin::Account - secp256k1 q9f/examples-dev + + + + + + + + +
    +

    + + class Bitcoin::Account + +

    + + + + + + + +

    + + + + Overview +

    + +

    An example implementation of a Bitcoin account using an Secp256k1 +key-pair and a Bitcoin network version identifier; only for educational +purposes and should not be used in production.

    + + + + + + + + + + + + + + +

    + + + + Defined in: +

    + + + bitcoin.cr + +
    + + + + + + +

    + + + + Constructors +

    + + + + + + +

    + + + + Instance Method Summary +

    + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + +
    + + +

    + + + + Constructor Detail +

    + +
    +
    + + def self.new(key = Key.new, version = Num.new("0x00")) + + # +
    + +
    + +

    Creates a Bitcoin account from a given Secp256k1::Key keypay and for the +specified network version, e.g., 00 for Bitcoin main network. It creates +a random account if no parameters are supplied.

    +

    Parameters:

    + +
    priv = Secp256k1::Num.new "18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725"
    +key = Secp256k1::Key.new priv
    +account = Bitcoin::Account.new key
    +# => #<Bitcoin::Account:0x7f2611dcab40
    +#         @key=#<Secp256k1::Key:0x7f261ae90ee0
    +#               @private_key=#<Secp256k1::Num:0x7f261ae93300
    +#                   @hex="18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725",
    +#                   @dec=11253563012059685825953619222107823549092147699031672238385790369351542642469,
    +#                   @bin=Bytes[24, 225, 74, 123, 106, 48, 127, 66, 106, 148, 248, 17, 71, 1, 231, 200, 231, 116, 231, 249, 164, 126, 44, 32, 53, 219, 41, 162, 6, 50, 23, 37]>,
    +#               @public_key=#<Secp256k1::Point:0x7f261ae90d20
    +#                   @x=#<Secp256k1::Num:0x7f2611dcabc0
    +#                       @hex="50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352",
    +#                       @dec=36422191471907241029883925342251831624200921388586025344128047678873736520530,
    +#                       @bin=Bytes[80, 134, 58, 214, 74, 135, 174, 138, 47, 232, 60, 26, 241, 168, 64, 60, 181, 63, 83, 228, 134, 216, 81, 29, 173, 138, 4, 136, 126, 91, 35, 82]>,
    +#                   @y=#<Secp256k1::Num:0x7f2611dcab80
    +#                       @hex="2cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6",
    +#                       @dec=20277110887056303803699431755396003735040374760118964734768299847012543114150,
    +#                       @bin=Bytes[44, 212, 112, 36, 52, 83, 162, 153, 250, 158, 119, 35, 119, 22, 16, 58, 188, 17, 161, 223, 56, 133, 94, 214, 242, 238, 24, 126, 156, 88, 43, 166]>>>,
    +#         @version=#<Secp256k1::Num:0x7f2611dcab00
    +#               @hex="00",
    +#               @dec=0,
    +#               @bin=Bytes[0]>,
    +#         @address="16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM",
    +#         @address_compressed="1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs",
    +#         @wif="5J1F7GHadZG3sCCKHCwg8Jvys9xUbFsjLnGec4H125Ny1V9nR6V",
    +#         @wif_compressed="Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C">
    +
    + +
    +
    + +
    +
    + + + + + + +

    + + + + Instance Method Detail +

    + +
    +
    + + def address : String + + # +
    + +
    + +

    The public, uncompressed Bitcoin account address.

    +
    + +
    +
    + +
    +
    + +
    +
    + + def address_compressed : String + + # +
    + +
    + +

    The public, compressed Bitcoin account address.

    +
    + +
    +
    + +
    +
    + +
    +
    + + def key : Key + + # +
    + +
    + +

    The Secp256k1 keypair for the account.

    +
    + +
    +
    + +
    +
    + +
    +
    + + def version : Num + + # +
    + +
    + +

    The network version indicator.

    +
    + +
    +
    + +
    +
    + +
    +
    + + def wif : String + + # +
    + +
    + +

    The private, uncompressed wallet-import format.

    +
    + +
    +
    + +
    +
    + +
    +
    + + def wif_compressed : String + + # +
    + +
    + +

    The private, compressed wallet-import format.

    +
    + +
    +
    + +
    +
    + + + + + +
    + + + diff --git a/docs/Ethereum.html b/docs/Ethereum.html new file mode 100644 index 0000000..faf1e08 --- /dev/null +++ b/docs/Ethereum.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + Ethereum - secp256k1 q9f/examples-dev + + + + + + + + +
    +

    + + module Ethereum + +

    + + + + + + + + + + + + + + + + + + +

    + + + + Defined in: +

    + + + ethereum.cr + +
    + + + + + + + + + + + + + + +
    + +
    + + + + + + + + + +
    + + + diff --git a/docs/Secp256k1.html b/docs/Secp256k1.html index f04c3de..2e94915 100644 --- a/docs/Secp256k1.html +++ b/docs/Secp256k1.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - Secp256k1 - secp256k1 q9f/rewrite-dev + Secp256k1 - secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

    - q9f/rewrite-dev + q9f/examples-dev
@@ -51,6 +51,26 @@

    +
  • + Bitcoin + + + + +
  • + +
  • + Ethereum + +
  • +
  • Secp256k1 @@ -123,7 +143,7 @@

    Provides the Secp256k1 module with the elliptic curve parameters -used by the Bitcoin, Ethereum, and Polkadot blockchains. It's +used by the Bitcoin, Ethereum, and Polkadot blockchains. It's primarily used to generate key-pairs as well as signing messages and recoverying signatures.

    Ref: secg.org/sec2-v2.pdf

    diff --git a/docs/Secp256k1/Context.html b/docs/Secp256k1/Context.html index 24db2c9..212cffd 100644 --- a/docs/Secp256k1/Context.html +++ b/docs/Secp256k1/Context.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - Secp256k1::Context - secp256k1 q9f/rewrite-dev + Secp256k1::Context - secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

    - q9f/rewrite-dev + q9f/examples-dev
@@ -51,6 +51,26 @@

    +
  • + Bitcoin + + + + +
  • + +
  • + Ethereum + +
  • +
  • Secp256k1 diff --git a/docs/Secp256k1/Curve.html b/docs/Secp256k1/Curve.html index faf5bbe..1b3f04e 100644 --- a/docs/Secp256k1/Curve.html +++ b/docs/Secp256k1/Curve.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - Secp256k1::Curve - secp256k1 q9f/rewrite-dev + Secp256k1::Curve - secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

    - q9f/rewrite-dev + q9f/examples-dev
@@ -51,6 +51,26 @@

    +
  • + Bitcoin + + + + +
  • + +
  • + Ethereum + +
  • +
  • Secp256k1 diff --git a/docs/Secp256k1/Key.html b/docs/Secp256k1/Key.html index c819c5b..9d0ea99 100644 --- a/docs/Secp256k1/Key.html +++ b/docs/Secp256k1/Key.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - Secp256k1::Key - secp256k1 q9f/rewrite-dev + Secp256k1::Key - secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

    - q9f/rewrite-dev + q9f/examples-dev
@@ -51,6 +51,26 @@

@@ -462,25 +468,6 @@

-
-
- - def private_key=(private_key : Num) - - # -
- -
- -

The secret number representing the private key.

-
- -
-
- -
-
-
@@ -584,25 +571,6 @@

-
-
- - def public_key=(public_key : Point) - - # -
- -
- -

The point on the elliptic curve representing the public key.

-
- -
-
- -
-
- diff --git a/docs/Secp256k1/Num.html b/docs/Secp256k1/Num.html index cd24cea..aa033cb 100644 --- a/docs/Secp256k1/Num.html +++ b/docs/Secp256k1/Num.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - Secp256k1::Num - secp256k1 q9f/rewrite-dev + Secp256k1::Num - secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

- q9f/rewrite-dev + q9f/examples-dev @@ -51,6 +51,26 @@

-
-
- - def bin=(bin : Slice(UInt8)) - - # -
- -
- -

The binary bytes-slice represenation of the number.

-
- -
-
- -
-
-
@@ -526,25 +506,6 @@

-
-
- - def dec=(dec : BigInt) - - # -
- -
- -

The decimal big-integer representation of the number.

-
- -
-
- -
-
-
@@ -564,25 +525,6 @@

-
-
- - def hex=(hex : String) - - # -
- -
- -

The hexadecimal string representation of the number.

-
- -
-
- -
-
-
diff --git a/docs/Secp256k1/Point.html b/docs/Secp256k1/Point.html index 1f609ba..0028ad4 100644 --- a/docs/Secp256k1/Point.html +++ b/docs/Secp256k1/Point.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - Secp256k1::Point - secp256k1 q9f/rewrite-dev + Secp256k1::Point - secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

- q9f/rewrite-dev + q9f/examples-dev
@@ -51,6 +51,26 @@

    +
  • + Bitcoin + + + + +
  • + +
  • + Ethereum + +
  • +
  • Secp256k1 diff --git a/docs/Secp256k1/Signature.html b/docs/Secp256k1/Signature.html index 1164d76..6e520e0 100644 --- a/docs/Secp256k1/Signature.html +++ b/docs/Secp256k1/Signature.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - Secp256k1::Signature - secp256k1 q9f/rewrite-dev + Secp256k1::Signature - secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

    - q9f/rewrite-dev + q9f/examples-dev
@@ -51,6 +51,26 @@

@@ -388,25 +387,6 @@

-
-
- - def r=(r : Num) - - # -
- -
- -

The x coordinate of a random point R on the curve.

-
- -
-
- -
-
-
@@ -426,25 +406,6 @@

-
-
- - def s=(s : Num) - - # -
- -
- -

The signature proof of a message.

-
- -
-
- -
-
-
@@ -464,25 +425,6 @@

-
-
- - def v=(v : Num) - - # -
- -
- -

The recovery id or #v value.

-
- -
-
- -
-
- diff --git a/docs/Secp256k1/Util.html b/docs/Secp256k1/Util.html index a7a2a84..e3c21e5 100644 --- a/docs/Secp256k1/Util.html +++ b/docs/Secp256k1/Util.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - Secp256k1::Util - secp256k1 q9f/rewrite-dev + Secp256k1::Util - secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

- q9f/rewrite-dev + q9f/examples-dev @@ -51,6 +51,26 @@

-
+
- def keccak(data : Num | String, entropy = 256) : Num + def keccak(data : Num | Bytes | String, entropy = 256) : Num - # + #
@@ -326,7 +346,7 @@

Operating a Keccak hash on a binary/number or string literal.

Parameters:

    -
  • data (Num | String): the binary numeric or string literal to be hashed.
  • +
  • data (Num | Bytes | String): the binary numeric or string literal to be hashed.
  • entropy (Int32): the required entropy (default 256).

Returns a Num representing the Keccak hash.

@@ -343,12 +363,12 @@

-
+
- def ripemd160(data : Num | String) : Num + def ripemd160(data : Num | Bytes | String) : Num - # + #
@@ -356,7 +376,7 @@

Operating a RIPEMD-160 hash on a binary/number or string literal.

Parameters:

    -
  • data (Num | String): the binary numeric or string literal to be hashed.
  • +
  • data (Num | Bytes | String): the binary numeric or string literal to be hashed.

Returns a Num representing the RIPEMD hash.

Util.ripemd160(Num.new "0xdeadbeef").hex
@@ -372,12 +392,12 @@ 

-
+
- def sha256(data : Num | String) : Num + def sha256(data : Num | Bytes | String) : Num - # + #
@@ -385,7 +405,7 @@

Operating a SHA2-256 hash on a binary/number or string literal.

Parameters:

    -
  • data (Num | String): the binary numeric or string literal to be hashed.
  • +
  • data (Num | Bytes | String): the binary numeric or string literal to be hashed.

Returns a Num representing the SHA2 hash.

Util.sha256(Num.new "0xdeadbeef").hex
@@ -401,12 +421,12 @@ 

-
+
- def sha3(data : Num | String, entropy = 256) : Num + def sha3(data : Num | Bytes | String, entropy = 256) : Num - # + #
@@ -414,7 +434,7 @@

Operating a SHA3 hash on a binary/number or string literal.

Parameters:

    -
  • data (Num | String): the binary numeric or string literal to be hashed.
  • +
  • data (Num | Bytes | String): the binary numeric or string literal to be hashed.
  • entropy (Int32): the required entropy (default 256).

Returns a Num representing the SHA3 hash.

diff --git a/docs/index.html b/docs/index.html index 22da91c..15b787e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -4,7 +4,7 @@ - + @@ -13,7 +13,7 @@ - secp256k1 q9f/rewrite-dev + secp256k1 q9f/examples-dev @@ -39,7 +39,7 @@

- q9f/rewrite-dev + q9f/examples-dev
@@ -51,6 +51,26 @@

    +
  • + Bitcoin + + + + +
  • + +
  • + Ethereum + +
  • +
  • Secp256k1 @@ -114,7 +134,7 @@

    Language License

    A library implementing the Secp256k1 elliptic curve natively in pure Crystal. -Secp256k1 is the elliptic curve used in the public-private-key cryptography required by Bitcoin, Ethereum, and Polkadot.

    +Secp256k1 is the elliptic curve used in the public-private-key cryptography required by Bitcoin, Ethereum, and Polkadot.

    This library allows for:

    • providing a Secp256k1 cryptographic context, see Secp256k1::Context
    • diff --git a/docs/index.json b/docs/index.json index 79e8828..9aab011 100644 --- a/docs/index.json +++ b/docs/index.json @@ -1 +1 @@ -{"repository_name":"secp256k1","body":"# secp256k1.cr\n\n[![Build Status](https://img.shields.io/github/workflow/status/q9f/secp256k1.cr/Nightly)](https://github.com/q9f/secp256k1.cr/actions)\n[![Code Coverage](https://codecov.io/gh/q9f/secp256k1.cr/branch/main/graph/badge.svg?token=ngxRs9HdJA)](https://codecov.io/gh/q9f/secp256k1.cr)\n[![Documentation](https://img.shields.io/badge/docs-html-black)](https://q9f.github.io/secp256k1.cr/)\n[![Release](https://img.shields.io/github/v/release/q9f/secp256k1.cr?include_prereleases&color=black)](https://github.com/q9f/secp256k1.cr/releases/latest)\n[![Language](https://img.shields.io/github/languages/top/q9f/secp256k1.cr?color=black)](https://github.com/q9f/secp256k1.cr/search?l=crystal)\n[![License](https://img.shields.io/github/license/q9f/secp256k1.cr.svg?color=black)](LICENSE)\n\nA library implementing the `Secp256k1` elliptic curve natively in pure Crystal.\n`Secp256k1` is the elliptic curve used in the public-private-key cryptography required by `Bitcoin`, `Ethereum`, and `Polkadot`.\n\nThis library allows for:\n* providing a `Secp256k1` cryptographic context, see `Secp256k1::Context`\n* managing `Secp256k1` signatures and verification, see `Secp256k1::Signature`\n* managing private-public keypairs, see `Secp256k1::Key`\n* generating public keys, see `Secp256k1::Point`\n* generating private keys, see `Secp256k1::Num`\n\n# Installation\n\nAdd the `Secp256k1` library to your `shard.yml`\n\n```yaml\ndependencies:\n secp256k1:\n github: q9f/secp256k1.cr\n version: \"~> 0.5\"\n```\n\n# Usage\n\nImport and expose the `Secp256k1` module.\n\n```crystal\nrequire \"secp256k1\"\n```\n\nThis library exposes the following modules and classes (in logical order):\n\n* `Secp256k1`: necessary constants and data structures, including:\n - `Secp256k1::Num`: for managing big numerics (private keys)\n - `Secp256k1::Point`: for handling of elliptic curve points (public keys)\n - `Secp256k1::Key`: for managing private-public keypairs (accounts)\n - `Secp256k1::Signature`: for handling ECDSA signatures (r, s, v)\n* `Secp256k1::Context`: providing a cryptographic context for signing and verification\n* `Secp256k1::Curve`: the entire core mathematics behind the elliptic curve cryptography\n* `Secp256k1::Util`: binding of various hashing algorithms for convenience\n\nBasic usage:\n\n```crystal\n# generates a new, random keypair\nkey = Secp256k1::Key.new\n# => #,\n# @public_key=#,\n# @y=#>>\n\n# gets the private key\nkey.private_hex\n# => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\n\n# gets the compressed public key with prefix\nkey.public_hex_compressed\n# => \"02cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba2\"\n```\n\nSignature generation and verification:\n\n```crystal\n# sign a message with a private key\nctx = Secp256k1::Context.new\npriv = Secp256k1::Num.new \"1f0c122d41ff536b19bfd83537c0dfc290e45cd3c375a43237c8b8fff7ac8af7\"\nkey = Secp256k1::Key.new priv\nhash = Secp256k1::Util.sha256 \"Henlo, Wordl\"\nsig = ctx.sign key, hash\n# => #,\n# @s=#,\n# @v=#>\n\n# verify a signature with a public key\nr = Secp256k1::Num.new \"c4079db44240b7afe94985c69fc89602e33629fd9b8623d711c30ce6378b33df\"\ns = Secp256k1::Num.new \"6842c1b63c94bdb8e4f5ae88fb65f7a98b77b197c8323004fb47ef57fab29053\"\nv = Secp256k1::Num.new \"00\"\nsig = Secp256k1::Signature.new r, s, v\nhash = Secp256k1::Util.sha256 \"Henlo, Wordl\"\npubl = Secp256k1::Point.new \"0416008a369439f1a8a75cf974860bed5b10180518d6b1dd3ac847f423fd375d6aa29474394f0cd79d2ea543507d069e97339284f01bdbfd27392daec0ec553816\"\nctx.verify sig, hash, publ\n# => true\n```\n\n# Documentation\n\nThe full library documentation can be found here: [q9f.github.io/secp256k1.cr](https://q9f.github.io/secp256k1.cr/)\n\nGenerate a local copy with:\n\n```shell\ncrystal docs\n```\n\n# Testing\n\nThe library is entirely specified through tests in `./spec`; run:\n\n```shell\ncrystal spec --verbose\n```\n\n# Understand\n\nPrivate keys are just scalars (`Secp256k1::Num`) and public keys are points (`Secp256k1::Point`) with `x` and `y` coordinates.\n\nBitcoin public keys can be uncompressed `p|x|y` or compressed `p|x`. both come with a prefix `p` which is useless for uncompressed keys but necessary for compressed keys to recover the `y` coordinate on the `Secp256k1` elliptic curve field.\n\nEthereum public keys are uncompressed `x|y` without any prefix. The last 20 bytes slice of the `y` coordinate is actually used as address without any checksum. A checksum was later added in EIP-55 using a `keccak256` hash and indicating character capitalization.\n\nNeither Bitcoin nor Ethereum allow for recovering public keys from an address unless there exists a transaction with a valid signature on the blockchain.\n\n# Known issues\n\n_Note: this library should not be used in production without proper auditing. It should be considered slow and insecure._\n\n* This library is not constant time and might be subject to side-channel attacks. ([#4](https://github.com/q9f/secp256k1.cr/issues/4))\n* This library does unnecessary big-integer math and should someday rather correctly implement the `Secp256k1` prime field ([#5](https://github.com/q9f/secp256k1.cr/issues/5))\n* This library is slow in recovering signatures. Future versions should respect the recovery ID to quickly identify the correct public key from a signature.\n\nFound any other issue? Report it: [github.com/q9f/secp256k1.cr/issues](https://github.com/q9f/secp256k1.cr/issues)\n\n# Contribute\n\nCreate a pull request, and make sure tests and linter pass.\n\nThis pure crystal implementation is based on the python implementation [wobine/blackboard101](https://github.com/wobine/blackboard101) which is also used as reference to write tests against. It's a complete rewrite of the abandoned [packetzero/bitcoinutils](https://github.com/packetzero/bitcoinutils) for educational purposes.\n\nHonerable mention for the [bitcoin wiki](https://en.bitcoin.it/wiki/Main_Page) and the [ethereum stackexchange](https://ethereum.stackexchange.com/) for providing so many in-depth resources that supported this project in reimplementing everything.\n\nLicense: Apache License v2.0\n\nContributors: [**@q9f**](https://github.com/q9f/), [@cserb](https://github.com/cserb), [MrSorcus](https://github.com/MrSorcus)\n","program":{"html_id":"secp256k1/toplevel","path":"toplevel.html","kind":"module","full_name":"Top Level Namespace","name":"Top Level Namespace","abstract":false,"locations":[],"repository_name":"secp256k1","program":true,"enum":false,"alias":false,"const":false,"types":[{"html_id":"secp256k1/Secp256k1","path":"Secp256k1.html","kind":"module","full_name":"Secp256k1","name":"Secp256k1","abstract":false,"locations":[{"filename":"src/secp256k1.cr","line_number":35,"url":null},{"filename":"src/secp256k1/context.cr","line_number":22,"url":null},{"filename":"src/secp256k1/version.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"G","name":"G","value":"Point.new(Num.new(\"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\"), Num.new(\"483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8\"))","doc":"A commonly used base point `G` with coordinates `x` and `y`\nsatisfying `y^2 = x^3 + 7`.","summary":"

      A commonly used base point G with coordinates x and y satisfying y^2 = x^3 + 7.

      "},{"id":"N","name":"N","value":"Num.new(\"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141\")","doc":"The order `n` of `G` defines the finite size of the Secp256k1 field `E`.","summary":"

      The order n of G defines the finite size of the Secp256k1 field E.

      "},{"id":"P","name":"P","value":"Num.new(\"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f\")","doc":"The elliptic curve domain parameters over `F_p` associated with a\nKoblitz curve `Secp256k1` are specified by the sextuple\n`T = (p, a, b, G, n, h)` where the finite field `F_p` is defined by\nthe prime `p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1`.","summary":"

      The elliptic curve domain parameters over F_p associated with a Koblitz curve Secp256k1 are specified by the sextuple T = (p, a, b, G, n, h) where the finite field F_p is defined by the prime p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1.

      "},{"id":"VERSION","name":"VERSION","value":"\"0.5.0\"","doc":"The `VERSION` of the `Secp256k1` module.","summary":"

      The VERSION of the Secp256k1 module.

      "}],"doc":"Provides the `Secp256k1` module with the elliptic curve parameters\nused by the `Bitcoin`, `Ethereum`, and `Polkadot` blockchains. It's\nprimarily used to generate key-pairs as well as signing messages and\nrecoverying signatures.\n\nRef: [secg.org/sec2-v2.pdf](https://www.secg.org/sec2-v2.pdf)","summary":"

      Provides the Secp256k1 module with the elliptic curve parameters used by the Bitcoin, Ethereum, and Polkadot blockchains.

      ","types":[{"html_id":"secp256k1/Secp256k1/Context","path":"Secp256k1/Context.html","kind":"class","full_name":"Secp256k1::Context","name":"Context","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/context.cr","line_number":22,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a `Secp256k1` context to allow signing arbitrary data,\nrecovering public keys, and verifying signatures.\n\n```\nctx = Context.new\n# => #\n```","summary":"

      Provides a Secp256k1 context to allow signing arbitrary data, recovering public keys, and verifying signatures.

      ","instance_methods":[{"html_id":"sign(key:Key,hash:Num):Signature-instance-method","name":"sign","doc":"Signs a message hash or any other arbitrary data with a given keypair.\n\nParameters:\n* `key` (`Key`): the keypair containing a secret to sign the data.\n* `hash` (`Num`): the message or arbirtrary data hash.\n\nReturns a `Signature` proving the given key signed the message hash.\n\n```\nctx = Context.new\nkey = Key.new Num.new \"1f0c122d41ff536b19bfd83537c0dfc290e45cd3c375a43237c8b8fff7ac8af7\"\nhash = Util.sha256 \"Henlo, Wordl\"\nsig = ctx.sign key, hash\n# => #,\n# @s=#,\n# @v=#>\n```","summary":"

      Signs a message hash or any other arbitrary data with a given keypair.

      ","abstract":false,"args":[{"name":"key","external_name":"key","restriction":"Key"},{"name":"hash","external_name":"hash","restriction":"Num"}],"args_string":"(key : Key, hash : Num) : Signature","args_html":"(key : Key, hash : Num) : Signature","location":{"filename":"src/secp256k1/context.cr","line_number":50,"url":null},"def":{"name":"sign","args":[{"name":"key","external_name":"key","restriction":"Key"},{"name":"hash","external_name":"hash","restriction":"Num"}],"return_type":"Signature","visibility":"Public","body":"k = Util.deterministic_k(key.private_key, hash)\nhash = hash.to_big\npriv = key.private_key.to_big\npoint = Curve.mul(G, k)\nr = point.x.to_big % N.to_big\nk_inv = Curve.mod_inv(k, N)\ns = ((hash + (r * priv)) * k_inv.to_big) % N.to_big\nx_mag = point.x.to_big > N.to_big\ny_parity = (point.y.to_big % 2) == 0\nrec_id : Int8 = -1\nif (!y_parity) && x_mag\n rec_id = 3\nelse\n if y_parity && x_mag\n rec_id = 2\n else\n if (!y_parity) && (!x_mag)\n rec_id = 1\n else\n rec_id = 0\n end\n end\nend\nr = Num.new(r)\ns = Num.new(s)\nv = Num.new(BigInt.new(rec_id))\nSignature.new(r, s, v)\n"}},{"html_id":"verify(sig:Signature,hash:Num,publ:Point):Bool-instance-method","name":"verify","doc":"Verifies that a given signature for a given message hash matches\nthe provided public key.\n\nParameters:\n* `sig` (`Signature`): the signature to be verified.\n* `hash` (`Num`): the message or arbirtrary data hash.\n* `publ` (`Point`): the public key to match.\n\nReturns _true_ if the signature verifies.\n\n```\nctx = Context.new\nr = Num.new \"c4079db44240b7afe94985c69fc89602e33629fd9b8623d711c30ce6378b33df\"\ns = Num.new \"6842c1b63c94bdb8e4f5ae88fb65f7a98b77b197c8323004fb47ef57fab29053\"\nv = Num.new \"00\"\nsig = Signature.new r, s, v\nhash = Util.sha256 \"Henlo, Wordl\"\npubl = Point.new \"0416008a369439f1a8a75cf974860bed5b10180518d6b1dd3ac847f423fd375d6aa29474394f0cd79d2ea543507d069e97339284f01bdbfd27392daec0ec553816\"\nctx.verify sig, hash, publ\n# => true\n```","summary":"

      Verifies that a given signature for a given message hash matches the provided public key.

      ","abstract":false,"args":[{"name":"sig","external_name":"sig","restriction":"Signature"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"publ","external_name":"publ","restriction":"Point"}],"args_string":"(sig : Signature, hash : Num, publ : Point) : Bool","args_html":"(sig : Signature, hash : Num, publ : Point) : Bool","location":{"filename":"src/secp256k1/context.cr","line_number":97,"url":null},"def":{"name":"verify","args":[{"name":"sig","external_name":"sig","restriction":"Signature"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"publ","external_name":"publ","restriction":"Point"}],"return_type":"Bool","visibility":"Public","body":"s_inv = Curve.mod_inv(sig.s, N)\np0 = Curve.mul(G, (hash.to_big * s_inv.to_big) % N.to_big)\np1 = Curve.mul(publ, (sig.r.to_big * s_inv.to_big) % N.to_big)\np = Curve.add(p0, p1)\nsig.r.to_big === p.x.to_big\n"}}]},{"html_id":"secp256k1/Secp256k1/Curve","path":"Secp256k1/Curve.html","kind":"module","full_name":"Secp256k1::Curve","name":"Curve","abstract":false,"locations":[{"filename":"src/secp256k1/curve.cr","line_number":18,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"secp256k1/Secp256k1/Curve","kind":"module","full_name":"Secp256k1::Curve","name":"Curve"}],"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Implements 256-bit `Secp256k1` Koblitz elliptic curve operations.\n\nRef: [secg.org/sec2-v2.pdf](https://www.secg.org/sec2-v2.pdf)","summary":"

      Implements 256-bit Secp256k1 Koblitz elliptic curve operations.

      ","instance_methods":[{"html_id":"add(p:Point,q:Point,prime=P):Point-instance-method","name":"add","doc":"Computes the elliptic curve jive addition of point `p(x, y)` and `q(x, y)`.\nIt _draws_ a line between `p` and `q` which will intersect the\ncurve in the point `r` which will be mirrored over the `x`-axis.\n\nParamters:\n* `p` (`Num`): the point `p(x, y)` to be used in the jive addition.\n* `q` (`Num`): the point `q(x, y)` to be used in the jive addition.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Point` containing the result of the intersection.\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\nq = Point.new Num.new \"7e17f60baa7b8dc8581a55f7be1ea263c6a88452cf3f0a3f710651767654946c\"\nCurve.add p, q\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve jive addition of point p(x, y) and q(x, y).

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"q","external_name":"q","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(p : Point, q : Point, prime = P) : Point","args_html":"(p : Point, q : Point, prime = P) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":82,"url":null},"def":{"name":"add","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"q","external_name":"q","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Point","visibility":"Public","body":"if prime.is_a?(Num)\n prime = prime.to_big\nend\np_x = p.x.to_big\np_y = p.y.to_big\nq_x = q.x.to_big\nq_y = q.y.to_big\nx_delta = q_x - p_x\nx_inv = mod_inv(x_delta)\ny_delta = q_y - p_y\nm = (y_delta * x_inv.to_big) % prime\nx = (((m * m) - p_x) - q_x) % prime\ny = ((m * (p_x - x)) - p_y) % prime\nx = Num.new(x)\ny = Num.new(y)\nPoint.new(x, y)\n"}},{"html_id":"double(p:Point,prime=P):Point-instance-method","name":"double","doc":"Computes the elliptic curve juke point doubling of `p(x, y)`.\nThis is a special case of addition where both points are the same.\nIt _draws_ a tangent line at `p` which will intersect the curve\nat point `r` which will be mirrored over the `x`-axis.\n\nParamters:\n* `p` (`Point`): the point `p(x, y)` to be used in the juke doubling.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Point` as a result of the intersection.\n\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\nCurve.double p\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve juke point doubling of p(x, y).

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(p : Point, prime = P) : Point","args_html":"(p : Point, prime = P) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":123,"url":null},"def":{"name":"double","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Point","visibility":"Public","body":"if prime.is_a?(Num)\n prime = prime.to_big\nend\np_x = p.x.to_big\np_y = p.y.to_big\nlam_numer = (3 * p_x) * p_x\nlam_denom = 2 * p_y\nlam_inv = mod_inv(Num.new(lam_denom))\nlam = (lam_numer * lam_inv.to_big) % prime\nx = ((lam * lam) - (2 * p_x)) % prime\ny = ((lam * (p_x - x)) - p_y) % prime\nx = Num.new(x)\ny = Num.new(y)\nPoint.new(x, y)\n"}},{"html_id":"mod_inv(a:Num|BigInt,prime=P):Num-instance-method","name":"mod_inv","doc":"Computes the elliptic curve modular multiplicative inverse of `a`.\n\nParemeters:\n* `a` (`Num | BigInt`): the integer that we want the modular inverse of.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Num` containing the mod inverse.\n\n```\na = Num.new \"ea678c668356d16d8bf5c69f95c1055e39bd24174605f64846e27c3ae6a88d81\"\nCurve.mod_inv a\n# => #\n```","summary":"

      Computes the elliptic curve modular multiplicative inverse of a.

      ","abstract":false,"args":[{"name":"a","external_name":"a","restriction":"Num | BigInt"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(a : Num | BigInt, prime = P) : Num","args_html":"(a : Num | BigInt, prime = P) : Num","location":{"filename":"src/secp256k1/curve.cr","line_number":37,"url":null},"def":{"name":"mod_inv","args":[{"name":"a","external_name":"a","restriction":"Num | BigInt"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Num","visibility":"Public","body":"if a.is_a?(Num)\n a = a.to_big\nend\nif prime.is_a?(Num)\n prime = prime.to_big\nend\nm_low = 1\nm_high = 0\nv_low = a % prime\nv_high = prime\nwhile v_low > 1\n v_ratio = v_high // v_low\n m_low_r = m_low * v_ratio\n v_low_r = v_low * v_ratio\n m = m_high - m_low_r\n v = v_high - v_low_r\n m_high = m_low\n v_high = v_low\n m_low = m\n v_low = v\nend\nNum.new(m_low % prime)\n"}},{"html_id":"mul(p:Point,s:Num|BigInt):Point-instance-method","name":"mul","doc":"Computes the elliptic curve sequence multiplication of point `p(x, y)`\nand a skalar `s`; with `s` being a private key within the elliptic\ncurve field size of `N`.\n\nParamters:\n* `p` (`Point`): the point `p(x, y)` to be used in the sequencing.\n* `s` (`Num | BigInt`): a skalar, in most cases a private key.\n\nReturns a `Point` as a result of the multiplication.\n\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\ns = Num.new \"f51ad125548b7a283ebf15ab830a25c850d4d863078c48cc9993b79ee18ee11e\"\nCurve.mul p, s\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve sequence multiplication of point p(x, y) and a skalar s; with s being a private key within the elliptic curve field size of N.

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"s","external_name":"s","restriction":"Num | BigInt"}],"args_string":"(p : Point, s : Num | BigInt) : Point","args_html":"(p : Point, s : Num | BigInt) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":162,"url":null},"def":{"name":"mul","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"s","external_name":"s","restriction":"Num | BigInt"}],"return_type":"Point","visibility":"Public","body":"if s.is_a?(Num)\n s = s.to_big\nend\nif (s === 0) || s >= N.to_big\n raise(\"Invalid scalar: outside of Secp256k1 field dimension.\")\nend\ns_bin = s.to_s(2)\nq = p\ns_bin.each_char_with_index do |char, index|\n if index === 0\n next\n end\n q = double(q)\n if char === '1'\n q = add(q, p)\n end\nend\nq\n"}}]},{"html_id":"secp256k1/Secp256k1/Key","path":"Secp256k1/Key.html","kind":"class","full_name":"Secp256k1::Key","name":"Key","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/key.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a `Secp256k1` keypair containing a secret number (private key)\nand a public point on the elliptic curve (public key).\n\nProperties:\n* `private_key` (`Num`): the secret number representing the private key.\n* `public_key` (`Point`): the point on the elliptic curve representing the public key.","summary":"

      Provides a Secp256k1 keypair containing a secret number (private key) and a public point on the elliptic curve (public key).

      ","constructors":[{"html_id":"new(priv:Num)-class-method","name":"new","doc":"Creates a public-private keypair from an existing private key.\n\nParameters:\n* `priv` (`Num`): the private key for the keypair.\n\n```\npriv = Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\nKey.new priv\n# => #,\n# @public_key=#,\n# @y=#>>\n```","summary":"

      Creates a public-private keypair from an existing private key.

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"args_string":"(priv : Num)","args_html":"(priv : Num)","location":{"filename":"src/secp256k1/key.cr","line_number":74,"url":null},"def":{"name":"new","args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(priv)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new-class-method","name":"new","doc":"Creates a new, random `Secp256k1` keypair.\n\n```\nKey.new\n# => #,\n# @public_key=#,\n# @y=#>>\n```","summary":"

      Creates a new, random Secp256k1 keypair.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":46,"url":null},"def":{"name":"new","visibility":"Public","body":"_ = allocate\n_.initialize\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"private_bytes:Bytes-instance-method","name":"private_bytes","doc":"Returns the private key as binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_bytes\n# => Bytes[60, 207, 132, 130, 12, 32, 213, 232, 197, 54, 186, 132, 197, 43, 164, 16, 55, 91, 41, 177, 129, 43, 95, 126, 114, 36, 69, 201, 105, 160, 251, 48]\n```","summary":"

      Returns the private key as binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":95,"url":null},"def":{"name":"private_bytes","return_type":"Bytes","visibility":"Public","body":"@private_key.to_zpadded_bytes"}},{"html_id":"private_hex:String-instance-method","name":"private_hex","doc":"Returns the private key as hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_hex\n# => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\n```","summary":"

      Returns the private key as hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":85,"url":null},"def":{"name":"private_hex","return_type":"String","visibility":"Public","body":"@private_key.to_zpadded_hex"}},{"html_id":"private_key:Num-instance-method","name":"private_key","doc":"The secret number representing the private key.","summary":"

      The secret number representing the private key.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":23,"url":null},"def":{"name":"private_key","return_type":"Num","visibility":"Public","body":"@private_key"}},{"html_id":"private_key=(private_key:Num)-instance-method","name":"private_key=","doc":"The secret number representing the private key.","summary":"

      The secret number representing the private key.

      ","abstract":false,"args":[{"name":"private_key","external_name":"private_key","restriction":"Num"}],"args_string":"(private_key : Num)","args_html":"(private_key : Num)","location":{"filename":"src/secp256k1/key.cr","line_number":23,"url":null},"def":{"name":"private_key=","args":[{"name":"private_key","external_name":"private_key","restriction":"Num"}],"visibility":"Public","body":"@private_key = private_key"}},{"html_id":"public_bytes:Bytes-instance-method","name":"public_bytes","doc":"Returns the public key as uncompressed, binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes\n# => Bytes[4, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162, 129, 54, 61, 41, 142, 74, 64, 235, 203, 19, 241, 175, 168, 90, 11, 148, 185, 103, 242, 67, 238, 89, 165, 144, 16, 203, 93, 234, 240, 215, 182, 108]\n```","summary":"

      Returns the public key as uncompressed, binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":125,"url":null},"def":{"name":"public_bytes","return_type":"Bytes","visibility":"Public","body":"(Num.new(@public_key.uncompressed)).to_bytes"}},{"html_id":"public_bytes_compressed:Bytes-instance-method","name":"public_bytes_compressed","doc":"Returns the public key as compressed, binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes_compressed\n# => Bytes[2, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162]\n```","summary":"

      Returns the public key as compressed, binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":135,"url":null},"def":{"name":"public_bytes_compressed","return_type":"Bytes","visibility":"Public","body":"(Num.new(@public_key.compressed)).to_bytes"}},{"html_id":"public_hex:String-instance-method","name":"public_hex","doc":"Returns the public key as uncompressed, hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex\n# => \"04cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba281363d298e4a40ebcb13f1afa85a0b94b967f243ee59a59010cb5deaf0d7b66c\"\n```","summary":"

      Returns the public key as uncompressed, hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":105,"url":null},"def":{"name":"public_hex","return_type":"String","visibility":"Public","body":"@public_key.uncompressed"}},{"html_id":"public_hex_compressed:String-instance-method","name":"public_hex_compressed","doc":"Returns the public key as compressed, hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex_compressed\n# => \"02cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba2\"\n```","summary":"

      Returns the public key as compressed, hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":115,"url":null},"def":{"name":"public_hex_compressed","return_type":"String","visibility":"Public","body":"@public_key.compressed"}},{"html_id":"public_key:Point-instance-method","name":"public_key","doc":"The point on the elliptic curve representing the public key.","summary":"

      The point on the elliptic curve representing the public key.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":25,"url":null},"def":{"name":"public_key","return_type":"Point","visibility":"Public","body":"@public_key"}},{"html_id":"public_key=(public_key:Point)-instance-method","name":"public_key=","doc":"The point on the elliptic curve representing the public key.","summary":"

      The point on the elliptic curve representing the public key.

      ","abstract":false,"args":[{"name":"public_key","external_name":"public_key","restriction":"Point"}],"args_string":"(public_key : Point)","args_html":"(public_key : Point)","location":{"filename":"src/secp256k1/key.cr","line_number":25,"url":null},"def":{"name":"public_key=","args":[{"name":"public_key","external_name":"public_key","restriction":"Point"}],"visibility":"Public","body":"@public_key = public_key"}}]},{"html_id":"secp256k1/Secp256k1/Num","path":"Secp256k1/Num.html","kind":"class","full_name":"Secp256k1::Num","name":"Num","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/num.cr","line_number":25,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a class to conveniently handle big numbers on the elliptic\ncurve. It allows to easily access decimal, hexadecimal, and binary\nrepresentations of the numeric. In addition, it implements some\nutilities such as zpadding or asserting hexadecimal strings. It's suited\nto temporarily handle unencrypted private keys.\n\nProperties:\n* `hex` (`String`): the hexadecimal string representation of the number.\n* `dec` (`BigInt`): the decimal big-integer representation of the number.\n* `bin` (`Bytes`): the binary bytes-slice represenation of the number.","summary":"

      Provides a class to conveniently handle big numbers on the elliptic curve.

      ","constructors":[{"html_id":"new(hex:String)-class-method","name":"new","doc":"Creates a number from a hexadecimal string literal.\n\nParameters:\n* `hex` (`String`): a hexadecimal string representating the number.\n\n```\nNum.new \"568a0f505bde902db4a6afd207c794c7845fe7715da5999bb276d453c702a46d\"\n# => #\n```","summary":"

      Creates a number from a hexadecimal string literal.

      ","abstract":false,"args":[{"name":"hex","external_name":"hex","restriction":"String"}],"args_string":"(hex : String)","args_html":"(hex : String)","location":{"filename":"src/secp256k1/num.cr","line_number":67,"url":null},"def":{"name":"new","args":[{"name":"hex","external_name":"hex","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(hex)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(num:BigInt)-class-method","name":"new","doc":"Creates a number from a big integer numeric.\n\nParameters:\n* `dec` (`BigInt`): the decimal big-integer representating the number.\n\n```\nNum.new BigInt.new \"39142835565766237398843902819171565157710677457569850027793715608438337348717\"\n# => #\n```","summary":"

      Creates a number from a big integer numeric.

      ","abstract":false,"args":[{"name":"num","external_name":"num","restriction":"BigInt"}],"args_string":"(num : BigInt)","args_html":"(num : BigInt)","location":{"filename":"src/secp256k1/num.cr","line_number":87,"url":null},"def":{"name":"new","args":[{"name":"num","external_name":"num","restriction":"BigInt"}],"visibility":"Public","body":"_ = allocate\n_.initialize(num)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(bin:Slice(UInt8))-class-method","name":"new","doc":"Creates a number from a binary bytes slice.\n\nParameters:\n* `bin` (`Bytes`): the binary bytes-slice represenating the number.\n\n```\nNum.new Bytes[86, 138, 15, 80, 91, 222, 144, 45, 180, 166, 175, 210, 7, 199, 148, 199, 132, 95, 231, 113, 93, 165, 153, 155, 178, 118, 212, 83, 199, 2, 164, 109]\n# => #\n```","summary":"

      Creates a number from a binary bytes slice.

      ","abstract":false,"args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"args_string":"(bin : Slice(UInt8))","args_html":"(bin : Slice(UInt8))","location":{"filename":"src/secp256k1/num.cr","line_number":107,"url":null},"def":{"name":"new","args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"visibility":"Public","body":"_ = allocate\n_.initialize(bin)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new-class-method","name":"new","doc":"Creates a random number using `Random::Secure` that can be used as\na secret (private key).\n\n```\nNum.new\n# => #\n```","summary":"

      Creates a random number using Random::Secure that can be used as a secret (private key).

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":43,"url":null},"def":{"name":"new","visibility":"Public","body":"_ = allocate\n_.initialize\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"bin:Slice(UInt8)-instance-method","name":"bin","doc":"The binary bytes-slice represenation of the number.","summary":"

      The binary bytes-slice represenation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":31,"url":null},"def":{"name":"bin","return_type":"Slice(UInt8)","visibility":"Public","body":"@bin"}},{"html_id":"bin=(bin:Slice(UInt8))-instance-method","name":"bin=","doc":"The binary bytes-slice represenation of the number.","summary":"

      The binary bytes-slice represenation of the number.

      ","abstract":false,"args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"args_string":"(bin : Slice(UInt8))","args_html":"(bin : Slice(UInt8))","location":{"filename":"src/secp256k1/num.cr","line_number":31,"url":null},"def":{"name":"bin=","args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"visibility":"Public","body":"@bin = bin"}},{"html_id":"dec:BigInt-instance-method","name":"dec","doc":"The decimal big-integer representation of the number.","summary":"

      The decimal big-integer representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":29,"url":null},"def":{"name":"dec","return_type":"BigInt","visibility":"Public","body":"@dec"}},{"html_id":"dec=(dec:BigInt)-instance-method","name":"dec=","doc":"The decimal big-integer representation of the number.","summary":"

      The decimal big-integer representation of the number.

      ","abstract":false,"args":[{"name":"dec","external_name":"dec","restriction":"BigInt"}],"args_string":"(dec : BigInt)","args_html":"(dec : BigInt)","location":{"filename":"src/secp256k1/num.cr","line_number":29,"url":null},"def":{"name":"dec=","args":[{"name":"dec","external_name":"dec","restriction":"BigInt"}],"visibility":"Public","body":"@dec = dec"}},{"html_id":"hex:String-instance-method","name":"hex","doc":"The hexadecimal string representation of the number.","summary":"

      The hexadecimal string representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":27,"url":null},"def":{"name":"hex","return_type":"String","visibility":"Public","body":"@hex"}},{"html_id":"hex=(hex:String)-instance-method","name":"hex=","doc":"The hexadecimal string representation of the number.","summary":"

      The hexadecimal string representation of the number.

      ","abstract":false,"args":[{"name":"hex","external_name":"hex","restriction":"String"}],"args_string":"(hex : String)","args_html":"(hex : String)","location":{"filename":"src/secp256k1/num.cr","line_number":27,"url":null},"def":{"name":"hex=","args":[{"name":"hex","external_name":"hex","restriction":"String"}],"visibility":"Public","body":"@hex = hex"}},{"html_id":"to_big:BigInt-instance-method","name":"to_big","doc":"Returns a big-integer representation of the number.\n\n```\nNum.new(Bytes[137]).to_big\n# => 137\n```","summary":"

      Returns a big-integer representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":156,"url":null},"def":{"name":"to_big","return_type":"BigInt","visibility":"Public","body":"@dec"}},{"html_id":"to_bytes:Bytes-instance-method","name":"to_bytes","doc":"Returns a binary byte-slice representation of the number.\n\n```\nNum.new(\"0x89\").to_bytes\n# => Bytes[137]\n```","summary":"

      Returns a binary byte-slice representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":166,"url":null},"def":{"name":"to_bytes","return_type":"Bytes","visibility":"Public","body":"@bin"}},{"html_id":"to_hex:String-instance-method","name":"to_hex","doc":"Returns an unprefixed hexadecimal string representation.\n\n```\nNum.new(Bytes[137]).to_hex\n# => \"89\"\n```","summary":"

      Returns an unprefixed hexadecimal string representation.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":119,"url":null},"def":{"name":"to_hex","return_type":"String","visibility":"Public","body":"@hex"}},{"html_id":"to_prefixed_hex:String-instance-method","name":"to_prefixed_hex","doc":"Returns an `0x`-prefixed hexadecimal string representation.\n\n```\nNum.new(Bytes[137]).to_prefixed_hex\n# => \"0x89\"\n```","summary":"

      Returns an 0x-prefixed hexadecimal string representation.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":129,"url":null},"def":{"name":"to_prefixed_hex","return_type":"String","visibility":"Public","body":"\"0x#{@hex}\""}},{"html_id":"to_zpadded_bytes(length=32):Bytes-instance-method","name":"to_zpadded_bytes","doc":"Returns a z-padded byte-slice binary representation.\n\nParameters:\n* `length` (`Int`): the byte-size of the final z-padded slice (default `32`).\n\n```\nNum.new(Bytes[137]).to_zpadded_bytes\n# => Bytes[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137]\n```","summary":"

      Returns a z-padded byte-slice binary representation.

      ","abstract":false,"args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"args_string":"(length = 32) : Bytes","args_html":"(length = 32) : Bytes","location":{"filename":"src/secp256k1/num.cr","line_number":179,"url":null},"def":{"name":"to_zpadded_bytes","args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"return_type":"Bytes","visibility":"Public","body":"zpadded_bytes = @bin\nwhile zpadded_bytes.size < length\n zpadded_bytes = Util.concat_bytes(Bytes[0], zpadded_bytes)\nend\nzpadded_bytes\n"}},{"html_id":"to_zpadded_hex(length=32):String-instance-method","name":"to_zpadded_hex","doc":"Returns a z-padded hexadecimal string representation.\n\nParameters:\n* `length` (`Int`): the byte-size of the final z-padded hex-string (default `32`).\n\n```\nNum.new(Bytes[137]).to_zpadded_hex\n# => \"0000000000000000000000000000000000000000000000000000000000000089\"\n```","summary":"

      Returns a z-padded hexadecimal string representation.

      ","abstract":false,"args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"args_string":"(length = 32) : String","args_html":"(length = 32) : String","location":{"filename":"src/secp256k1/num.cr","line_number":142,"url":null},"def":{"name":"to_zpadded_hex","args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"return_type":"String","visibility":"Public","body":"zpadded_hex = @hex\nwhile zpadded_hex.size < (length * 2)\n zpadded_hex = \"0#{zpadded_hex}\"\nend\nzpadded_hex\n"}}]},{"html_id":"secp256k1/Secp256k1/Point","path":"Secp256k1/Point.html","kind":"class","full_name":"Secp256k1::Point","name":"Point","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/point.cr","line_number":30,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a point in the two-dimensional space of any elliptic curve.\nIn most cases, such a point on a given curve represents a public key.\nHowever, for keypairs, a `Key` type shall be used!\n\nProperties:\n* `x` (`Num`): the position on the x-axis.\n* `y` (`Num`): the position on the y-axis.","summary":"

      Provides a point in the two-dimensional space of any elliptic curve.

      ","constructors":[{"html_id":"new(x:Num,y:Num)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing the x- and y-coordinates (public key).\n\nParameters:\n* `x` (`Num`): the position on the x-axis.\n* `y` (`Num`): the position on the y-axis.\n\n```\nx = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ny = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nPoint.new x, y\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing the x- and y-coordinates (public key).

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Num"},{"name":"y","external_name":"y","restriction":"Num"}],"args_string":"(x : Num, y : Num)","args_html":"(x : Num, y : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":58,"url":null},"def":{"name":"new","args":[{"name":"x","external_name":"x","restriction":"Num"},{"name":"y","external_name":"y","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(x, y)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(priv:Num)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing a random number (private key). Note, that the\nprivate key will be consumed by this constructor and should only be used\nto retrieve a public key. To manage keypairs, use the `Key` type instead.\n\nParameters:\n* `priv` (`Num`): the random number giving access to the point.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new priv\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing a random number (private key).

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"args_string":"(priv : Num)","args_html":"(priv : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":84,"url":null},"def":{"name":"new","args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(priv)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(pub:String)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing a compressed or uncompressed public key.\n\nParameters:\n* `pub` (`String`): the public key string (compressed or uncompressed).\n\n```\npub = \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\"\nPoint.new pub\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing a compressed or uncompressed public key.

      ","abstract":false,"args":[{"name":"pub","external_name":"pub","restriction":"String"}],"args_string":"(pub : String)","args_html":"(pub : String)","location":{"filename":"src/secp256k1/point.cr","line_number":109,"url":null},"def":{"name":"new","args":[{"name":"pub","external_name":"pub","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(pub)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"compressed:String-instance-method","name":"compressed","doc":"Returns a prefixed, compressed public key string for the given point\nin the format `prefix|x|y`.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new(priv).compressed\n# => \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\"\n```","summary":"

      Returns a prefixed, compressed public key string for the given point in the format prefix|x|y.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":161,"url":null},"def":{"name":"compressed","return_type":"String","visibility":"Public","body":"prefix = 2 + (@y.to_big % 2)\nprefix = \"0#{prefix}\"\n\"#{prefix}#{@x.to_zpadded_hex}\"\n"}},{"html_id":"uncompressed:String-instance-method","name":"uncompressed","doc":"Returns a prefixed, uncompressed public key string for the given point\nin the format `04|x|y`.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new(priv).uncompressed\n# => \"04aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f21f4c49cfe90da39c254a51b8ee8afcdd8c02dd566f13582c23e104c7ed5936b\"\n```","summary":"

      Returns a prefixed, uncompressed public key string for the given point in the format 04|x|y.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":148,"url":null},"def":{"name":"uncompressed","return_type":"String","visibility":"Public","body":"prefix = \"04\"\n\"#{prefix}#{@x.to_zpadded_hex}#{@y.to_zpadded_hex}\"\n"}},{"html_id":"x:Num-instance-method","name":"x","doc":"The position on the x-axis.","summary":"

      The position on the x-axis.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":32,"url":null},"def":{"name":"x","return_type":"Num","visibility":"Public","body":"@x"}},{"html_id":"x=(x:Num)-instance-method","name":"x=","doc":"The position on the x-axis.","summary":"

      The position on the x-axis.

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Num"}],"args_string":"(x : Num)","args_html":"(x : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":32,"url":null},"def":{"name":"x=","args":[{"name":"x","external_name":"x","restriction":"Num"}],"visibility":"Public","body":"@x = x"}},{"html_id":"y:Num-instance-method","name":"y","doc":"The position on the y-axis.","summary":"

      The position on the y-axis.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":35,"url":null},"def":{"name":"y","return_type":"Num","visibility":"Public","body":"@y"}},{"html_id":"y=(y:Num)-instance-method","name":"y=","doc":"The position on the y-axis.","summary":"

      The position on the y-axis.

      ","abstract":false,"args":[{"name":"y","external_name":"y","restriction":"Num"}],"args_string":"(y : Num)","args_html":"(y : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":35,"url":null},"def":{"name":"y=","args":[{"name":"y","external_name":"y","restriction":"Num"}],"visibility":"Public","body":"@y = y"}}]},{"html_id":"secp256k1/Secp256k1/Signature","path":"Secp256k1/Signature.html","kind":"class","full_name":"Secp256k1::Signature","name":"Signature","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/signature.cr","line_number":22,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides an ECDSA Signature containing the random point `r`, the\nsignature proof `s`, and the recovery id or `v` value.\n\nProperties:\n* `r` (`Num`): the `x` coordinate of a random point `R` on the curve.\n* `s` (`Num`): the signature proof of a message.\n* `v` (`Num`): the recovery id or `v` value.","summary":"

      Provides an ECDSA Signature containing the random point #r, the signature proof #s, and the recovery id or #v value.

      ","constructors":[{"html_id":"new(r:Num,s:Num,v:Num)-class-method","name":"new","doc":"Provides an ECDSA Signature containing the random point `r`, the\nsignature proof `s`, and the recovery id or `v` value.\n\nParameters:\n* `r` (`Num`): the `x` coordinate of a random point `R` on the curve.\n* `s` (`Num`): the signature proof of a message.\n* `v` (`Num`): the recovery id or `v` value.\n\n```\nr = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ns = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nv = Num.new \"00\"\nSignature.new r, s, v\n# => #,\n# @s=#,\n# @v=#>\n```","summary":"

      Provides an ECDSA Signature containing the random point #r, the signature proof #s, and the recovery id or #v value.

      ","abstract":false,"args":[{"name":"r","external_name":"r","restriction":"Num"},{"name":"s","external_name":"s","restriction":"Num"},{"name":"v","external_name":"v","restriction":"Num"}],"args_string":"(r : Num, s : Num, v : Num)","args_html":"(r : Num, s : Num, v : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":59,"url":null},"def":{"name":"new","args":[{"name":"r","external_name":"r","restriction":"Num"},{"name":"s","external_name":"s","restriction":"Num"},{"name":"v","external_name":"v","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(r, s, v)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"compact:String-instance-method","name":"compact","doc":"Returns a compact `String` containing the concatenated signature\nin the form `r|s|v`.\n\n```\nr = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ns = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nv = Num.new \"00\"\nSignature.new(r, s, v).compact\n# => \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae000\"\n```","summary":"

      Returns a compact String containing the concatenated signature in the form r|s|v.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":75,"url":null},"def":{"name":"compact","return_type":"String","visibility":"Public","body":"\"#{r.to_zpadded_hex}#{s.to_zpadded_hex}#{v.to_hex}\""}},{"html_id":"r:Num-instance-method","name":"r","doc":"The `x` coordinate of a random point `R` on the curve.","summary":"

      The x coordinate of a random point R on the curve.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":24,"url":null},"def":{"name":"r","return_type":"Num","visibility":"Public","body":"@r"}},{"html_id":"r=(r:Num)-instance-method","name":"r=","doc":"The `x` coordinate of a random point `R` on the curve.","summary":"

      The x coordinate of a random point R on the curve.

      ","abstract":false,"args":[{"name":"r","external_name":"r","restriction":"Num"}],"args_string":"(r : Num)","args_html":"(r : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":24,"url":null},"def":{"name":"r=","args":[{"name":"r","external_name":"r","restriction":"Num"}],"visibility":"Public","body":"@r = r"}},{"html_id":"s:Num-instance-method","name":"s","doc":"The signature proof of a message.","summary":"

      The signature proof of a message.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":27,"url":null},"def":{"name":"s","return_type":"Num","visibility":"Public","body":"@s"}},{"html_id":"s=(s:Num)-instance-method","name":"s=","doc":"The signature proof of a message.","summary":"

      The signature proof of a message.

      ","abstract":false,"args":[{"name":"s","external_name":"s","restriction":"Num"}],"args_string":"(s : Num)","args_html":"(s : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":27,"url":null},"def":{"name":"s=","args":[{"name":"s","external_name":"s","restriction":"Num"}],"visibility":"Public","body":"@s = s"}},{"html_id":"v:Num-instance-method","name":"v","doc":"The recovery id or `v` value.","summary":"

      The recovery id or #v value.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":30,"url":null},"def":{"name":"v","return_type":"Num","visibility":"Public","body":"@v"}},{"html_id":"v=(v:Num)-instance-method","name":"v=","doc":"The recovery id or `v` value.","summary":"

      The recovery id or #v value.

      ","abstract":false,"args":[{"name":"v","external_name":"v","restriction":"Num"}],"args_string":"(v : Num)","args_html":"(v : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":30,"url":null},"def":{"name":"v=","args":[{"name":"v","external_name":"v","restriction":"Num"}],"visibility":"Public","body":"@v = v"}}]},{"html_id":"secp256k1/Secp256k1/Util","path":"Secp256k1/Util.html","kind":"module","full_name":"Secp256k1::Util","name":"Util","abstract":false,"locations":[{"filename":"src/secp256k1/util.cr","line_number":17,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"secp256k1/Secp256k1/Util","kind":"module","full_name":"Secp256k1::Util","name":"Util"}],"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a collection of utilities for convenience, e.g., to bind\nrelevant hashing algorithms, or to concatenate byte slices.","summary":"

      Provides a collection of utilities for convenience, e.g., to bind relevant hashing algorithms, or to concatenate byte slices.

      ","instance_methods":[{"html_id":"concat_bytes(x:Bytes,y:Bytes):Bytes-instance-method","name":"concat_bytes","doc":"Concatenates two byte slices in the order provided, i.e., `x|y`.\n\nParameters:\n* `x` (`Bytes`): a byte slice.\n* `y` (`Bytes`): another byte slice.\n\nReturns a concatenated `Bytes` slice.\n\n```\nUtil.concat_bytes Bytes[1, 2, 3], Bytes[9, 8, 7]\n# => Bytes[1, 2, 3, 9, 8, 7]\n```","summary":"

      Concatenates two byte slices in the order provided, i.e., x|y.

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Bytes"},{"name":"y","external_name":"y","restriction":"Bytes"}],"args_string":"(x : Bytes, y : Bytes) : Bytes","args_html":"(x : Bytes, y : Bytes) : Bytes","location":{"filename":"src/secp256k1/util.cr","line_number":177,"url":null},"def":{"name":"concat_bytes","args":[{"name":"x","external_name":"x","restriction":"Bytes"},{"name":"y","external_name":"y","restriction":"Bytes"}],"return_type":"Bytes","visibility":"Public","body":"z = IO::Memory.new(x.bytesize + y.bytesize)\nx.each do |b|\n z.write_bytes(UInt8.new(b))\nend\ny.each do |b|\n z.write_bytes(UInt8.new(b))\nend\nreturn z.to_slice\n"}},{"html_id":"deterministic_k(priv:Num,hash:Num,order=N):Num-instance-method","name":"deterministic_k","doc":"Provides a deterministic secret based on private key and message hash\nas defined in RFC-6979.\n\nRef: [datatracker.ietf.org/doc/html/rfc6979](https://datatracker.ietf.org/doc/html/rfc6979)\n\nParameters:\n* `priv` (`Num`): the private key or secret number.\n* `hash` (`Num`): the message hash or arbirtrary data hash.\n* `order` (`Num`): the order of the curve over `G` (default `N`).\n\nReturns a deterministically random number of type `Num`.\n\n```\npriv = Num.new \"3b74fcc0b0c419a00d2d9e88b15fbd99e03920138da22e2a00c327b88d24cf45\"\nhash = Util.sha256 \"Henlo, Wordl\"\nUtil.deterministic_k(priv, hash)\n# => #\n```","summary":"

      Provides a deterministic secret based on private key and message hash as defined in RFC-6979.

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"order","default_value":"N","external_name":"order","restriction":""}],"args_string":"(priv : Num, hash : Num, order = N) : Num","args_html":"(priv : Num, hash : Num, order = N) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":135,"url":null},"def":{"name":"deterministic_k","args":[{"name":"priv","external_name":"priv","restriction":"Num"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"order","default_value":"N","external_name":"order","restriction":""}],"return_type":"Num","visibility":"Public","body":"order_size = order.hex.size // 2\nv = Num.new(Bytes.new(order_size, 1))\nk = Num.new(Bytes.new(order_size, 0))\nconcat = Util.concat_bytes(v.bin, Bytes[0])\nconcat = Util.concat_bytes(concat, priv.bin)\nconcat = Util.concat_bytes(concat, hash.bin)\nk = OpenSSL::HMAC.digest(:sha256, k.bin, concat)\nv = OpenSSL::HMAC.digest(:sha256, k, v.bin)\nconcat = Util.concat_bytes(v, Bytes[0])\nconcat = Util.concat_bytes(concat, priv.bin)\nconcat = Util.concat_bytes(concat, hash.bin)\nk = OpenSSL::HMAC.digest(:sha256, k, concat)\nv = OpenSSL::HMAC.digest(:sha256, k, v)\nwhile true\n t = IO::Memory.new.to_slice\n while t.size < order_size\n v = OpenSSL::HMAC.digest(:sha256, k, v)\n t = Util.concat_bytes(t, v)\n end\n secret = Num.new(t)\n if secret.dec < order.dec && secret.dec > 0\n return secret\n end\n increment = Util.concat_bytes(v, Bytes[0])\n k = OpenSSL::HMAC.digest(:sha256, k, increment)\n v = OpenSSL::HMAC.digest(:sha256, k, v)\nend\n"}},{"html_id":"keccak(data:Num|String,entropy=256):Num-instance-method","name":"keccak","doc":"Operating a Keccak hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | String`): the binary numeric or string literal to be hashed.\n* `entropy` (`Int32`): the required entropy (default `256`).\n\nReturns a `Num` representing the Keccak hash.\n\n```\nUtil.keccak(Num.new \"0xdeadbeef\").hex\n# => \"d4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1\"\n\nUtil.keccak(\"0xdeadbeef\").hex\n# => \"4f440a001006a49f24a7de53c04eca3f79aef851ac58e460c9630d044277c8b0\"\n```","summary":"

      Operating a Keccak hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"args_string":"(data : Num | String, entropy = 256) : Num","args_html":"(data : Num | String, entropy = 256) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":35,"url":null},"def":{"name":"keccak","args":[{"name":"data","external_name":"data","restriction":"Num | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"return_type":"Num","visibility":"Public","body":"keccak = Digest::Keccak3.new(entropy)\nif data.is_a?(String)\n return Num.new((keccak.update(data)).hexdigest)\nelse\n return Num.new((keccak.update(data.to_bytes)).hexdigest)\nend\n"}},{"html_id":"ripemd160(data:Num|String):Num-instance-method","name":"ripemd160","doc":"Operating a RIPEMD-160 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | String`): the binary numeric or string literal to be hashed.\n\nReturns a `Num` representing the RIPEMD hash.\n\n```\nUtil.ripemd160(Num.new \"0xdeadbeef\").hex\n# => \"226821c2f5423e11fe9af68bd285c249db2e4b5a\"\n\nUtil.ripemd160(\"0xdeadbeef\").hex\n# => \"4caf817f14e84b564e47afd19966e5d123ee0183\"\n```","summary":"

      Operating a RIPEMD-160 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | String"}],"args_string":"(data : Num | String) : Num","args_html":"(data : Num | String) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":105,"url":null},"def":{"name":"ripemd160","args":[{"name":"data","external_name":"data","restriction":"Num | String"}],"return_type":"Num","visibility":"Public","body":"ripemd = OpenSSL::Digest.new(\"RIPEMD160\")\nif data.is_a?(String)\n return Num.new((ripemd.update(data)).final.hexstring)\nelse\n return Num.new((ripemd.update(data.to_bytes)).final.hexstring)\nend\n"}},{"html_id":"sha256(data:Num|String):Num-instance-method","name":"sha256","doc":"Operating a SHA2-256 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | String`): the binary numeric or string literal to be hashed.\n\nReturns a `Num` representing the SHA2 hash.\n\n```\nUtil.sha256(Num.new \"0xdeadbeef\").hex\n# => \"5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953\"\n\nUtil.sha256(\"0xdeadbeef\").hex\n# => \"4142710b9b4caaeb000b8e5de271bbebac7f509aab2f5e61d1ed1958bfe6d583\"\n```","summary":"

      Operating a SHA2-256 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | String"}],"args_string":"(data : Num | String) : Num","args_html":"(data : Num | String) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":82,"url":null},"def":{"name":"sha256","args":[{"name":"data","external_name":"data","restriction":"Num | String"}],"return_type":"Num","visibility":"Public","body":"sha2 = OpenSSL::Digest.new(\"SHA256\")\nif data.is_a?(String)\n return Num.new((sha2.update(data)).final.hexstring)\nelse\n return Num.new((sha2.update(data.to_bytes)).final.hexstring)\nend\n"}},{"html_id":"sha3(data:Num|String,entropy=256):Num-instance-method","name":"sha3","doc":"Operating a SHA3 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | String`): the binary numeric or string literal to be hashed.\n* `entropy` (`Int32`): the required entropy (default `256`).\n\nReturns a `Num` representing the SHA3 hash.\n\n```\nUtil.sha3(Num.new \"0xdeadbeef\").hex\n# => \"352b82608dad6c7ac3dd665bc2666e5d97803cb13f23a1109e2105e93f42c448\"\n\nUtil.sha3(\"0xdeadbeef\").hex\n# => \"c12811e13ed75afe3e0945ef34e8a25b9d321a46e131c6463731de25a21b39eb\"\n```","summary":"

      Operating a SHA3 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"args_string":"(data : Num | String, entropy = 256) : Num","args_html":"(data : Num | String, entropy = 256) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":59,"url":null},"def":{"name":"sha3","args":[{"name":"data","external_name":"data","restriction":"Num | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"return_type":"Num","visibility":"Public","body":"sha3 = Digest::SHA3.new(entropy)\nif data.is_a?(String)\n return Num.new((sha3.update(data)).hexdigest)\nelse\n return Num.new((sha3.update(data.to_bytes)).hexdigest)\nend\n"}}]}]}]}} \ No newline at end of file +{"repository_name":"secp256k1","body":"# secp256k1.cr\n\n[![Build Status](https://img.shields.io/github/workflow/status/q9f/secp256k1.cr/Nightly)](https://github.com/q9f/secp256k1.cr/actions)\n[![Code Coverage](https://codecov.io/gh/q9f/secp256k1.cr/branch/main/graph/badge.svg?token=ngxRs9HdJA)](https://codecov.io/gh/q9f/secp256k1.cr)\n[![Documentation](https://img.shields.io/badge/docs-html-black)](https://q9f.github.io/secp256k1.cr/)\n[![Release](https://img.shields.io/github/v/release/q9f/secp256k1.cr?include_prereleases&color=black)](https://github.com/q9f/secp256k1.cr/releases/latest)\n[![Language](https://img.shields.io/github/languages/top/q9f/secp256k1.cr?color=black)](https://github.com/q9f/secp256k1.cr/search?l=crystal)\n[![License](https://img.shields.io/github/license/q9f/secp256k1.cr.svg?color=black)](LICENSE)\n\nA library implementing the `Secp256k1` elliptic curve natively in pure Crystal.\n`Secp256k1` is the elliptic curve used in the public-private-key cryptography required by `Bitcoin`, `Ethereum`, and `Polkadot`.\n\nThis library allows for:\n* providing a `Secp256k1` cryptographic context, see `Secp256k1::Context`\n* managing `Secp256k1` signatures and verification, see `Secp256k1::Signature`\n* managing private-public keypairs, see `Secp256k1::Key`\n* generating public keys, see `Secp256k1::Point`\n* generating private keys, see `Secp256k1::Num`\n\n# Installation\n\nAdd the `Secp256k1` library to your `shard.yml`\n\n```yaml\ndependencies:\n secp256k1:\n github: q9f/secp256k1.cr\n version: \"~> 0.5\"\n```\n\n# Usage\n\nImport and expose the `Secp256k1` module.\n\n```crystal\nrequire \"secp256k1\"\n```\n\nThis library exposes the following modules and classes (in logical order):\n\n* `Secp256k1`: necessary constants and data structures, including:\n - `Secp256k1::Num`: for managing big numerics (private keys)\n - `Secp256k1::Point`: for handling of elliptic curve points (public keys)\n - `Secp256k1::Key`: for managing private-public keypairs (accounts)\n - `Secp256k1::Signature`: for handling ECDSA signatures (r, s, v)\n* `Secp256k1::Context`: providing a cryptographic context for signing and verification\n* `Secp256k1::Curve`: the entire core mathematics behind the elliptic curve cryptography\n* `Secp256k1::Util`: binding of various hashing algorithms for convenience\n\nBasic usage:\n\n```crystal\n# generates a new, random keypair\nkey = Secp256k1::Key.new\n# => #,\n# @public_key=#,\n# @y=#>>\n\n# gets the private key\nkey.private_hex\n# => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\n\n# gets the compressed public key with prefix\nkey.public_hex_compressed\n# => \"02cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba2\"\n```\n\nSignature generation and verification:\n\n```crystal\n# sign a message with a private key\nctx = Secp256k1::Context.new\npriv = Secp256k1::Num.new \"1f0c122d41ff536b19bfd83537c0dfc290e45cd3c375a43237c8b8fff7ac8af7\"\nkey = Secp256k1::Key.new priv\nhash = Secp256k1::Util.sha256 \"Henlo, Wordl\"\nsig = ctx.sign key, hash\n# => #,\n# @s=#,\n# @v=#>\n\n# verify a signature with a public key\nr = Secp256k1::Num.new \"c4079db44240b7afe94985c69fc89602e33629fd9b8623d711c30ce6378b33df\"\ns = Secp256k1::Num.new \"6842c1b63c94bdb8e4f5ae88fb65f7a98b77b197c8323004fb47ef57fab29053\"\nv = Secp256k1::Num.new \"00\"\nsig = Secp256k1::Signature.new r, s, v\nhash = Secp256k1::Util.sha256 \"Henlo, Wordl\"\npubl = Secp256k1::Point.new \"0416008a369439f1a8a75cf974860bed5b10180518d6b1dd3ac847f423fd375d6aa29474394f0cd79d2ea543507d069e97339284f01bdbfd27392daec0ec553816\"\nctx.verify sig, hash, publ\n# => true\n```\n\n# Documentation\n\nThe full library documentation can be found here: [q9f.github.io/secp256k1.cr](https://q9f.github.io/secp256k1.cr/)\n\nGenerate a local copy with:\n\n```shell\ncrystal docs\n```\n\n# Testing\n\nThe library is entirely specified through tests in `./spec`; run:\n\n```shell\ncrystal spec --verbose\n```\n\n# Understand\n\nPrivate keys are just scalars (`Secp256k1::Num`) and public keys are points (`Secp256k1::Point`) with `x` and `y` coordinates.\n\nBitcoin public keys can be uncompressed `p|x|y` or compressed `p|x`. both come with a prefix `p` which is useless for uncompressed keys but necessary for compressed keys to recover the `y` coordinate on the `Secp256k1` elliptic curve field.\n\nEthereum public keys are uncompressed `x|y` without any prefix. The last 20 bytes slice of the `y` coordinate is actually used as address without any checksum. A checksum was later added in EIP-55 using a `keccak256` hash and indicating character capitalization.\n\nNeither Bitcoin nor Ethereum allow for recovering public keys from an address unless there exists a transaction with a valid signature on the blockchain.\n\n# Known issues\n\n_Note: this library should not be used in production without proper auditing. It should be considered slow and insecure._\n\n* This library is not constant time and might be subject to side-channel attacks. ([#4](https://github.com/q9f/secp256k1.cr/issues/4))\n* This library does unnecessary big-integer math and should someday rather correctly implement the `Secp256k1` prime field ([#5](https://github.com/q9f/secp256k1.cr/issues/5))\n* This library is slow in recovering signatures. Future versions should respect the recovery ID to quickly identify the correct public key from a signature.\n\nFound any other issue? Report it: [github.com/q9f/secp256k1.cr/issues](https://github.com/q9f/secp256k1.cr/issues)\n\n# Contribute\n\nCreate a pull request, and make sure tests and linter pass.\n\nThis pure crystal implementation is based on the python implementation [wobine/blackboard101](https://github.com/wobine/blackboard101) which is also used as reference to write tests against. It's a complete rewrite of the abandoned [packetzero/bitcoinutils](https://github.com/packetzero/bitcoinutils) for educational purposes.\n\nHonerable mention for the [bitcoin wiki](https://en.bitcoin.it/wiki/Main_Page) and the [ethereum stackexchange](https://ethereum.stackexchange.com/) for providing so many in-depth resources that supported this project in reimplementing everything.\n\nLicense: Apache License v2.0\n\nContributors: [**@q9f**](https://github.com/q9f/), [@cserb](https://github.com/cserb), [MrSorcus](https://github.com/MrSorcus)\n","program":{"html_id":"secp256k1/toplevel","path":"toplevel.html","kind":"module","full_name":"Top Level Namespace","name":"Top Level Namespace","abstract":false,"ancestors":[{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"}],"locations":[],"repository_name":"secp256k1","program":true,"enum":false,"alias":false,"const":false,"included_modules":[{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"}],"extended_modules":[{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"}],"types":[{"html_id":"secp256k1/Bitcoin","path":"Bitcoin.html","kind":"module","full_name":"Bitcoin","name":"Bitcoin","abstract":false,"locations":[{"filename":"src/bitcoin.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"BASE_58","name":"BASE_58","value":"\"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\"","doc":"The Base-58 alphabet for `Bitcoin` addresses is a Base-64 alphabet without\n`0`, `O`, `I`, and `l` to omit similar-looking letters.","summary":"

      The Base-58 alphabet for Bitcoin addresses is a Base-64 alphabet without 0, O, I, and l to omit similar-looking letters.

      "}],"doc":"An example implementation of a `Bitcoin` account using an `Secp256k1`\nkey-pair and a Bitcoin network version identifier; only for educational\npurposes and should not be used in production.","summary":"

      An example implementation of a Bitcoin account using an Secp256k1 key-pair and a Bitcoin network version identifier; only for educational purposes and should not be used in production.

      ","types":[{"html_id":"secp256k1/Bitcoin/Account","path":"Bitcoin/Account.html","kind":"class","full_name":"Bitcoin::Account","name":"Account","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/bitcoin.cr","line_number":29,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Bitcoin","kind":"module","full_name":"Bitcoin","name":"Bitcoin"},"doc":"An example implementation of a `Bitcoin` account using an `Secp256k1`\nkey-pair and a Bitcoin network version identifier; only for educational\npurposes and should not be used in production.","summary":"

      An example implementation of a Bitcoin account using an Secp256k1 key-pair and a Bitcoin network version identifier; only for educational purposes and should not be used in production.

      ","constructors":[{"html_id":"new(key=Key.new,version=Num.new(\"0x00\"))-class-method","name":"new","doc":"Creates a Bitcoin account from a given `Secp256k1::Key` keypay and for the\nspecified network version, e.g., `00` for Bitcoin main network. It creates\na random account if no parameters are supplied.\n\nParameters:\n* `key` (`Secp256k1::Key`): the `Secp256k1` keypair for the account.\n* `version` (`Secp256k1::Num`): the network version indicator.\n\n```\npriv = Secp256k1::Num.new \"18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725\"\nkey = Secp256k1::Key.new priv\naccount = Bitcoin::Account.new key\n# => #,\n# @public_key=#,\n# @y=#>>,\n# @version=#,\n# @address=\"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM\",\n# @address_compressed=\"1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\",\n# @wif=\"5J1F7GHadZG3sCCKHCwg8Jvys9xUbFsjLnGec4H125Ny1V9nR6V\",\n# @wif_compressed=\"Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C\">\n```","summary":"

      Creates a Bitcoin account from a given Secp256k1::Key keypay and for the specified network version, e.g., 00 for Bitcoin main network.

      ","abstract":false,"args":[{"name":"key","default_value":"Key.new","external_name":"key","restriction":""},{"name":"version","default_value":"Num.new(\"0x00\")","external_name":"version","restriction":""}],"args_string":"(key = Key.new, version = Num.new(\"0x00\"))","args_html":"(key = Key.new, version = Num.new("0x00"))","location":{"filename":"src/bitcoin.cr","line_number":79,"url":null},"def":{"name":"new","args":[{"name":"key","default_value":"Key.new","external_name":"key","restriction":""},{"name":"version","default_value":"Num.new(\"0x00\")","external_name":"version","restriction":""}],"visibility":"Public","body":"_ = allocate\n_.initialize(key, version)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"address:String-instance-method","name":"address","doc":"The public, uncompressed Bitcoin account address.","summary":"

      The public, uncompressed Bitcoin account address.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":35,"url":null},"def":{"name":"address","return_type":"String","visibility":"Public","body":"@address"}},{"html_id":"address_compressed:String-instance-method","name":"address_compressed","doc":"The public, compressed Bitcoin account address.","summary":"

      The public, compressed Bitcoin account address.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":37,"url":null},"def":{"name":"address_compressed","return_type":"String","visibility":"Public","body":"@address_compressed"}},{"html_id":"key:Key-instance-method","name":"key","doc":"The `Secp256k1` keypair for the account.","summary":"

      The Secp256k1 keypair for the account.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":31,"url":null},"def":{"name":"key","return_type":"Key","visibility":"Public","body":"@key"}},{"html_id":"version:Num-instance-method","name":"version","doc":"The network version indicator.","summary":"

      The network version indicator.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":33,"url":null},"def":{"name":"version","return_type":"Num","visibility":"Public","body":"@version"}},{"html_id":"wif:String-instance-method","name":"wif","doc":"The private, uncompressed wallet-import format.","summary":"

      The private, uncompressed wallet-import format.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":39,"url":null},"def":{"name":"wif","return_type":"String","visibility":"Public","body":"@wif"}},{"html_id":"wif_compressed:String-instance-method","name":"wif_compressed","doc":"The private, compressed wallet-import format.","summary":"

      The private, compressed wallet-import format.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":41,"url":null},"def":{"name":"wif_compressed","return_type":"String","visibility":"Public","body":"@wif_compressed"}}]}]},{"html_id":"secp256k1/Ethereum","path":"Ethereum.html","kind":"module","full_name":"Ethereum","name":"Ethereum","abstract":false,"locations":[{"filename":"src/ethereum.cr","line_number":15,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false},{"html_id":"secp256k1/Secp256k1","path":"Secp256k1.html","kind":"module","full_name":"Secp256k1","name":"Secp256k1","abstract":false,"locations":[{"filename":"src/secp256k1.cr","line_number":35,"url":null},{"filename":"src/secp256k1/context.cr","line_number":22,"url":null},{"filename":"src/secp256k1/version.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"G","name":"G","value":"Point.new(Num.new(\"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\"), Num.new(\"483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8\"))","doc":"A commonly used base point `G` with coordinates `x` and `y`\nsatisfying `y^2 = x^3 + 7`.","summary":"

      A commonly used base point G with coordinates x and y satisfying y^2 = x^3 + 7.

      "},{"id":"N","name":"N","value":"Num.new(\"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141\")","doc":"The order `n` of `G` defines the finite size of the Secp256k1 field `E`.","summary":"

      The order n of G defines the finite size of the Secp256k1 field E.

      "},{"id":"P","name":"P","value":"Num.new(\"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f\")","doc":"The elliptic curve domain parameters over `F_p` associated with a\nKoblitz curve `Secp256k1` are specified by the sextuple\n`T = (p, a, b, G, n, h)` where the finite field `F_p` is defined by\nthe prime `p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1`.","summary":"

      The elliptic curve domain parameters over F_p associated with a Koblitz curve Secp256k1 are specified by the sextuple T = (p, a, b, G, n, h) where the finite field F_p is defined by the prime p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1.

      "},{"id":"VERSION","name":"VERSION","value":"\"0.5.0\"","doc":"The `VERSION` of the `Secp256k1` module.","summary":"

      The VERSION of the Secp256k1 module.

      "}],"doc":"Provides the `Secp256k1` module with the elliptic curve parameters\nused by the `Bitcoin`, `Ethereum`, and `Polkadot` blockchains. It's\nprimarily used to generate key-pairs as well as signing messages and\nrecoverying signatures.\n\nRef: [secg.org/sec2-v2.pdf](https://www.secg.org/sec2-v2.pdf)","summary":"

      Provides the Secp256k1 module with the elliptic curve parameters used by the Bitcoin, Ethereum, and Polkadot blockchains.

      ","types":[{"html_id":"secp256k1/Secp256k1/Context","path":"Secp256k1/Context.html","kind":"class","full_name":"Secp256k1::Context","name":"Context","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/context.cr","line_number":22,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a `Secp256k1` context to allow signing arbitrary data,\nrecovering public keys, and verifying signatures.\n\n```\nctx = Context.new\n# => #\n```","summary":"

      Provides a Secp256k1 context to allow signing arbitrary data, recovering public keys, and verifying signatures.

      ","instance_methods":[{"html_id":"sign(key:Key,hash:Num):Signature-instance-method","name":"sign","doc":"Signs a message hash or any other arbitrary data with a given keypair.\n\nParameters:\n* `key` (`Key`): the keypair containing a secret to sign the data.\n* `hash` (`Num`): the message or arbirtrary data hash.\n\nReturns a `Signature` proving the given key signed the message hash.\n\n```\nctx = Context.new\nkey = Key.new Num.new \"1f0c122d41ff536b19bfd83537c0dfc290e45cd3c375a43237c8b8fff7ac8af7\"\nhash = Util.sha256 \"Henlo, Wordl\"\nsig = ctx.sign key, hash\n# => #,\n# @s=#,\n# @v=#>\n```","summary":"

      Signs a message hash or any other arbitrary data with a given keypair.

      ","abstract":false,"args":[{"name":"key","external_name":"key","restriction":"Key"},{"name":"hash","external_name":"hash","restriction":"Num"}],"args_string":"(key : Key, hash : Num) : Signature","args_html":"(key : Key, hash : Num) : Signature","location":{"filename":"src/secp256k1/context.cr","line_number":50,"url":null},"def":{"name":"sign","args":[{"name":"key","external_name":"key","restriction":"Key"},{"name":"hash","external_name":"hash","restriction":"Num"}],"return_type":"Signature","visibility":"Public","body":"k = Util.deterministic_k(key.private_key, hash)\nhash = hash.to_big\npriv = key.private_key.to_big\npoint = Curve.mul(G, k)\nr = point.x.to_big % N.to_big\nk_inv = Curve.mod_inv(k, N)\ns = ((hash + (r * priv)) * k_inv.to_big) % N.to_big\nx_mag = point.x.to_big > N.to_big\ny_parity = (point.y.to_big % 2) == 0\nrec_id : Int8 = -1\nif (!y_parity) && x_mag\n rec_id = 3\nelse\n if y_parity && x_mag\n rec_id = 2\n else\n if (!y_parity) && (!x_mag)\n rec_id = 1\n else\n rec_id = 0\n end\n end\nend\nr = Num.new(r)\ns = Num.new(s)\nv = Num.new(BigInt.new(rec_id))\nSignature.new(r, s, v)\n"}},{"html_id":"verify(sig:Signature,hash:Num,publ:Point):Bool-instance-method","name":"verify","doc":"Verifies that a given signature for a given message hash matches\nthe provided public key.\n\nParameters:\n* `sig` (`Signature`): the signature to be verified.\n* `hash` (`Num`): the message or arbirtrary data hash.\n* `publ` (`Point`): the public key to match.\n\nReturns _true_ if the signature verifies.\n\n```\nctx = Context.new\nr = Num.new \"c4079db44240b7afe94985c69fc89602e33629fd9b8623d711c30ce6378b33df\"\ns = Num.new \"6842c1b63c94bdb8e4f5ae88fb65f7a98b77b197c8323004fb47ef57fab29053\"\nv = Num.new \"00\"\nsig = Signature.new r, s, v\nhash = Util.sha256 \"Henlo, Wordl\"\npubl = Point.new \"0416008a369439f1a8a75cf974860bed5b10180518d6b1dd3ac847f423fd375d6aa29474394f0cd79d2ea543507d069e97339284f01bdbfd27392daec0ec553816\"\nctx.verify sig, hash, publ\n# => true\n```","summary":"

      Verifies that a given signature for a given message hash matches the provided public key.

      ","abstract":false,"args":[{"name":"sig","external_name":"sig","restriction":"Signature"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"publ","external_name":"publ","restriction":"Point"}],"args_string":"(sig : Signature, hash : Num, publ : Point) : Bool","args_html":"(sig : Signature, hash : Num, publ : Point) : Bool","location":{"filename":"src/secp256k1/context.cr","line_number":97,"url":null},"def":{"name":"verify","args":[{"name":"sig","external_name":"sig","restriction":"Signature"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"publ","external_name":"publ","restriction":"Point"}],"return_type":"Bool","visibility":"Public","body":"s_inv = Curve.mod_inv(sig.s, N)\np0 = Curve.mul(G, (hash.to_big * s_inv.to_big) % N.to_big)\np1 = Curve.mul(publ, (sig.r.to_big * s_inv.to_big) % N.to_big)\np = Curve.add(p0, p1)\nsig.r.to_big === p.x.to_big\n"}}]},{"html_id":"secp256k1/Secp256k1/Curve","path":"Secp256k1/Curve.html","kind":"module","full_name":"Secp256k1::Curve","name":"Curve","abstract":false,"locations":[{"filename":"src/secp256k1/curve.cr","line_number":18,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"secp256k1/Secp256k1/Curve","kind":"module","full_name":"Secp256k1::Curve","name":"Curve"}],"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Implements 256-bit `Secp256k1` Koblitz elliptic curve operations.\n\nRef: [secg.org/sec2-v2.pdf](https://www.secg.org/sec2-v2.pdf)","summary":"

      Implements 256-bit Secp256k1 Koblitz elliptic curve operations.

      ","instance_methods":[{"html_id":"add(p:Point,q:Point,prime=P):Point-instance-method","name":"add","doc":"Computes the elliptic curve jive addition of point `p(x, y)` and `q(x, y)`.\nIt _draws_ a line between `p` and `q` which will intersect the\ncurve in the point `r` which will be mirrored over the `x`-axis.\n\nParamters:\n* `p` (`Num`): the point `p(x, y)` to be used in the jive addition.\n* `q` (`Num`): the point `q(x, y)` to be used in the jive addition.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Point` containing the result of the intersection.\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\nq = Point.new Num.new \"7e17f60baa7b8dc8581a55f7be1ea263c6a88452cf3f0a3f710651767654946c\"\nCurve.add p, q\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve jive addition of point p(x, y) and q(x, y).

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"q","external_name":"q","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(p : Point, q : Point, prime = P) : Point","args_html":"(p : Point, q : Point, prime = P) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":82,"url":null},"def":{"name":"add","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"q","external_name":"q","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Point","visibility":"Public","body":"if prime.is_a?(Num)\n prime = prime.to_big\nend\np_x = p.x.to_big\np_y = p.y.to_big\nq_x = q.x.to_big\nq_y = q.y.to_big\nx_delta = q_x - p_x\nx_inv = mod_inv(x_delta)\ny_delta = q_y - p_y\nm = (y_delta * x_inv.to_big) % prime\nx = (((m * m) - p_x) - q_x) % prime\ny = ((m * (p_x - x)) - p_y) % prime\nx = Num.new(x)\ny = Num.new(y)\nPoint.new(x, y)\n"}},{"html_id":"double(p:Point,prime=P):Point-instance-method","name":"double","doc":"Computes the elliptic curve juke point doubling of `p(x, y)`.\nThis is a special case of addition where both points are the same.\nIt _draws_ a tangent line at `p` which will intersect the curve\nat point `r` which will be mirrored over the `x`-axis.\n\nParamters:\n* `p` (`Point`): the point `p(x, y)` to be used in the juke doubling.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Point` as a result of the intersection.\n\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\nCurve.double p\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve juke point doubling of p(x, y).

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(p : Point, prime = P) : Point","args_html":"(p : Point, prime = P) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":123,"url":null},"def":{"name":"double","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Point","visibility":"Public","body":"if prime.is_a?(Num)\n prime = prime.to_big\nend\np_x = p.x.to_big\np_y = p.y.to_big\nlam_numer = (3 * p_x) * p_x\nlam_denom = 2 * p_y\nlam_inv = mod_inv(Num.new(lam_denom))\nlam = (lam_numer * lam_inv.to_big) % prime\nx = ((lam * lam) - (2 * p_x)) % prime\ny = ((lam * (p_x - x)) - p_y) % prime\nx = Num.new(x)\ny = Num.new(y)\nPoint.new(x, y)\n"}},{"html_id":"mod_inv(a:Num|BigInt,prime=P):Num-instance-method","name":"mod_inv","doc":"Computes the elliptic curve modular multiplicative inverse of `a`.\n\nParemeters:\n* `a` (`Num | BigInt`): the integer that we want the modular inverse of.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Num` containing the mod inverse.\n\n```\na = Num.new \"ea678c668356d16d8bf5c69f95c1055e39bd24174605f64846e27c3ae6a88d81\"\nCurve.mod_inv a\n# => #\n```","summary":"

      Computes the elliptic curve modular multiplicative inverse of a.

      ","abstract":false,"args":[{"name":"a","external_name":"a","restriction":"Num | BigInt"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(a : Num | BigInt, prime = P) : Num","args_html":"(a : Num | BigInt, prime = P) : Num","location":{"filename":"src/secp256k1/curve.cr","line_number":37,"url":null},"def":{"name":"mod_inv","args":[{"name":"a","external_name":"a","restriction":"Num | BigInt"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Num","visibility":"Public","body":"if a.is_a?(Num)\n a = a.to_big\nend\nif prime.is_a?(Num)\n prime = prime.to_big\nend\nm_low = 1\nm_high = 0\nv_low = a % prime\nv_high = prime\nwhile v_low > 1\n v_ratio = v_high // v_low\n m_low_r = m_low * v_ratio\n v_low_r = v_low * v_ratio\n m = m_high - m_low_r\n v = v_high - v_low_r\n m_high = m_low\n v_high = v_low\n m_low = m\n v_low = v\nend\nNum.new(m_low % prime)\n"}},{"html_id":"mul(p:Point,s:Num|BigInt):Point-instance-method","name":"mul","doc":"Computes the elliptic curve sequence multiplication of point `p(x, y)`\nand a skalar `s`; with `s` being a private key within the elliptic\ncurve field size of `N`.\n\nParamters:\n* `p` (`Point`): the point `p(x, y)` to be used in the sequencing.\n* `s` (`Num | BigInt`): a skalar, in most cases a private key.\n\nReturns a `Point` as a result of the multiplication.\n\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\ns = Num.new \"f51ad125548b7a283ebf15ab830a25c850d4d863078c48cc9993b79ee18ee11e\"\nCurve.mul p, s\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve sequence multiplication of point p(x, y) and a skalar s; with s being a private key within the elliptic curve field size of N.

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"s","external_name":"s","restriction":"Num | BigInt"}],"args_string":"(p : Point, s : Num | BigInt) : Point","args_html":"(p : Point, s : Num | BigInt) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":162,"url":null},"def":{"name":"mul","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"s","external_name":"s","restriction":"Num | BigInt"}],"return_type":"Point","visibility":"Public","body":"if s.is_a?(Num)\n s = s.to_big\nend\nif (s === 0) || s >= N.to_big\n raise(\"Invalid scalar: outside of Secp256k1 field dimension.\")\nend\ns_bin = s.to_s(2)\nq = p\ns_bin.each_char_with_index do |char, index|\n if index === 0\n next\n end\n q = double(q)\n if char === '1'\n q = add(q, p)\n end\nend\nq\n"}}]},{"html_id":"secp256k1/Secp256k1/Key","path":"Secp256k1/Key.html","kind":"class","full_name":"Secp256k1::Key","name":"Key","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/key.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a `Secp256k1` keypair containing a secret number (private key)\nand a public point on the elliptic curve (public key).\n\nProperties:\n* `private_key` (`Num`): the secret number representing the private key.\n* `public_key` (`Point`): the point on the elliptic curve representing the public key.","summary":"

      Provides a Secp256k1 keypair containing a secret number (private key) and a public point on the elliptic curve (public key).

      ","constructors":[{"html_id":"new(priv:Num)-class-method","name":"new","doc":"Creates a public-private keypair from an existing private key.\n\nParameters:\n* `priv` (`Num`): the private key for the keypair.\n\n```\npriv = Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\nKey.new priv\n# => #,\n# @public_key=#,\n# @y=#>>\n```","summary":"

      Creates a public-private keypair from an existing private key.

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"args_string":"(priv : Num)","args_html":"(priv : Num)","location":{"filename":"src/secp256k1/key.cr","line_number":74,"url":null},"def":{"name":"new","args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(priv)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new-class-method","name":"new","doc":"Creates a new, random `Secp256k1` keypair.\n\n```\nKey.new\n# => #,\n# @public_key=#,\n# @y=#>>\n```","summary":"

      Creates a new, random Secp256k1 keypair.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":46,"url":null},"def":{"name":"new","visibility":"Public","body":"_ = allocate\n_.initialize\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"private_bytes:Bytes-instance-method","name":"private_bytes","doc":"Returns the private key as binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_bytes\n# => Bytes[60, 207, 132, 130, 12, 32, 213, 232, 197, 54, 186, 132, 197, 43, 164, 16, 55, 91, 41, 177, 129, 43, 95, 126, 114, 36, 69, 201, 105, 160, 251, 48]\n```","summary":"

      Returns the private key as binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":95,"url":null},"def":{"name":"private_bytes","return_type":"Bytes","visibility":"Public","body":"@private_key.to_zpadded_bytes"}},{"html_id":"private_hex:String-instance-method","name":"private_hex","doc":"Returns the private key as hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_hex\n# => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\n```","summary":"

      Returns the private key as hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":85,"url":null},"def":{"name":"private_hex","return_type":"String","visibility":"Public","body":"@private_key.to_zpadded_hex"}},{"html_id":"private_key:Num-instance-method","name":"private_key","doc":"The secret number representing the private key.","summary":"

      The secret number representing the private key.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":23,"url":null},"def":{"name":"private_key","return_type":"Num","visibility":"Public","body":"@private_key"}},{"html_id":"public_bytes:Bytes-instance-method","name":"public_bytes","doc":"Returns the public key as uncompressed, binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes\n# => Bytes[4, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162, 129, 54, 61, 41, 142, 74, 64, 235, 203, 19, 241, 175, 168, 90, 11, 148, 185, 103, 242, 67, 238, 89, 165, 144, 16, 203, 93, 234, 240, 215, 182, 108]\n```","summary":"

      Returns the public key as uncompressed, binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":125,"url":null},"def":{"name":"public_bytes","return_type":"Bytes","visibility":"Public","body":"(Num.new(@public_key.uncompressed)).to_bytes"}},{"html_id":"public_bytes_compressed:Bytes-instance-method","name":"public_bytes_compressed","doc":"Returns the public key as compressed, binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes_compressed\n# => Bytes[2, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162]\n```","summary":"

      Returns the public key as compressed, binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":135,"url":null},"def":{"name":"public_bytes_compressed","return_type":"Bytes","visibility":"Public","body":"(Num.new(@public_key.compressed)).to_bytes"}},{"html_id":"public_hex:String-instance-method","name":"public_hex","doc":"Returns the public key as uncompressed, hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex\n# => \"04cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba281363d298e4a40ebcb13f1afa85a0b94b967f243ee59a59010cb5deaf0d7b66c\"\n```","summary":"

      Returns the public key as uncompressed, hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":105,"url":null},"def":{"name":"public_hex","return_type":"String","visibility":"Public","body":"@public_key.uncompressed"}},{"html_id":"public_hex_compressed:String-instance-method","name":"public_hex_compressed","doc":"Returns the public key as compressed, hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex_compressed\n# => \"02cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba2\"\n```","summary":"

      Returns the public key as compressed, hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":115,"url":null},"def":{"name":"public_hex_compressed","return_type":"String","visibility":"Public","body":"@public_key.compressed"}},{"html_id":"public_key:Point-instance-method","name":"public_key","doc":"The point on the elliptic curve representing the public key.","summary":"

      The point on the elliptic curve representing the public key.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":25,"url":null},"def":{"name":"public_key","return_type":"Point","visibility":"Public","body":"@public_key"}}]},{"html_id":"secp256k1/Secp256k1/Num","path":"Secp256k1/Num.html","kind":"class","full_name":"Secp256k1::Num","name":"Num","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/num.cr","line_number":25,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a class to conveniently handle big numbers on the elliptic\ncurve. It allows to easily access decimal, hexadecimal, and binary\nrepresentations of the numeric. In addition, it implements some\nutilities such as zpadding or asserting hexadecimal strings. It's suited\nto temporarily handle unencrypted private keys.\n\nProperties:\n* `hex` (`String`): the hexadecimal string representation of the number.\n* `dec` (`BigInt`): the decimal big-integer representation of the number.\n* `bin` (`Bytes`): the binary bytes-slice represenation of the number.","summary":"

      Provides a class to conveniently handle big numbers on the elliptic curve.

      ","constructors":[{"html_id":"new(hex:String)-class-method","name":"new","doc":"Creates a number from a hexadecimal string literal.\n\nParameters:\n* `hex` (`String`): a hexadecimal string representating the number.\n\n```\nNum.new \"568a0f505bde902db4a6afd207c794c7845fe7715da5999bb276d453c702a46d\"\n# => #\n```","summary":"

      Creates a number from a hexadecimal string literal.

      ","abstract":false,"args":[{"name":"hex","external_name":"hex","restriction":"String"}],"args_string":"(hex : String)","args_html":"(hex : String)","location":{"filename":"src/secp256k1/num.cr","line_number":67,"url":null},"def":{"name":"new","args":[{"name":"hex","external_name":"hex","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(hex)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(num:BigInt)-class-method","name":"new","doc":"Creates a number from a big integer numeric.\n\nParameters:\n* `dec` (`BigInt`): the decimal big-integer representating the number.\n\n```\nNum.new BigInt.new \"39142835565766237398843902819171565157710677457569850027793715608438337348717\"\n# => #\n```","summary":"

      Creates a number from a big integer numeric.

      ","abstract":false,"args":[{"name":"num","external_name":"num","restriction":"BigInt"}],"args_string":"(num : BigInt)","args_html":"(num : BigInt)","location":{"filename":"src/secp256k1/num.cr","line_number":87,"url":null},"def":{"name":"new","args":[{"name":"num","external_name":"num","restriction":"BigInt"}],"visibility":"Public","body":"_ = allocate\n_.initialize(num)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(bin:Slice(UInt8))-class-method","name":"new","doc":"Creates a number from a binary bytes slice.\n\nParameters:\n* `bin` (`Bytes`): the binary bytes-slice represenating the number.\n\n```\nNum.new Bytes[86, 138, 15, 80, 91, 222, 144, 45, 180, 166, 175, 210, 7, 199, 148, 199, 132, 95, 231, 113, 93, 165, 153, 155, 178, 118, 212, 83, 199, 2, 164, 109]\n# => #\n```","summary":"

      Creates a number from a binary bytes slice.

      ","abstract":false,"args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"args_string":"(bin : Slice(UInt8))","args_html":"(bin : Slice(UInt8))","location":{"filename":"src/secp256k1/num.cr","line_number":107,"url":null},"def":{"name":"new","args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"visibility":"Public","body":"_ = allocate\n_.initialize(bin)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new-class-method","name":"new","doc":"Creates a random number using `Random::Secure` that can be used as\na secret (private key).\n\n```\nNum.new\n# => #\n```","summary":"

      Creates a random number using Random::Secure that can be used as a secret (private key).

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":43,"url":null},"def":{"name":"new","visibility":"Public","body":"_ = allocate\n_.initialize\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"bin:Slice(UInt8)-instance-method","name":"bin","doc":"The binary bytes-slice represenation of the number.","summary":"

      The binary bytes-slice represenation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":31,"url":null},"def":{"name":"bin","return_type":"Slice(UInt8)","visibility":"Public","body":"@bin"}},{"html_id":"dec:BigInt-instance-method","name":"dec","doc":"The decimal big-integer representation of the number.","summary":"

      The decimal big-integer representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":29,"url":null},"def":{"name":"dec","return_type":"BigInt","visibility":"Public","body":"@dec"}},{"html_id":"hex:String-instance-method","name":"hex","doc":"The hexadecimal string representation of the number.","summary":"

      The hexadecimal string representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":27,"url":null},"def":{"name":"hex","return_type":"String","visibility":"Public","body":"@hex"}},{"html_id":"to_big:BigInt-instance-method","name":"to_big","doc":"Returns a big-integer representation of the number.\n\n```\nNum.new(Bytes[137]).to_big\n# => 137\n```","summary":"

      Returns a big-integer representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":156,"url":null},"def":{"name":"to_big","return_type":"BigInt","visibility":"Public","body":"@dec"}},{"html_id":"to_bytes:Bytes-instance-method","name":"to_bytes","doc":"Returns a binary byte-slice representation of the number.\n\n```\nNum.new(\"0x89\").to_bytes\n# => Bytes[137]\n```","summary":"

      Returns a binary byte-slice representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":166,"url":null},"def":{"name":"to_bytes","return_type":"Bytes","visibility":"Public","body":"@bin"}},{"html_id":"to_hex:String-instance-method","name":"to_hex","doc":"Returns an unprefixed hexadecimal string representation.\n\n```\nNum.new(Bytes[137]).to_hex\n# => \"89\"\n```","summary":"

      Returns an unprefixed hexadecimal string representation.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":119,"url":null},"def":{"name":"to_hex","return_type":"String","visibility":"Public","body":"@hex"}},{"html_id":"to_prefixed_hex:String-instance-method","name":"to_prefixed_hex","doc":"Returns an `0x`-prefixed hexadecimal string representation.\n\n```\nNum.new(Bytes[137]).to_prefixed_hex\n# => \"0x89\"\n```","summary":"

      Returns an 0x-prefixed hexadecimal string representation.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":129,"url":null},"def":{"name":"to_prefixed_hex","return_type":"String","visibility":"Public","body":"\"0x#{@hex}\""}},{"html_id":"to_zpadded_bytes(length=32):Bytes-instance-method","name":"to_zpadded_bytes","doc":"Returns a z-padded byte-slice binary representation.\n\nParameters:\n* `length` (`Int`): the byte-size of the final z-padded slice (default `32`).\n\n```\nNum.new(Bytes[137]).to_zpadded_bytes\n# => Bytes[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137]\n```","summary":"

      Returns a z-padded byte-slice binary representation.

      ","abstract":false,"args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"args_string":"(length = 32) : Bytes","args_html":"(length = 32) : Bytes","location":{"filename":"src/secp256k1/num.cr","line_number":179,"url":null},"def":{"name":"to_zpadded_bytes","args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"return_type":"Bytes","visibility":"Public","body":"zpadded_bytes = @bin\nwhile zpadded_bytes.size < length\n zpadded_bytes = Util.concat_bytes(Bytes[0], zpadded_bytes)\nend\nzpadded_bytes\n"}},{"html_id":"to_zpadded_hex(length=32):String-instance-method","name":"to_zpadded_hex","doc":"Returns a z-padded hexadecimal string representation.\n\nParameters:\n* `length` (`Int`): the byte-size of the final z-padded hex-string (default `32`).\n\n```\nNum.new(Bytes[137]).to_zpadded_hex\n# => \"0000000000000000000000000000000000000000000000000000000000000089\"\n```","summary":"

      Returns a z-padded hexadecimal string representation.

      ","abstract":false,"args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"args_string":"(length = 32) : String","args_html":"(length = 32) : String","location":{"filename":"src/secp256k1/num.cr","line_number":142,"url":null},"def":{"name":"to_zpadded_hex","args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"return_type":"String","visibility":"Public","body":"zpadded_hex = @hex\nwhile zpadded_hex.size < (length * 2)\n zpadded_hex = \"0#{zpadded_hex}\"\nend\nzpadded_hex\n"}}]},{"html_id":"secp256k1/Secp256k1/Point","path":"Secp256k1/Point.html","kind":"class","full_name":"Secp256k1::Point","name":"Point","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/point.cr","line_number":30,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a point in the two-dimensional space of any elliptic curve.\nIn most cases, such a point on a given curve represents a public key.\nHowever, for keypairs, a `Key` type shall be used!\n\nProperties:\n* `x` (`Num`): the position on the x-axis.\n* `y` (`Num`): the position on the y-axis.","summary":"

      Provides a point in the two-dimensional space of any elliptic curve.

      ","constructors":[{"html_id":"new(x:Num,y:Num)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing the x- and y-coordinates (public key).\n\nParameters:\n* `x` (`Num`): the position on the x-axis.\n* `y` (`Num`): the position on the y-axis.\n\n```\nx = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ny = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nPoint.new x, y\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing the x- and y-coordinates (public key).

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Num"},{"name":"y","external_name":"y","restriction":"Num"}],"args_string":"(x : Num, y : Num)","args_html":"(x : Num, y : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":58,"url":null},"def":{"name":"new","args":[{"name":"x","external_name":"x","restriction":"Num"},{"name":"y","external_name":"y","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(x, y)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(priv:Num)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing a random number (private key). Note, that the\nprivate key will be consumed by this constructor and should only be used\nto retrieve a public key. To manage keypairs, use the `Key` type instead.\n\nParameters:\n* `priv` (`Num`): the random number giving access to the point.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new priv\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing a random number (private key).

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"args_string":"(priv : Num)","args_html":"(priv : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":84,"url":null},"def":{"name":"new","args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(priv)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(pub:String)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing a compressed or uncompressed public key.\n\nParameters:\n* `pub` (`String`): the public key string (compressed or uncompressed).\n\n```\npub = \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\"\nPoint.new pub\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing a compressed or uncompressed public key.

      ","abstract":false,"args":[{"name":"pub","external_name":"pub","restriction":"String"}],"args_string":"(pub : String)","args_html":"(pub : String)","location":{"filename":"src/secp256k1/point.cr","line_number":109,"url":null},"def":{"name":"new","args":[{"name":"pub","external_name":"pub","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(pub)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"compressed:String-instance-method","name":"compressed","doc":"Returns a prefixed, compressed public key string for the given point\nin the format `prefix|x|y`.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new(priv).compressed\n# => \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\"\n```","summary":"

      Returns a prefixed, compressed public key string for the given point in the format prefix|x|y.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":161,"url":null},"def":{"name":"compressed","return_type":"String","visibility":"Public","body":"prefix = 2 + (@y.to_big % 2)\nprefix = \"0#{prefix}\"\n\"#{prefix}#{@x.to_zpadded_hex}\"\n"}},{"html_id":"uncompressed:String-instance-method","name":"uncompressed","doc":"Returns a prefixed, uncompressed public key string for the given point\nin the format `04|x|y`.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new(priv).uncompressed\n# => \"04aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f21f4c49cfe90da39c254a51b8ee8afcdd8c02dd566f13582c23e104c7ed5936b\"\n```","summary":"

      Returns a prefixed, uncompressed public key string for the given point in the format 04|x|y.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":148,"url":null},"def":{"name":"uncompressed","return_type":"String","visibility":"Public","body":"prefix = \"04\"\n\"#{prefix}#{@x.to_zpadded_hex}#{@y.to_zpadded_hex}\"\n"}},{"html_id":"x:Num-instance-method","name":"x","doc":"The position on the x-axis.","summary":"

      The position on the x-axis.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":32,"url":null},"def":{"name":"x","return_type":"Num","visibility":"Public","body":"@x"}},{"html_id":"x=(x:Num)-instance-method","name":"x=","doc":"The position on the x-axis.","summary":"

      The position on the x-axis.

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Num"}],"args_string":"(x : Num)","args_html":"(x : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":32,"url":null},"def":{"name":"x=","args":[{"name":"x","external_name":"x","restriction":"Num"}],"visibility":"Public","body":"@x = x"}},{"html_id":"y:Num-instance-method","name":"y","doc":"The position on the y-axis.","summary":"

      The position on the y-axis.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":35,"url":null},"def":{"name":"y","return_type":"Num","visibility":"Public","body":"@y"}},{"html_id":"y=(y:Num)-instance-method","name":"y=","doc":"The position on the y-axis.","summary":"

      The position on the y-axis.

      ","abstract":false,"args":[{"name":"y","external_name":"y","restriction":"Num"}],"args_string":"(y : Num)","args_html":"(y : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":35,"url":null},"def":{"name":"y=","args":[{"name":"y","external_name":"y","restriction":"Num"}],"visibility":"Public","body":"@y = y"}}]},{"html_id":"secp256k1/Secp256k1/Signature","path":"Secp256k1/Signature.html","kind":"class","full_name":"Secp256k1::Signature","name":"Signature","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/signature.cr","line_number":22,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides an ECDSA Signature containing the random point `r`, the\nsignature proof `s`, and the recovery id or `v` value.\n\nProperties:\n* `r` (`Num`): the `x` coordinate of a random point `R` on the curve.\n* `s` (`Num`): the signature proof of a message.\n* `v` (`Num`): the recovery id or `v` value.","summary":"

      Provides an ECDSA Signature containing the random point #r, the signature proof #s, and the recovery id or #v value.

      ","constructors":[{"html_id":"new(r:Num,s:Num,v:Num)-class-method","name":"new","doc":"Provides an ECDSA Signature containing the random point `r`, the\nsignature proof `s`, and the recovery id or `v` value.\n\nParameters:\n* `r` (`Num`): the `x` coordinate of a random point `R` on the curve.\n* `s` (`Num`): the signature proof of a message.\n* `v` (`Num`): the recovery id or `v` value.\n\n```\nr = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ns = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nv = Num.new \"00\"\nSignature.new r, s, v\n# => #,\n# @s=#,\n# @v=#>\n```","summary":"

      Provides an ECDSA Signature containing the random point #r, the signature proof #s, and the recovery id or #v value.

      ","abstract":false,"args":[{"name":"r","external_name":"r","restriction":"Num"},{"name":"s","external_name":"s","restriction":"Num"},{"name":"v","external_name":"v","restriction":"Num"}],"args_string":"(r : Num, s : Num, v : Num)","args_html":"(r : Num, s : Num, v : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":59,"url":null},"def":{"name":"new","args":[{"name":"r","external_name":"r","restriction":"Num"},{"name":"s","external_name":"s","restriction":"Num"},{"name":"v","external_name":"v","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(r, s, v)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"compact:String-instance-method","name":"compact","doc":"Returns a compact `String` containing the concatenated signature\nin the form `r|s|v`.\n\n```\nr = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ns = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nv = Num.new \"00\"\nSignature.new(r, s, v).compact\n# => \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae000\"\n```","summary":"

      Returns a compact String containing the concatenated signature in the form r|s|v.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":75,"url":null},"def":{"name":"compact","return_type":"String","visibility":"Public","body":"\"#{r.to_zpadded_hex}#{s.to_zpadded_hex}#{v.to_hex}\""}},{"html_id":"r:Num-instance-method","name":"r","doc":"The `x` coordinate of a random point `R` on the curve.","summary":"

      The x coordinate of a random point R on the curve.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":24,"url":null},"def":{"name":"r","return_type":"Num","visibility":"Public","body":"@r"}},{"html_id":"s:Num-instance-method","name":"s","doc":"The signature proof of a message.","summary":"

      The signature proof of a message.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":27,"url":null},"def":{"name":"s","return_type":"Num","visibility":"Public","body":"@s"}},{"html_id":"v:Num-instance-method","name":"v","doc":"The recovery id or `v` value.","summary":"

      The recovery id or #v value.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":30,"url":null},"def":{"name":"v","return_type":"Num","visibility":"Public","body":"@v"}}]},{"html_id":"secp256k1/Secp256k1/Util","path":"Secp256k1/Util.html","kind":"module","full_name":"Secp256k1::Util","name":"Util","abstract":false,"locations":[{"filename":"src/secp256k1/util.cr","line_number":17,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"secp256k1/Secp256k1/Util","kind":"module","full_name":"Secp256k1::Util","name":"Util"}],"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a collection of utilities for convenience, e.g., to bind\nrelevant hashing algorithms, or to concatenate byte slices.","summary":"

      Provides a collection of utilities for convenience, e.g., to bind relevant hashing algorithms, or to concatenate byte slices.

      ","instance_methods":[{"html_id":"concat_bytes(x:Bytes,y:Bytes):Bytes-instance-method","name":"concat_bytes","doc":"Concatenates two byte slices in the order provided, i.e., `x|y`.\n\nParameters:\n* `x` (`Bytes`): a byte slice.\n* `y` (`Bytes`): another byte slice.\n\nReturns a concatenated `Bytes` slice.\n\n```\nUtil.concat_bytes Bytes[1, 2, 3], Bytes[9, 8, 7]\n# => Bytes[1, 2, 3, 9, 8, 7]\n```","summary":"

      Concatenates two byte slices in the order provided, i.e., x|y.

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Bytes"},{"name":"y","external_name":"y","restriction":"Bytes"}],"args_string":"(x : Bytes, y : Bytes) : Bytes","args_html":"(x : Bytes, y : Bytes) : Bytes","location":{"filename":"src/secp256k1/util.cr","line_number":177,"url":null},"def":{"name":"concat_bytes","args":[{"name":"x","external_name":"x","restriction":"Bytes"},{"name":"y","external_name":"y","restriction":"Bytes"}],"return_type":"Bytes","visibility":"Public","body":"z = IO::Memory.new(x.bytesize + y.bytesize)\nx.each do |b|\n z.write_bytes(UInt8.new(b))\nend\ny.each do |b|\n z.write_bytes(UInt8.new(b))\nend\nreturn z.to_slice\n"}},{"html_id":"deterministic_k(priv:Num,hash:Num,order=N):Num-instance-method","name":"deterministic_k","doc":"Provides a deterministic secret based on private key and message hash\nas defined in RFC-6979.\n\nRef: [datatracker.ietf.org/doc/html/rfc6979](https://datatracker.ietf.org/doc/html/rfc6979)\n\nParameters:\n* `priv` (`Num`): the private key or secret number.\n* `hash` (`Num`): the message hash or arbirtrary data hash.\n* `order` (`Num`): the order of the curve over `G` (default `N`).\n\nReturns a deterministically random number of type `Num`.\n\n```\npriv = Num.new \"3b74fcc0b0c419a00d2d9e88b15fbd99e03920138da22e2a00c327b88d24cf45\"\nhash = Util.sha256 \"Henlo, Wordl\"\nUtil.deterministic_k(priv, hash)\n# => #\n```","summary":"

      Provides a deterministic secret based on private key and message hash as defined in RFC-6979.

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"order","default_value":"N","external_name":"order","restriction":""}],"args_string":"(priv : Num, hash : Num, order = N) : Num","args_html":"(priv : Num, hash : Num, order = N) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":135,"url":null},"def":{"name":"deterministic_k","args":[{"name":"priv","external_name":"priv","restriction":"Num"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"order","default_value":"N","external_name":"order","restriction":""}],"return_type":"Num","visibility":"Public","body":"order_size = order.hex.size // 2\nv = Num.new(Bytes.new(order_size, 1))\nk = Num.new(Bytes.new(order_size, 0))\nconcat = Util.concat_bytes(v.bin, Bytes[0])\nconcat = Util.concat_bytes(concat, priv.bin)\nconcat = Util.concat_bytes(concat, hash.bin)\nk = OpenSSL::HMAC.digest(:sha256, k.bin, concat)\nv = OpenSSL::HMAC.digest(:sha256, k, v.bin)\nconcat = Util.concat_bytes(v, Bytes[0])\nconcat = Util.concat_bytes(concat, priv.bin)\nconcat = Util.concat_bytes(concat, hash.bin)\nk = OpenSSL::HMAC.digest(:sha256, k, concat)\nv = OpenSSL::HMAC.digest(:sha256, k, v)\nwhile true\n t = IO::Memory.new.to_slice\n while t.size < order_size\n v = OpenSSL::HMAC.digest(:sha256, k, v)\n t = Util.concat_bytes(t, v)\n end\n secret = Num.new(t)\n if secret.dec < order.dec && secret.dec > 0\n return secret\n end\n increment = Util.concat_bytes(v, Bytes[0])\n k = OpenSSL::HMAC.digest(:sha256, k, increment)\n v = OpenSSL::HMAC.digest(:sha256, k, v)\nend\n"}},{"html_id":"keccak(data:Num|Bytes|String,entropy=256):Num-instance-method","name":"keccak","doc":"Operating a Keccak hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed.\n* `entropy` (`Int32`): the required entropy (default `256`).\n\nReturns a `Num` representing the Keccak hash.\n\n```\nUtil.keccak(Num.new \"0xdeadbeef\").hex\n# => \"d4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1\"\n\nUtil.keccak(\"0xdeadbeef\").hex\n# => \"4f440a001006a49f24a7de53c04eca3f79aef851ac58e460c9630d044277c8b0\"\n```","summary":"

      Operating a Keccak hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"args_string":"(data : Num | Bytes | String, entropy = 256) : Num","args_html":"(data : Num | Bytes | String, entropy = 256) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":35,"url":null},"def":{"name":"keccak","args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"return_type":"Num","visibility":"Public","body":"keccak = Digest::Keccak3.new(entropy)\nif data.is_a?(Num)\n return Num.new((keccak.update(data.to_bytes)).hexdigest)\nelse\n return Num.new((keccak.update(data)).hexdigest)\nend\n"}},{"html_id":"ripemd160(data:Num|Bytes|String):Num-instance-method","name":"ripemd160","doc":"Operating a RIPEMD-160 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed.\n\nReturns a `Num` representing the RIPEMD hash.\n\n```\nUtil.ripemd160(Num.new \"0xdeadbeef\").hex\n# => \"226821c2f5423e11fe9af68bd285c249db2e4b5a\"\n\nUtil.ripemd160(\"0xdeadbeef\").hex\n# => \"4caf817f14e84b564e47afd19966e5d123ee0183\"\n```","summary":"

      Operating a RIPEMD-160 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"}],"args_string":"(data : Num | Bytes | String) : Num","args_html":"(data : Num | Bytes | String) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":105,"url":null},"def":{"name":"ripemd160","args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"}],"return_type":"Num","visibility":"Public","body":"ripemd = OpenSSL::Digest.new(\"RIPEMD160\")\nif data.is_a?(Num)\n return Num.new((ripemd.update(data.to_bytes)).final.hexstring)\nelse\n return Num.new((ripemd.update(data)).final.hexstring)\nend\n"}},{"html_id":"sha256(data:Num|Bytes|String):Num-instance-method","name":"sha256","doc":"Operating a SHA2-256 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed.\n\nReturns a `Num` representing the SHA2 hash.\n\n```\nUtil.sha256(Num.new \"0xdeadbeef\").hex\n# => \"5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953\"\n\nUtil.sha256(\"0xdeadbeef\").hex\n# => \"4142710b9b4caaeb000b8e5de271bbebac7f509aab2f5e61d1ed1958bfe6d583\"\n```","summary":"

      Operating a SHA2-256 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"}],"args_string":"(data : Num | Bytes | String) : Num","args_html":"(data : Num | Bytes | String) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":82,"url":null},"def":{"name":"sha256","args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"}],"return_type":"Num","visibility":"Public","body":"sha2 = OpenSSL::Digest.new(\"SHA256\")\nif data.is_a?(Num)\n return Num.new((sha2.update(data.to_bytes)).final.hexstring)\nelse\n return Num.new((sha2.update(data)).final.hexstring)\nend\n"}},{"html_id":"sha3(data:Num|Bytes|String,entropy=256):Num-instance-method","name":"sha3","doc":"Operating a SHA3 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed.\n* `entropy` (`Int32`): the required entropy (default `256`).\n\nReturns a `Num` representing the SHA3 hash.\n\n```\nUtil.sha3(Num.new \"0xdeadbeef\").hex\n# => \"352b82608dad6c7ac3dd665bc2666e5d97803cb13f23a1109e2105e93f42c448\"\n\nUtil.sha3(\"0xdeadbeef\").hex\n# => \"c12811e13ed75afe3e0945ef34e8a25b9d321a46e131c6463731de25a21b39eb\"\n```","summary":"

      Operating a SHA3 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"args_string":"(data : Num | Bytes | String, entropy = 256) : Num","args_html":"(data : Num | Bytes | String, entropy = 256) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":59,"url":null},"def":{"name":"sha3","args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"return_type":"Num","visibility":"Public","body":"sha3 = Digest::SHA3.new(entropy)\nif data.is_a?(Num)\n return Num.new((sha3.update(data.to_bytes)).hexdigest)\nelse\n return Num.new((sha3.update(data)).hexdigest)\nend\n"}}]}]}]}} \ No newline at end of file diff --git a/docs/search-index.js b/docs/search-index.js index 9766f15..dd1db58 100644 --- a/docs/search-index.js +++ b/docs/search-index.js @@ -1 +1 @@ -crystal_doc_search_index_callback({"repository_name":"secp256k1","body":"# secp256k1.cr\n\n[![Build Status](https://img.shields.io/github/workflow/status/q9f/secp256k1.cr/Nightly)](https://github.com/q9f/secp256k1.cr/actions)\n[![Code Coverage](https://codecov.io/gh/q9f/secp256k1.cr/branch/main/graph/badge.svg?token=ngxRs9HdJA)](https://codecov.io/gh/q9f/secp256k1.cr)\n[![Documentation](https://img.shields.io/badge/docs-html-black)](https://q9f.github.io/secp256k1.cr/)\n[![Release](https://img.shields.io/github/v/release/q9f/secp256k1.cr?include_prereleases&color=black)](https://github.com/q9f/secp256k1.cr/releases/latest)\n[![Language](https://img.shields.io/github/languages/top/q9f/secp256k1.cr?color=black)](https://github.com/q9f/secp256k1.cr/search?l=crystal)\n[![License](https://img.shields.io/github/license/q9f/secp256k1.cr.svg?color=black)](LICENSE)\n\nA library implementing the `Secp256k1` elliptic curve natively in pure Crystal.\n`Secp256k1` is the elliptic curve used in the public-private-key cryptography required by `Bitcoin`, `Ethereum`, and `Polkadot`.\n\nThis library allows for:\n* providing a `Secp256k1` cryptographic context, see `Secp256k1::Context`\n* managing `Secp256k1` signatures and verification, see `Secp256k1::Signature`\n* managing private-public keypairs, see `Secp256k1::Key`\n* generating public keys, see `Secp256k1::Point`\n* generating private keys, see `Secp256k1::Num`\n\n# Installation\n\nAdd the `Secp256k1` library to your `shard.yml`\n\n```yaml\ndependencies:\n secp256k1:\n github: q9f/secp256k1.cr\n version: \"~> 0.5\"\n```\n\n# Usage\n\nImport and expose the `Secp256k1` module.\n\n```crystal\nrequire \"secp256k1\"\n```\n\nThis library exposes the following modules and classes (in logical order):\n\n* `Secp256k1`: necessary constants and data structures, including:\n - `Secp256k1::Num`: for managing big numerics (private keys)\n - `Secp256k1::Point`: for handling of elliptic curve points (public keys)\n - `Secp256k1::Key`: for managing private-public keypairs (accounts)\n - `Secp256k1::Signature`: for handling ECDSA signatures (r, s, v)\n* `Secp256k1::Context`: providing a cryptographic context for signing and verification\n* `Secp256k1::Curve`: the entire core mathematics behind the elliptic curve cryptography\n* `Secp256k1::Util`: binding of various hashing algorithms for convenience\n\nBasic usage:\n\n```crystal\n# generates a new, random keypair\nkey = Secp256k1::Key.new\n# => #,\n# @public_key=#,\n# @y=#>>\n\n# gets the private key\nkey.private_hex\n# => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\n\n# gets the compressed public key with prefix\nkey.public_hex_compressed\n# => \"02cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba2\"\n```\n\nSignature generation and verification:\n\n```crystal\n# sign a message with a private key\nctx = Secp256k1::Context.new\npriv = Secp256k1::Num.new \"1f0c122d41ff536b19bfd83537c0dfc290e45cd3c375a43237c8b8fff7ac8af7\"\nkey = Secp256k1::Key.new priv\nhash = Secp256k1::Util.sha256 \"Henlo, Wordl\"\nsig = ctx.sign key, hash\n# => #,\n# @s=#,\n# @v=#>\n\n# verify a signature with a public key\nr = Secp256k1::Num.new \"c4079db44240b7afe94985c69fc89602e33629fd9b8623d711c30ce6378b33df\"\ns = Secp256k1::Num.new \"6842c1b63c94bdb8e4f5ae88fb65f7a98b77b197c8323004fb47ef57fab29053\"\nv = Secp256k1::Num.new \"00\"\nsig = Secp256k1::Signature.new r, s, v\nhash = Secp256k1::Util.sha256 \"Henlo, Wordl\"\npubl = Secp256k1::Point.new \"0416008a369439f1a8a75cf974860bed5b10180518d6b1dd3ac847f423fd375d6aa29474394f0cd79d2ea543507d069e97339284f01bdbfd27392daec0ec553816\"\nctx.verify sig, hash, publ\n# => true\n```\n\n# Documentation\n\nThe full library documentation can be found here: [q9f.github.io/secp256k1.cr](https://q9f.github.io/secp256k1.cr/)\n\nGenerate a local copy with:\n\n```shell\ncrystal docs\n```\n\n# Testing\n\nThe library is entirely specified through tests in `./spec`; run:\n\n```shell\ncrystal spec --verbose\n```\n\n# Understand\n\nPrivate keys are just scalars (`Secp256k1::Num`) and public keys are points (`Secp256k1::Point`) with `x` and `y` coordinates.\n\nBitcoin public keys can be uncompressed `p|x|y` or compressed `p|x`. both come with a prefix `p` which is useless for uncompressed keys but necessary for compressed keys to recover the `y` coordinate on the `Secp256k1` elliptic curve field.\n\nEthereum public keys are uncompressed `x|y` without any prefix. The last 20 bytes slice of the `y` coordinate is actually used as address without any checksum. A checksum was later added in EIP-55 using a `keccak256` hash and indicating character capitalization.\n\nNeither Bitcoin nor Ethereum allow for recovering public keys from an address unless there exists a transaction with a valid signature on the blockchain.\n\n# Known issues\n\n_Note: this library should not be used in production without proper auditing. It should be considered slow and insecure._\n\n* This library is not constant time and might be subject to side-channel attacks. ([#4](https://github.com/q9f/secp256k1.cr/issues/4))\n* This library does unnecessary big-integer math and should someday rather correctly implement the `Secp256k1` prime field ([#5](https://github.com/q9f/secp256k1.cr/issues/5))\n* This library is slow in recovering signatures. Future versions should respect the recovery ID to quickly identify the correct public key from a signature.\n\nFound any other issue? Report it: [github.com/q9f/secp256k1.cr/issues](https://github.com/q9f/secp256k1.cr/issues)\n\n# Contribute\n\nCreate a pull request, and make sure tests and linter pass.\n\nThis pure crystal implementation is based on the python implementation [wobine/blackboard101](https://github.com/wobine/blackboard101) which is also used as reference to write tests against. It's a complete rewrite of the abandoned [packetzero/bitcoinutils](https://github.com/packetzero/bitcoinutils) for educational purposes.\n\nHonerable mention for the [bitcoin wiki](https://en.bitcoin.it/wiki/Main_Page) and the [ethereum stackexchange](https://ethereum.stackexchange.com/) for providing so many in-depth resources that supported this project in reimplementing everything.\n\nLicense: Apache License v2.0\n\nContributors: [**@q9f**](https://github.com/q9f/), [@cserb](https://github.com/cserb), [MrSorcus](https://github.com/MrSorcus)\n","program":{"html_id":"secp256k1/toplevel","path":"toplevel.html","kind":"module","full_name":"Top Level Namespace","name":"Top Level Namespace","abstract":false,"locations":[],"repository_name":"secp256k1","program":true,"enum":false,"alias":false,"const":false,"types":[{"html_id":"secp256k1/Secp256k1","path":"Secp256k1.html","kind":"module","full_name":"Secp256k1","name":"Secp256k1","abstract":false,"locations":[{"filename":"src/secp256k1.cr","line_number":35,"url":null},{"filename":"src/secp256k1/context.cr","line_number":22,"url":null},{"filename":"src/secp256k1/version.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"G","name":"G","value":"Point.new(Num.new(\"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\"), Num.new(\"483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8\"))","doc":"A commonly used base point `G` with coordinates `x` and `y`\nsatisfying `y^2 = x^3 + 7`.","summary":"

      A commonly used base point G with coordinates x and y satisfying y^2 = x^3 + 7.

      "},{"id":"N","name":"N","value":"Num.new(\"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141\")","doc":"The order `n` of `G` defines the finite size of the Secp256k1 field `E`.","summary":"

      The order n of G defines the finite size of the Secp256k1 field E.

      "},{"id":"P","name":"P","value":"Num.new(\"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f\")","doc":"The elliptic curve domain parameters over `F_p` associated with a\nKoblitz curve `Secp256k1` are specified by the sextuple\n`T = (p, a, b, G, n, h)` where the finite field `F_p` is defined by\nthe prime `p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1`.","summary":"

      The elliptic curve domain parameters over F_p associated with a Koblitz curve Secp256k1 are specified by the sextuple T = (p, a, b, G, n, h) where the finite field F_p is defined by the prime p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1.

      "},{"id":"VERSION","name":"VERSION","value":"\"0.5.0\"","doc":"The `VERSION` of the `Secp256k1` module.","summary":"

      The VERSION of the Secp256k1 module.

      "}],"doc":"Provides the `Secp256k1` module with the elliptic curve parameters\nused by the `Bitcoin`, `Ethereum`, and `Polkadot` blockchains. It's\nprimarily used to generate key-pairs as well as signing messages and\nrecoverying signatures.\n\nRef: [secg.org/sec2-v2.pdf](https://www.secg.org/sec2-v2.pdf)","summary":"

      Provides the Secp256k1 module with the elliptic curve parameters used by the Bitcoin, Ethereum, and Polkadot blockchains.

      ","types":[{"html_id":"secp256k1/Secp256k1/Context","path":"Secp256k1/Context.html","kind":"class","full_name":"Secp256k1::Context","name":"Context","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/context.cr","line_number":22,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a `Secp256k1` context to allow signing arbitrary data,\nrecovering public keys, and verifying signatures.\n\n```\nctx = Context.new\n# => #\n```","summary":"

      Provides a Secp256k1 context to allow signing arbitrary data, recovering public keys, and verifying signatures.

      ","instance_methods":[{"html_id":"sign(key:Key,hash:Num):Signature-instance-method","name":"sign","doc":"Signs a message hash or any other arbitrary data with a given keypair.\n\nParameters:\n* `key` (`Key`): the keypair containing a secret to sign the data.\n* `hash` (`Num`): the message or arbirtrary data hash.\n\nReturns a `Signature` proving the given key signed the message hash.\n\n```\nctx = Context.new\nkey = Key.new Num.new \"1f0c122d41ff536b19bfd83537c0dfc290e45cd3c375a43237c8b8fff7ac8af7\"\nhash = Util.sha256 \"Henlo, Wordl\"\nsig = ctx.sign key, hash\n# => #,\n# @s=#,\n# @v=#>\n```","summary":"

      Signs a message hash or any other arbitrary data with a given keypair.

      ","abstract":false,"args":[{"name":"key","external_name":"key","restriction":"Key"},{"name":"hash","external_name":"hash","restriction":"Num"}],"args_string":"(key : Key, hash : Num) : Signature","args_html":"(key : Key, hash : Num) : Signature","location":{"filename":"src/secp256k1/context.cr","line_number":50,"url":null},"def":{"name":"sign","args":[{"name":"key","external_name":"key","restriction":"Key"},{"name":"hash","external_name":"hash","restriction":"Num"}],"return_type":"Signature","visibility":"Public","body":"k = Util.deterministic_k(key.private_key, hash)\nhash = hash.to_big\npriv = key.private_key.to_big\npoint = Curve.mul(G, k)\nr = point.x.to_big % N.to_big\nk_inv = Curve.mod_inv(k, N)\ns = ((hash + (r * priv)) * k_inv.to_big) % N.to_big\nx_mag = point.x.to_big > N.to_big\ny_parity = (point.y.to_big % 2) == 0\nrec_id : Int8 = -1\nif (!y_parity) && x_mag\n rec_id = 3\nelse\n if y_parity && x_mag\n rec_id = 2\n else\n if (!y_parity) && (!x_mag)\n rec_id = 1\n else\n rec_id = 0\n end\n end\nend\nr = Num.new(r)\ns = Num.new(s)\nv = Num.new(BigInt.new(rec_id))\nSignature.new(r, s, v)\n"}},{"html_id":"verify(sig:Signature,hash:Num,publ:Point):Bool-instance-method","name":"verify","doc":"Verifies that a given signature for a given message hash matches\nthe provided public key.\n\nParameters:\n* `sig` (`Signature`): the signature to be verified.\n* `hash` (`Num`): the message or arbirtrary data hash.\n* `publ` (`Point`): the public key to match.\n\nReturns _true_ if the signature verifies.\n\n```\nctx = Context.new\nr = Num.new \"c4079db44240b7afe94985c69fc89602e33629fd9b8623d711c30ce6378b33df\"\ns = Num.new \"6842c1b63c94bdb8e4f5ae88fb65f7a98b77b197c8323004fb47ef57fab29053\"\nv = Num.new \"00\"\nsig = Signature.new r, s, v\nhash = Util.sha256 \"Henlo, Wordl\"\npubl = Point.new \"0416008a369439f1a8a75cf974860bed5b10180518d6b1dd3ac847f423fd375d6aa29474394f0cd79d2ea543507d069e97339284f01bdbfd27392daec0ec553816\"\nctx.verify sig, hash, publ\n# => true\n```","summary":"

      Verifies that a given signature for a given message hash matches the provided public key.

      ","abstract":false,"args":[{"name":"sig","external_name":"sig","restriction":"Signature"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"publ","external_name":"publ","restriction":"Point"}],"args_string":"(sig : Signature, hash : Num, publ : Point) : Bool","args_html":"(sig : Signature, hash : Num, publ : Point) : Bool","location":{"filename":"src/secp256k1/context.cr","line_number":97,"url":null},"def":{"name":"verify","args":[{"name":"sig","external_name":"sig","restriction":"Signature"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"publ","external_name":"publ","restriction":"Point"}],"return_type":"Bool","visibility":"Public","body":"s_inv = Curve.mod_inv(sig.s, N)\np0 = Curve.mul(G, (hash.to_big * s_inv.to_big) % N.to_big)\np1 = Curve.mul(publ, (sig.r.to_big * s_inv.to_big) % N.to_big)\np = Curve.add(p0, p1)\nsig.r.to_big === p.x.to_big\n"}}]},{"html_id":"secp256k1/Secp256k1/Curve","path":"Secp256k1/Curve.html","kind":"module","full_name":"Secp256k1::Curve","name":"Curve","abstract":false,"locations":[{"filename":"src/secp256k1/curve.cr","line_number":18,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"secp256k1/Secp256k1/Curve","kind":"module","full_name":"Secp256k1::Curve","name":"Curve"}],"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Implements 256-bit `Secp256k1` Koblitz elliptic curve operations.\n\nRef: [secg.org/sec2-v2.pdf](https://www.secg.org/sec2-v2.pdf)","summary":"

      Implements 256-bit Secp256k1 Koblitz elliptic curve operations.

      ","instance_methods":[{"html_id":"add(p:Point,q:Point,prime=P):Point-instance-method","name":"add","doc":"Computes the elliptic curve jive addition of point `p(x, y)` and `q(x, y)`.\nIt _draws_ a line between `p` and `q` which will intersect the\ncurve in the point `r` which will be mirrored over the `x`-axis.\n\nParamters:\n* `p` (`Num`): the point `p(x, y)` to be used in the jive addition.\n* `q` (`Num`): the point `q(x, y)` to be used in the jive addition.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Point` containing the result of the intersection.\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\nq = Point.new Num.new \"7e17f60baa7b8dc8581a55f7be1ea263c6a88452cf3f0a3f710651767654946c\"\nCurve.add p, q\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve jive addition of point p(x, y) and q(x, y).

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"q","external_name":"q","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(p : Point, q : Point, prime = P) : Point","args_html":"(p : Point, q : Point, prime = P) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":82,"url":null},"def":{"name":"add","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"q","external_name":"q","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Point","visibility":"Public","body":"if prime.is_a?(Num)\n prime = prime.to_big\nend\np_x = p.x.to_big\np_y = p.y.to_big\nq_x = q.x.to_big\nq_y = q.y.to_big\nx_delta = q_x - p_x\nx_inv = mod_inv(x_delta)\ny_delta = q_y - p_y\nm = (y_delta * x_inv.to_big) % prime\nx = (((m * m) - p_x) - q_x) % prime\ny = ((m * (p_x - x)) - p_y) % prime\nx = Num.new(x)\ny = Num.new(y)\nPoint.new(x, y)\n"}},{"html_id":"double(p:Point,prime=P):Point-instance-method","name":"double","doc":"Computes the elliptic curve juke point doubling of `p(x, y)`.\nThis is a special case of addition where both points are the same.\nIt _draws_ a tangent line at `p` which will intersect the curve\nat point `r` which will be mirrored over the `x`-axis.\n\nParamters:\n* `p` (`Point`): the point `p(x, y)` to be used in the juke doubling.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Point` as a result of the intersection.\n\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\nCurve.double p\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve juke point doubling of p(x, y).

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(p : Point, prime = P) : Point","args_html":"(p : Point, prime = P) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":123,"url":null},"def":{"name":"double","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Point","visibility":"Public","body":"if prime.is_a?(Num)\n prime = prime.to_big\nend\np_x = p.x.to_big\np_y = p.y.to_big\nlam_numer = (3 * p_x) * p_x\nlam_denom = 2 * p_y\nlam_inv = mod_inv(Num.new(lam_denom))\nlam = (lam_numer * lam_inv.to_big) % prime\nx = ((lam * lam) - (2 * p_x)) % prime\ny = ((lam * (p_x - x)) - p_y) % prime\nx = Num.new(x)\ny = Num.new(y)\nPoint.new(x, y)\n"}},{"html_id":"mod_inv(a:Num|BigInt,prime=P):Num-instance-method","name":"mod_inv","doc":"Computes the elliptic curve modular multiplicative inverse of `a`.\n\nParemeters:\n* `a` (`Num | BigInt`): the integer that we want the modular inverse of.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Num` containing the mod inverse.\n\n```\na = Num.new \"ea678c668356d16d8bf5c69f95c1055e39bd24174605f64846e27c3ae6a88d81\"\nCurve.mod_inv a\n# => #\n```","summary":"

      Computes the elliptic curve modular multiplicative inverse of a.

      ","abstract":false,"args":[{"name":"a","external_name":"a","restriction":"Num | BigInt"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(a : Num | BigInt, prime = P) : Num","args_html":"(a : Num | BigInt, prime = P) : Num","location":{"filename":"src/secp256k1/curve.cr","line_number":37,"url":null},"def":{"name":"mod_inv","args":[{"name":"a","external_name":"a","restriction":"Num | BigInt"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Num","visibility":"Public","body":"if a.is_a?(Num)\n a = a.to_big\nend\nif prime.is_a?(Num)\n prime = prime.to_big\nend\nm_low = 1\nm_high = 0\nv_low = a % prime\nv_high = prime\nwhile v_low > 1\n v_ratio = v_high // v_low\n m_low_r = m_low * v_ratio\n v_low_r = v_low * v_ratio\n m = m_high - m_low_r\n v = v_high - v_low_r\n m_high = m_low\n v_high = v_low\n m_low = m\n v_low = v\nend\nNum.new(m_low % prime)\n"}},{"html_id":"mul(p:Point,s:Num|BigInt):Point-instance-method","name":"mul","doc":"Computes the elliptic curve sequence multiplication of point `p(x, y)`\nand a skalar `s`; with `s` being a private key within the elliptic\ncurve field size of `N`.\n\nParamters:\n* `p` (`Point`): the point `p(x, y)` to be used in the sequencing.\n* `s` (`Num | BigInt`): a skalar, in most cases a private key.\n\nReturns a `Point` as a result of the multiplication.\n\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\ns = Num.new \"f51ad125548b7a283ebf15ab830a25c850d4d863078c48cc9993b79ee18ee11e\"\nCurve.mul p, s\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve sequence multiplication of point p(x, y) and a skalar s; with s being a private key within the elliptic curve field size of N.

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"s","external_name":"s","restriction":"Num | BigInt"}],"args_string":"(p : Point, s : Num | BigInt) : Point","args_html":"(p : Point, s : Num | BigInt) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":162,"url":null},"def":{"name":"mul","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"s","external_name":"s","restriction":"Num | BigInt"}],"return_type":"Point","visibility":"Public","body":"if s.is_a?(Num)\n s = s.to_big\nend\nif (s === 0) || s >= N.to_big\n raise(\"Invalid scalar: outside of Secp256k1 field dimension.\")\nend\ns_bin = s.to_s(2)\nq = p\ns_bin.each_char_with_index do |char, index|\n if index === 0\n next\n end\n q = double(q)\n if char === '1'\n q = add(q, p)\n end\nend\nq\n"}}]},{"html_id":"secp256k1/Secp256k1/Key","path":"Secp256k1/Key.html","kind":"class","full_name":"Secp256k1::Key","name":"Key","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/key.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a `Secp256k1` keypair containing a secret number (private key)\nand a public point on the elliptic curve (public key).\n\nProperties:\n* `private_key` (`Num`): the secret number representing the private key.\n* `public_key` (`Point`): the point on the elliptic curve representing the public key.","summary":"

      Provides a Secp256k1 keypair containing a secret number (private key) and a public point on the elliptic curve (public key).

      ","constructors":[{"html_id":"new(priv:Num)-class-method","name":"new","doc":"Creates a public-private keypair from an existing private key.\n\nParameters:\n* `priv` (`Num`): the private key for the keypair.\n\n```\npriv = Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\nKey.new priv\n# => #,\n# @public_key=#,\n# @y=#>>\n```","summary":"

      Creates a public-private keypair from an existing private key.

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"args_string":"(priv : Num)","args_html":"(priv : Num)","location":{"filename":"src/secp256k1/key.cr","line_number":74,"url":null},"def":{"name":"new","args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(priv)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new-class-method","name":"new","doc":"Creates a new, random `Secp256k1` keypair.\n\n```\nKey.new\n# => #,\n# @public_key=#,\n# @y=#>>\n```","summary":"

      Creates a new, random Secp256k1 keypair.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":46,"url":null},"def":{"name":"new","visibility":"Public","body":"_ = allocate\n_.initialize\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"private_bytes:Bytes-instance-method","name":"private_bytes","doc":"Returns the private key as binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_bytes\n# => Bytes[60, 207, 132, 130, 12, 32, 213, 232, 197, 54, 186, 132, 197, 43, 164, 16, 55, 91, 41, 177, 129, 43, 95, 126, 114, 36, 69, 201, 105, 160, 251, 48]\n```","summary":"

      Returns the private key as binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":95,"url":null},"def":{"name":"private_bytes","return_type":"Bytes","visibility":"Public","body":"@private_key.to_zpadded_bytes"}},{"html_id":"private_hex:String-instance-method","name":"private_hex","doc":"Returns the private key as hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_hex\n# => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\n```","summary":"

      Returns the private key as hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":85,"url":null},"def":{"name":"private_hex","return_type":"String","visibility":"Public","body":"@private_key.to_zpadded_hex"}},{"html_id":"private_key:Num-instance-method","name":"private_key","doc":"The secret number representing the private key.","summary":"

      The secret number representing the private key.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":23,"url":null},"def":{"name":"private_key","return_type":"Num","visibility":"Public","body":"@private_key"}},{"html_id":"private_key=(private_key:Num)-instance-method","name":"private_key=","doc":"The secret number representing the private key.","summary":"

      The secret number representing the private key.

      ","abstract":false,"args":[{"name":"private_key","external_name":"private_key","restriction":"Num"}],"args_string":"(private_key : Num)","args_html":"(private_key : Num)","location":{"filename":"src/secp256k1/key.cr","line_number":23,"url":null},"def":{"name":"private_key=","args":[{"name":"private_key","external_name":"private_key","restriction":"Num"}],"visibility":"Public","body":"@private_key = private_key"}},{"html_id":"public_bytes:Bytes-instance-method","name":"public_bytes","doc":"Returns the public key as uncompressed, binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes\n# => Bytes[4, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162, 129, 54, 61, 41, 142, 74, 64, 235, 203, 19, 241, 175, 168, 90, 11, 148, 185, 103, 242, 67, 238, 89, 165, 144, 16, 203, 93, 234, 240, 215, 182, 108]\n```","summary":"

      Returns the public key as uncompressed, binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":125,"url":null},"def":{"name":"public_bytes","return_type":"Bytes","visibility":"Public","body":"(Num.new(@public_key.uncompressed)).to_bytes"}},{"html_id":"public_bytes_compressed:Bytes-instance-method","name":"public_bytes_compressed","doc":"Returns the public key as compressed, binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes_compressed\n# => Bytes[2, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162]\n```","summary":"

      Returns the public key as compressed, binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":135,"url":null},"def":{"name":"public_bytes_compressed","return_type":"Bytes","visibility":"Public","body":"(Num.new(@public_key.compressed)).to_bytes"}},{"html_id":"public_hex:String-instance-method","name":"public_hex","doc":"Returns the public key as uncompressed, hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex\n# => \"04cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba281363d298e4a40ebcb13f1afa85a0b94b967f243ee59a59010cb5deaf0d7b66c\"\n```","summary":"

      Returns the public key as uncompressed, hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":105,"url":null},"def":{"name":"public_hex","return_type":"String","visibility":"Public","body":"@public_key.uncompressed"}},{"html_id":"public_hex_compressed:String-instance-method","name":"public_hex_compressed","doc":"Returns the public key as compressed, hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex_compressed\n# => \"02cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba2\"\n```","summary":"

      Returns the public key as compressed, hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":115,"url":null},"def":{"name":"public_hex_compressed","return_type":"String","visibility":"Public","body":"@public_key.compressed"}},{"html_id":"public_key:Point-instance-method","name":"public_key","doc":"The point on the elliptic curve representing the public key.","summary":"

      The point on the elliptic curve representing the public key.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":25,"url":null},"def":{"name":"public_key","return_type":"Point","visibility":"Public","body":"@public_key"}},{"html_id":"public_key=(public_key:Point)-instance-method","name":"public_key=","doc":"The point on the elliptic curve representing the public key.","summary":"

      The point on the elliptic curve representing the public key.

      ","abstract":false,"args":[{"name":"public_key","external_name":"public_key","restriction":"Point"}],"args_string":"(public_key : Point)","args_html":"(public_key : Point)","location":{"filename":"src/secp256k1/key.cr","line_number":25,"url":null},"def":{"name":"public_key=","args":[{"name":"public_key","external_name":"public_key","restriction":"Point"}],"visibility":"Public","body":"@public_key = public_key"}}]},{"html_id":"secp256k1/Secp256k1/Num","path":"Secp256k1/Num.html","kind":"class","full_name":"Secp256k1::Num","name":"Num","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/num.cr","line_number":25,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a class to conveniently handle big numbers on the elliptic\ncurve. It allows to easily access decimal, hexadecimal, and binary\nrepresentations of the numeric. In addition, it implements some\nutilities such as zpadding or asserting hexadecimal strings. It's suited\nto temporarily handle unencrypted private keys.\n\nProperties:\n* `hex` (`String`): the hexadecimal string representation of the number.\n* `dec` (`BigInt`): the decimal big-integer representation of the number.\n* `bin` (`Bytes`): the binary bytes-slice represenation of the number.","summary":"

      Provides a class to conveniently handle big numbers on the elliptic curve.

      ","constructors":[{"html_id":"new(hex:String)-class-method","name":"new","doc":"Creates a number from a hexadecimal string literal.\n\nParameters:\n* `hex` (`String`): a hexadecimal string representating the number.\n\n```\nNum.new \"568a0f505bde902db4a6afd207c794c7845fe7715da5999bb276d453c702a46d\"\n# => #\n```","summary":"

      Creates a number from a hexadecimal string literal.

      ","abstract":false,"args":[{"name":"hex","external_name":"hex","restriction":"String"}],"args_string":"(hex : String)","args_html":"(hex : String)","location":{"filename":"src/secp256k1/num.cr","line_number":67,"url":null},"def":{"name":"new","args":[{"name":"hex","external_name":"hex","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(hex)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(num:BigInt)-class-method","name":"new","doc":"Creates a number from a big integer numeric.\n\nParameters:\n* `dec` (`BigInt`): the decimal big-integer representating the number.\n\n```\nNum.new BigInt.new \"39142835565766237398843902819171565157710677457569850027793715608438337348717\"\n# => #\n```","summary":"

      Creates a number from a big integer numeric.

      ","abstract":false,"args":[{"name":"num","external_name":"num","restriction":"BigInt"}],"args_string":"(num : BigInt)","args_html":"(num : BigInt)","location":{"filename":"src/secp256k1/num.cr","line_number":87,"url":null},"def":{"name":"new","args":[{"name":"num","external_name":"num","restriction":"BigInt"}],"visibility":"Public","body":"_ = allocate\n_.initialize(num)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(bin:Slice(UInt8))-class-method","name":"new","doc":"Creates a number from a binary bytes slice.\n\nParameters:\n* `bin` (`Bytes`): the binary bytes-slice represenating the number.\n\n```\nNum.new Bytes[86, 138, 15, 80, 91, 222, 144, 45, 180, 166, 175, 210, 7, 199, 148, 199, 132, 95, 231, 113, 93, 165, 153, 155, 178, 118, 212, 83, 199, 2, 164, 109]\n# => #\n```","summary":"

      Creates a number from a binary bytes slice.

      ","abstract":false,"args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"args_string":"(bin : Slice(UInt8))","args_html":"(bin : Slice(UInt8))","location":{"filename":"src/secp256k1/num.cr","line_number":107,"url":null},"def":{"name":"new","args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"visibility":"Public","body":"_ = allocate\n_.initialize(bin)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new-class-method","name":"new","doc":"Creates a random number using `Random::Secure` that can be used as\na secret (private key).\n\n```\nNum.new\n# => #\n```","summary":"

      Creates a random number using Random::Secure that can be used as a secret (private key).

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":43,"url":null},"def":{"name":"new","visibility":"Public","body":"_ = allocate\n_.initialize\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"bin:Slice(UInt8)-instance-method","name":"bin","doc":"The binary bytes-slice represenation of the number.","summary":"

      The binary bytes-slice represenation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":31,"url":null},"def":{"name":"bin","return_type":"Slice(UInt8)","visibility":"Public","body":"@bin"}},{"html_id":"bin=(bin:Slice(UInt8))-instance-method","name":"bin=","doc":"The binary bytes-slice represenation of the number.","summary":"

      The binary bytes-slice represenation of the number.

      ","abstract":false,"args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"args_string":"(bin : Slice(UInt8))","args_html":"(bin : Slice(UInt8))","location":{"filename":"src/secp256k1/num.cr","line_number":31,"url":null},"def":{"name":"bin=","args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"visibility":"Public","body":"@bin = bin"}},{"html_id":"dec:BigInt-instance-method","name":"dec","doc":"The decimal big-integer representation of the number.","summary":"

      The decimal big-integer representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":29,"url":null},"def":{"name":"dec","return_type":"BigInt","visibility":"Public","body":"@dec"}},{"html_id":"dec=(dec:BigInt)-instance-method","name":"dec=","doc":"The decimal big-integer representation of the number.","summary":"

      The decimal big-integer representation of the number.

      ","abstract":false,"args":[{"name":"dec","external_name":"dec","restriction":"BigInt"}],"args_string":"(dec : BigInt)","args_html":"(dec : BigInt)","location":{"filename":"src/secp256k1/num.cr","line_number":29,"url":null},"def":{"name":"dec=","args":[{"name":"dec","external_name":"dec","restriction":"BigInt"}],"visibility":"Public","body":"@dec = dec"}},{"html_id":"hex:String-instance-method","name":"hex","doc":"The hexadecimal string representation of the number.","summary":"

      The hexadecimal string representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":27,"url":null},"def":{"name":"hex","return_type":"String","visibility":"Public","body":"@hex"}},{"html_id":"hex=(hex:String)-instance-method","name":"hex=","doc":"The hexadecimal string representation of the number.","summary":"

      The hexadecimal string representation of the number.

      ","abstract":false,"args":[{"name":"hex","external_name":"hex","restriction":"String"}],"args_string":"(hex : String)","args_html":"(hex : String)","location":{"filename":"src/secp256k1/num.cr","line_number":27,"url":null},"def":{"name":"hex=","args":[{"name":"hex","external_name":"hex","restriction":"String"}],"visibility":"Public","body":"@hex = hex"}},{"html_id":"to_big:BigInt-instance-method","name":"to_big","doc":"Returns a big-integer representation of the number.\n\n```\nNum.new(Bytes[137]).to_big\n# => 137\n```","summary":"

      Returns a big-integer representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":156,"url":null},"def":{"name":"to_big","return_type":"BigInt","visibility":"Public","body":"@dec"}},{"html_id":"to_bytes:Bytes-instance-method","name":"to_bytes","doc":"Returns a binary byte-slice representation of the number.\n\n```\nNum.new(\"0x89\").to_bytes\n# => Bytes[137]\n```","summary":"

      Returns a binary byte-slice representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":166,"url":null},"def":{"name":"to_bytes","return_type":"Bytes","visibility":"Public","body":"@bin"}},{"html_id":"to_hex:String-instance-method","name":"to_hex","doc":"Returns an unprefixed hexadecimal string representation.\n\n```\nNum.new(Bytes[137]).to_hex\n# => \"89\"\n```","summary":"

      Returns an unprefixed hexadecimal string representation.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":119,"url":null},"def":{"name":"to_hex","return_type":"String","visibility":"Public","body":"@hex"}},{"html_id":"to_prefixed_hex:String-instance-method","name":"to_prefixed_hex","doc":"Returns an `0x`-prefixed hexadecimal string representation.\n\n```\nNum.new(Bytes[137]).to_prefixed_hex\n# => \"0x89\"\n```","summary":"

      Returns an 0x-prefixed hexadecimal string representation.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":129,"url":null},"def":{"name":"to_prefixed_hex","return_type":"String","visibility":"Public","body":"\"0x#{@hex}\""}},{"html_id":"to_zpadded_bytes(length=32):Bytes-instance-method","name":"to_zpadded_bytes","doc":"Returns a z-padded byte-slice binary representation.\n\nParameters:\n* `length` (`Int`): the byte-size of the final z-padded slice (default `32`).\n\n```\nNum.new(Bytes[137]).to_zpadded_bytes\n# => Bytes[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137]\n```","summary":"

      Returns a z-padded byte-slice binary representation.

      ","abstract":false,"args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"args_string":"(length = 32) : Bytes","args_html":"(length = 32) : Bytes","location":{"filename":"src/secp256k1/num.cr","line_number":179,"url":null},"def":{"name":"to_zpadded_bytes","args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"return_type":"Bytes","visibility":"Public","body":"zpadded_bytes = @bin\nwhile zpadded_bytes.size < length\n zpadded_bytes = Util.concat_bytes(Bytes[0], zpadded_bytes)\nend\nzpadded_bytes\n"}},{"html_id":"to_zpadded_hex(length=32):String-instance-method","name":"to_zpadded_hex","doc":"Returns a z-padded hexadecimal string representation.\n\nParameters:\n* `length` (`Int`): the byte-size of the final z-padded hex-string (default `32`).\n\n```\nNum.new(Bytes[137]).to_zpadded_hex\n# => \"0000000000000000000000000000000000000000000000000000000000000089\"\n```","summary":"

      Returns a z-padded hexadecimal string representation.

      ","abstract":false,"args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"args_string":"(length = 32) : String","args_html":"(length = 32) : String","location":{"filename":"src/secp256k1/num.cr","line_number":142,"url":null},"def":{"name":"to_zpadded_hex","args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"return_type":"String","visibility":"Public","body":"zpadded_hex = @hex\nwhile zpadded_hex.size < (length * 2)\n zpadded_hex = \"0#{zpadded_hex}\"\nend\nzpadded_hex\n"}}]},{"html_id":"secp256k1/Secp256k1/Point","path":"Secp256k1/Point.html","kind":"class","full_name":"Secp256k1::Point","name":"Point","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/point.cr","line_number":30,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a point in the two-dimensional space of any elliptic curve.\nIn most cases, such a point on a given curve represents a public key.\nHowever, for keypairs, a `Key` type shall be used!\n\nProperties:\n* `x` (`Num`): the position on the x-axis.\n* `y` (`Num`): the position on the y-axis.","summary":"

      Provides a point in the two-dimensional space of any elliptic curve.

      ","constructors":[{"html_id":"new(x:Num,y:Num)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing the x- and y-coordinates (public key).\n\nParameters:\n* `x` (`Num`): the position on the x-axis.\n* `y` (`Num`): the position on the y-axis.\n\n```\nx = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ny = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nPoint.new x, y\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing the x- and y-coordinates (public key).

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Num"},{"name":"y","external_name":"y","restriction":"Num"}],"args_string":"(x : Num, y : Num)","args_html":"(x : Num, y : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":58,"url":null},"def":{"name":"new","args":[{"name":"x","external_name":"x","restriction":"Num"},{"name":"y","external_name":"y","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(x, y)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(priv:Num)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing a random number (private key). Note, that the\nprivate key will be consumed by this constructor and should only be used\nto retrieve a public key. To manage keypairs, use the `Key` type instead.\n\nParameters:\n* `priv` (`Num`): the random number giving access to the point.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new priv\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing a random number (private key).

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"args_string":"(priv : Num)","args_html":"(priv : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":84,"url":null},"def":{"name":"new","args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(priv)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(pub:String)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing a compressed or uncompressed public key.\n\nParameters:\n* `pub` (`String`): the public key string (compressed or uncompressed).\n\n```\npub = \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\"\nPoint.new pub\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing a compressed or uncompressed public key.

      ","abstract":false,"args":[{"name":"pub","external_name":"pub","restriction":"String"}],"args_string":"(pub : String)","args_html":"(pub : String)","location":{"filename":"src/secp256k1/point.cr","line_number":109,"url":null},"def":{"name":"new","args":[{"name":"pub","external_name":"pub","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(pub)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"compressed:String-instance-method","name":"compressed","doc":"Returns a prefixed, compressed public key string for the given point\nin the format `prefix|x|y`.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new(priv).compressed\n# => \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\"\n```","summary":"

      Returns a prefixed, compressed public key string for the given point in the format prefix|x|y.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":161,"url":null},"def":{"name":"compressed","return_type":"String","visibility":"Public","body":"prefix = 2 + (@y.to_big % 2)\nprefix = \"0#{prefix}\"\n\"#{prefix}#{@x.to_zpadded_hex}\"\n"}},{"html_id":"uncompressed:String-instance-method","name":"uncompressed","doc":"Returns a prefixed, uncompressed public key string for the given point\nin the format `04|x|y`.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new(priv).uncompressed\n# => \"04aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f21f4c49cfe90da39c254a51b8ee8afcdd8c02dd566f13582c23e104c7ed5936b\"\n```","summary":"

      Returns a prefixed, uncompressed public key string for the given point in the format 04|x|y.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":148,"url":null},"def":{"name":"uncompressed","return_type":"String","visibility":"Public","body":"prefix = \"04\"\n\"#{prefix}#{@x.to_zpadded_hex}#{@y.to_zpadded_hex}\"\n"}},{"html_id":"x:Num-instance-method","name":"x","doc":"The position on the x-axis.","summary":"

      The position on the x-axis.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":32,"url":null},"def":{"name":"x","return_type":"Num","visibility":"Public","body":"@x"}},{"html_id":"x=(x:Num)-instance-method","name":"x=","doc":"The position on the x-axis.","summary":"

      The position on the x-axis.

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Num"}],"args_string":"(x : Num)","args_html":"(x : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":32,"url":null},"def":{"name":"x=","args":[{"name":"x","external_name":"x","restriction":"Num"}],"visibility":"Public","body":"@x = x"}},{"html_id":"y:Num-instance-method","name":"y","doc":"The position on the y-axis.","summary":"

      The position on the y-axis.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":35,"url":null},"def":{"name":"y","return_type":"Num","visibility":"Public","body":"@y"}},{"html_id":"y=(y:Num)-instance-method","name":"y=","doc":"The position on the y-axis.","summary":"

      The position on the y-axis.

      ","abstract":false,"args":[{"name":"y","external_name":"y","restriction":"Num"}],"args_string":"(y : Num)","args_html":"(y : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":35,"url":null},"def":{"name":"y=","args":[{"name":"y","external_name":"y","restriction":"Num"}],"visibility":"Public","body":"@y = y"}}]},{"html_id":"secp256k1/Secp256k1/Signature","path":"Secp256k1/Signature.html","kind":"class","full_name":"Secp256k1::Signature","name":"Signature","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/signature.cr","line_number":22,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides an ECDSA Signature containing the random point `r`, the\nsignature proof `s`, and the recovery id or `v` value.\n\nProperties:\n* `r` (`Num`): the `x` coordinate of a random point `R` on the curve.\n* `s` (`Num`): the signature proof of a message.\n* `v` (`Num`): the recovery id or `v` value.","summary":"

      Provides an ECDSA Signature containing the random point #r, the signature proof #s, and the recovery id or #v value.

      ","constructors":[{"html_id":"new(r:Num,s:Num,v:Num)-class-method","name":"new","doc":"Provides an ECDSA Signature containing the random point `r`, the\nsignature proof `s`, and the recovery id or `v` value.\n\nParameters:\n* `r` (`Num`): the `x` coordinate of a random point `R` on the curve.\n* `s` (`Num`): the signature proof of a message.\n* `v` (`Num`): the recovery id or `v` value.\n\n```\nr = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ns = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nv = Num.new \"00\"\nSignature.new r, s, v\n# => #,\n# @s=#,\n# @v=#>\n```","summary":"

      Provides an ECDSA Signature containing the random point #r, the signature proof #s, and the recovery id or #v value.

      ","abstract":false,"args":[{"name":"r","external_name":"r","restriction":"Num"},{"name":"s","external_name":"s","restriction":"Num"},{"name":"v","external_name":"v","restriction":"Num"}],"args_string":"(r : Num, s : Num, v : Num)","args_html":"(r : Num, s : Num, v : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":59,"url":null},"def":{"name":"new","args":[{"name":"r","external_name":"r","restriction":"Num"},{"name":"s","external_name":"s","restriction":"Num"},{"name":"v","external_name":"v","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(r, s, v)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"compact:String-instance-method","name":"compact","doc":"Returns a compact `String` containing the concatenated signature\nin the form `r|s|v`.\n\n```\nr = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ns = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nv = Num.new \"00\"\nSignature.new(r, s, v).compact\n# => \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae000\"\n```","summary":"

      Returns a compact String containing the concatenated signature in the form r|s|v.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":75,"url":null},"def":{"name":"compact","return_type":"String","visibility":"Public","body":"\"#{r.to_zpadded_hex}#{s.to_zpadded_hex}#{v.to_hex}\""}},{"html_id":"r:Num-instance-method","name":"r","doc":"The `x` coordinate of a random point `R` on the curve.","summary":"

      The x coordinate of a random point R on the curve.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":24,"url":null},"def":{"name":"r","return_type":"Num","visibility":"Public","body":"@r"}},{"html_id":"r=(r:Num)-instance-method","name":"r=","doc":"The `x` coordinate of a random point `R` on the curve.","summary":"

      The x coordinate of a random point R on the curve.

      ","abstract":false,"args":[{"name":"r","external_name":"r","restriction":"Num"}],"args_string":"(r : Num)","args_html":"(r : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":24,"url":null},"def":{"name":"r=","args":[{"name":"r","external_name":"r","restriction":"Num"}],"visibility":"Public","body":"@r = r"}},{"html_id":"s:Num-instance-method","name":"s","doc":"The signature proof of a message.","summary":"

      The signature proof of a message.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":27,"url":null},"def":{"name":"s","return_type":"Num","visibility":"Public","body":"@s"}},{"html_id":"s=(s:Num)-instance-method","name":"s=","doc":"The signature proof of a message.","summary":"

      The signature proof of a message.

      ","abstract":false,"args":[{"name":"s","external_name":"s","restriction":"Num"}],"args_string":"(s : Num)","args_html":"(s : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":27,"url":null},"def":{"name":"s=","args":[{"name":"s","external_name":"s","restriction":"Num"}],"visibility":"Public","body":"@s = s"}},{"html_id":"v:Num-instance-method","name":"v","doc":"The recovery id or `v` value.","summary":"

      The recovery id or #v value.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":30,"url":null},"def":{"name":"v","return_type":"Num","visibility":"Public","body":"@v"}},{"html_id":"v=(v:Num)-instance-method","name":"v=","doc":"The recovery id or `v` value.","summary":"

      The recovery id or #v value.

      ","abstract":false,"args":[{"name":"v","external_name":"v","restriction":"Num"}],"args_string":"(v : Num)","args_html":"(v : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":30,"url":null},"def":{"name":"v=","args":[{"name":"v","external_name":"v","restriction":"Num"}],"visibility":"Public","body":"@v = v"}}]},{"html_id":"secp256k1/Secp256k1/Util","path":"Secp256k1/Util.html","kind":"module","full_name":"Secp256k1::Util","name":"Util","abstract":false,"locations":[{"filename":"src/secp256k1/util.cr","line_number":17,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"secp256k1/Secp256k1/Util","kind":"module","full_name":"Secp256k1::Util","name":"Util"}],"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a collection of utilities for convenience, e.g., to bind\nrelevant hashing algorithms, or to concatenate byte slices.","summary":"

      Provides a collection of utilities for convenience, e.g., to bind relevant hashing algorithms, or to concatenate byte slices.

      ","instance_methods":[{"html_id":"concat_bytes(x:Bytes,y:Bytes):Bytes-instance-method","name":"concat_bytes","doc":"Concatenates two byte slices in the order provided, i.e., `x|y`.\n\nParameters:\n* `x` (`Bytes`): a byte slice.\n* `y` (`Bytes`): another byte slice.\n\nReturns a concatenated `Bytes` slice.\n\n```\nUtil.concat_bytes Bytes[1, 2, 3], Bytes[9, 8, 7]\n# => Bytes[1, 2, 3, 9, 8, 7]\n```","summary":"

      Concatenates two byte slices in the order provided, i.e., x|y.

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Bytes"},{"name":"y","external_name":"y","restriction":"Bytes"}],"args_string":"(x : Bytes, y : Bytes) : Bytes","args_html":"(x : Bytes, y : Bytes) : Bytes","location":{"filename":"src/secp256k1/util.cr","line_number":177,"url":null},"def":{"name":"concat_bytes","args":[{"name":"x","external_name":"x","restriction":"Bytes"},{"name":"y","external_name":"y","restriction":"Bytes"}],"return_type":"Bytes","visibility":"Public","body":"z = IO::Memory.new(x.bytesize + y.bytesize)\nx.each do |b|\n z.write_bytes(UInt8.new(b))\nend\ny.each do |b|\n z.write_bytes(UInt8.new(b))\nend\nreturn z.to_slice\n"}},{"html_id":"deterministic_k(priv:Num,hash:Num,order=N):Num-instance-method","name":"deterministic_k","doc":"Provides a deterministic secret based on private key and message hash\nas defined in RFC-6979.\n\nRef: [datatracker.ietf.org/doc/html/rfc6979](https://datatracker.ietf.org/doc/html/rfc6979)\n\nParameters:\n* `priv` (`Num`): the private key or secret number.\n* `hash` (`Num`): the message hash or arbirtrary data hash.\n* `order` (`Num`): the order of the curve over `G` (default `N`).\n\nReturns a deterministically random number of type `Num`.\n\n```\npriv = Num.new \"3b74fcc0b0c419a00d2d9e88b15fbd99e03920138da22e2a00c327b88d24cf45\"\nhash = Util.sha256 \"Henlo, Wordl\"\nUtil.deterministic_k(priv, hash)\n# => #\n```","summary":"

      Provides a deterministic secret based on private key and message hash as defined in RFC-6979.

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"order","default_value":"N","external_name":"order","restriction":""}],"args_string":"(priv : Num, hash : Num, order = N) : Num","args_html":"(priv : Num, hash : Num, order = N) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":135,"url":null},"def":{"name":"deterministic_k","args":[{"name":"priv","external_name":"priv","restriction":"Num"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"order","default_value":"N","external_name":"order","restriction":""}],"return_type":"Num","visibility":"Public","body":"order_size = order.hex.size // 2\nv = Num.new(Bytes.new(order_size, 1))\nk = Num.new(Bytes.new(order_size, 0))\nconcat = Util.concat_bytes(v.bin, Bytes[0])\nconcat = Util.concat_bytes(concat, priv.bin)\nconcat = Util.concat_bytes(concat, hash.bin)\nk = OpenSSL::HMAC.digest(:sha256, k.bin, concat)\nv = OpenSSL::HMAC.digest(:sha256, k, v.bin)\nconcat = Util.concat_bytes(v, Bytes[0])\nconcat = Util.concat_bytes(concat, priv.bin)\nconcat = Util.concat_bytes(concat, hash.bin)\nk = OpenSSL::HMAC.digest(:sha256, k, concat)\nv = OpenSSL::HMAC.digest(:sha256, k, v)\nwhile true\n t = IO::Memory.new.to_slice\n while t.size < order_size\n v = OpenSSL::HMAC.digest(:sha256, k, v)\n t = Util.concat_bytes(t, v)\n end\n secret = Num.new(t)\n if secret.dec < order.dec && secret.dec > 0\n return secret\n end\n increment = Util.concat_bytes(v, Bytes[0])\n k = OpenSSL::HMAC.digest(:sha256, k, increment)\n v = OpenSSL::HMAC.digest(:sha256, k, v)\nend\n"}},{"html_id":"keccak(data:Num|String,entropy=256):Num-instance-method","name":"keccak","doc":"Operating a Keccak hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | String`): the binary numeric or string literal to be hashed.\n* `entropy` (`Int32`): the required entropy (default `256`).\n\nReturns a `Num` representing the Keccak hash.\n\n```\nUtil.keccak(Num.new \"0xdeadbeef\").hex\n# => \"d4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1\"\n\nUtil.keccak(\"0xdeadbeef\").hex\n# => \"4f440a001006a49f24a7de53c04eca3f79aef851ac58e460c9630d044277c8b0\"\n```","summary":"

      Operating a Keccak hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"args_string":"(data : Num | String, entropy = 256) : Num","args_html":"(data : Num | String, entropy = 256) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":35,"url":null},"def":{"name":"keccak","args":[{"name":"data","external_name":"data","restriction":"Num | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"return_type":"Num","visibility":"Public","body":"keccak = Digest::Keccak3.new(entropy)\nif data.is_a?(String)\n return Num.new((keccak.update(data)).hexdigest)\nelse\n return Num.new((keccak.update(data.to_bytes)).hexdigest)\nend\n"}},{"html_id":"ripemd160(data:Num|String):Num-instance-method","name":"ripemd160","doc":"Operating a RIPEMD-160 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | String`): the binary numeric or string literal to be hashed.\n\nReturns a `Num` representing the RIPEMD hash.\n\n```\nUtil.ripemd160(Num.new \"0xdeadbeef\").hex\n# => \"226821c2f5423e11fe9af68bd285c249db2e4b5a\"\n\nUtil.ripemd160(\"0xdeadbeef\").hex\n# => \"4caf817f14e84b564e47afd19966e5d123ee0183\"\n```","summary":"

      Operating a RIPEMD-160 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | String"}],"args_string":"(data : Num | String) : Num","args_html":"(data : Num | String) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":105,"url":null},"def":{"name":"ripemd160","args":[{"name":"data","external_name":"data","restriction":"Num | String"}],"return_type":"Num","visibility":"Public","body":"ripemd = OpenSSL::Digest.new(\"RIPEMD160\")\nif data.is_a?(String)\n return Num.new((ripemd.update(data)).final.hexstring)\nelse\n return Num.new((ripemd.update(data.to_bytes)).final.hexstring)\nend\n"}},{"html_id":"sha256(data:Num|String):Num-instance-method","name":"sha256","doc":"Operating a SHA2-256 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | String`): the binary numeric or string literal to be hashed.\n\nReturns a `Num` representing the SHA2 hash.\n\n```\nUtil.sha256(Num.new \"0xdeadbeef\").hex\n# => \"5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953\"\n\nUtil.sha256(\"0xdeadbeef\").hex\n# => \"4142710b9b4caaeb000b8e5de271bbebac7f509aab2f5e61d1ed1958bfe6d583\"\n```","summary":"

      Operating a SHA2-256 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | String"}],"args_string":"(data : Num | String) : Num","args_html":"(data : Num | String) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":82,"url":null},"def":{"name":"sha256","args":[{"name":"data","external_name":"data","restriction":"Num | String"}],"return_type":"Num","visibility":"Public","body":"sha2 = OpenSSL::Digest.new(\"SHA256\")\nif data.is_a?(String)\n return Num.new((sha2.update(data)).final.hexstring)\nelse\n return Num.new((sha2.update(data.to_bytes)).final.hexstring)\nend\n"}},{"html_id":"sha3(data:Num|String,entropy=256):Num-instance-method","name":"sha3","doc":"Operating a SHA3 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | String`): the binary numeric or string literal to be hashed.\n* `entropy` (`Int32`): the required entropy (default `256`).\n\nReturns a `Num` representing the SHA3 hash.\n\n```\nUtil.sha3(Num.new \"0xdeadbeef\").hex\n# => \"352b82608dad6c7ac3dd665bc2666e5d97803cb13f23a1109e2105e93f42c448\"\n\nUtil.sha3(\"0xdeadbeef\").hex\n# => \"c12811e13ed75afe3e0945ef34e8a25b9d321a46e131c6463731de25a21b39eb\"\n```","summary":"

      Operating a SHA3 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"args_string":"(data : Num | String, entropy = 256) : Num","args_html":"(data : Num | String, entropy = 256) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":59,"url":null},"def":{"name":"sha3","args":[{"name":"data","external_name":"data","restriction":"Num | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"return_type":"Num","visibility":"Public","body":"sha3 = Digest::SHA3.new(entropy)\nif data.is_a?(String)\n return Num.new((sha3.update(data)).hexdigest)\nelse\n return Num.new((sha3.update(data.to_bytes)).hexdigest)\nend\n"}}]}]}]}}) \ No newline at end of file +crystal_doc_search_index_callback({"repository_name":"secp256k1","body":"# secp256k1.cr\n\n[![Build Status](https://img.shields.io/github/workflow/status/q9f/secp256k1.cr/Nightly)](https://github.com/q9f/secp256k1.cr/actions)\n[![Code Coverage](https://codecov.io/gh/q9f/secp256k1.cr/branch/main/graph/badge.svg?token=ngxRs9HdJA)](https://codecov.io/gh/q9f/secp256k1.cr)\n[![Documentation](https://img.shields.io/badge/docs-html-black)](https://q9f.github.io/secp256k1.cr/)\n[![Release](https://img.shields.io/github/v/release/q9f/secp256k1.cr?include_prereleases&color=black)](https://github.com/q9f/secp256k1.cr/releases/latest)\n[![Language](https://img.shields.io/github/languages/top/q9f/secp256k1.cr?color=black)](https://github.com/q9f/secp256k1.cr/search?l=crystal)\n[![License](https://img.shields.io/github/license/q9f/secp256k1.cr.svg?color=black)](LICENSE)\n\nA library implementing the `Secp256k1` elliptic curve natively in pure Crystal.\n`Secp256k1` is the elliptic curve used in the public-private-key cryptography required by `Bitcoin`, `Ethereum`, and `Polkadot`.\n\nThis library allows for:\n* providing a `Secp256k1` cryptographic context, see `Secp256k1::Context`\n* managing `Secp256k1` signatures and verification, see `Secp256k1::Signature`\n* managing private-public keypairs, see `Secp256k1::Key`\n* generating public keys, see `Secp256k1::Point`\n* generating private keys, see `Secp256k1::Num`\n\n# Installation\n\nAdd the `Secp256k1` library to your `shard.yml`\n\n```yaml\ndependencies:\n secp256k1:\n github: q9f/secp256k1.cr\n version: \"~> 0.5\"\n```\n\n# Usage\n\nImport and expose the `Secp256k1` module.\n\n```crystal\nrequire \"secp256k1\"\n```\n\nThis library exposes the following modules and classes (in logical order):\n\n* `Secp256k1`: necessary constants and data structures, including:\n - `Secp256k1::Num`: for managing big numerics (private keys)\n - `Secp256k1::Point`: for handling of elliptic curve points (public keys)\n - `Secp256k1::Key`: for managing private-public keypairs (accounts)\n - `Secp256k1::Signature`: for handling ECDSA signatures (r, s, v)\n* `Secp256k1::Context`: providing a cryptographic context for signing and verification\n* `Secp256k1::Curve`: the entire core mathematics behind the elliptic curve cryptography\n* `Secp256k1::Util`: binding of various hashing algorithms for convenience\n\nBasic usage:\n\n```crystal\n# generates a new, random keypair\nkey = Secp256k1::Key.new\n# => #,\n# @public_key=#,\n# @y=#>>\n\n# gets the private key\nkey.private_hex\n# => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\n\n# gets the compressed public key with prefix\nkey.public_hex_compressed\n# => \"02cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba2\"\n```\n\nSignature generation and verification:\n\n```crystal\n# sign a message with a private key\nctx = Secp256k1::Context.new\npriv = Secp256k1::Num.new \"1f0c122d41ff536b19bfd83537c0dfc290e45cd3c375a43237c8b8fff7ac8af7\"\nkey = Secp256k1::Key.new priv\nhash = Secp256k1::Util.sha256 \"Henlo, Wordl\"\nsig = ctx.sign key, hash\n# => #,\n# @s=#,\n# @v=#>\n\n# verify a signature with a public key\nr = Secp256k1::Num.new \"c4079db44240b7afe94985c69fc89602e33629fd9b8623d711c30ce6378b33df\"\ns = Secp256k1::Num.new \"6842c1b63c94bdb8e4f5ae88fb65f7a98b77b197c8323004fb47ef57fab29053\"\nv = Secp256k1::Num.new \"00\"\nsig = Secp256k1::Signature.new r, s, v\nhash = Secp256k1::Util.sha256 \"Henlo, Wordl\"\npubl = Secp256k1::Point.new \"0416008a369439f1a8a75cf974860bed5b10180518d6b1dd3ac847f423fd375d6aa29474394f0cd79d2ea543507d069e97339284f01bdbfd27392daec0ec553816\"\nctx.verify sig, hash, publ\n# => true\n```\n\n# Documentation\n\nThe full library documentation can be found here: [q9f.github.io/secp256k1.cr](https://q9f.github.io/secp256k1.cr/)\n\nGenerate a local copy with:\n\n```shell\ncrystal docs\n```\n\n# Testing\n\nThe library is entirely specified through tests in `./spec`; run:\n\n```shell\ncrystal spec --verbose\n```\n\n# Understand\n\nPrivate keys are just scalars (`Secp256k1::Num`) and public keys are points (`Secp256k1::Point`) with `x` and `y` coordinates.\n\nBitcoin public keys can be uncompressed `p|x|y` or compressed `p|x`. both come with a prefix `p` which is useless for uncompressed keys but necessary for compressed keys to recover the `y` coordinate on the `Secp256k1` elliptic curve field.\n\nEthereum public keys are uncompressed `x|y` without any prefix. The last 20 bytes slice of the `y` coordinate is actually used as address without any checksum. A checksum was later added in EIP-55 using a `keccak256` hash and indicating character capitalization.\n\nNeither Bitcoin nor Ethereum allow for recovering public keys from an address unless there exists a transaction with a valid signature on the blockchain.\n\n# Known issues\n\n_Note: this library should not be used in production without proper auditing. It should be considered slow and insecure._\n\n* This library is not constant time and might be subject to side-channel attacks. ([#4](https://github.com/q9f/secp256k1.cr/issues/4))\n* This library does unnecessary big-integer math and should someday rather correctly implement the `Secp256k1` prime field ([#5](https://github.com/q9f/secp256k1.cr/issues/5))\n* This library is slow in recovering signatures. Future versions should respect the recovery ID to quickly identify the correct public key from a signature.\n\nFound any other issue? Report it: [github.com/q9f/secp256k1.cr/issues](https://github.com/q9f/secp256k1.cr/issues)\n\n# Contribute\n\nCreate a pull request, and make sure tests and linter pass.\n\nThis pure crystal implementation is based on the python implementation [wobine/blackboard101](https://github.com/wobine/blackboard101) which is also used as reference to write tests against. It's a complete rewrite of the abandoned [packetzero/bitcoinutils](https://github.com/packetzero/bitcoinutils) for educational purposes.\n\nHonerable mention for the [bitcoin wiki](https://en.bitcoin.it/wiki/Main_Page) and the [ethereum stackexchange](https://ethereum.stackexchange.com/) for providing so many in-depth resources that supported this project in reimplementing everything.\n\nLicense: Apache License v2.0\n\nContributors: [**@q9f**](https://github.com/q9f/), [@cserb](https://github.com/cserb), [MrSorcus](https://github.com/MrSorcus)\n","program":{"html_id":"secp256k1/toplevel","path":"toplevel.html","kind":"module","full_name":"Top Level Namespace","name":"Top Level Namespace","abstract":false,"ancestors":[{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"}],"locations":[],"repository_name":"secp256k1","program":true,"enum":false,"alias":false,"const":false,"included_modules":[{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"}],"extended_modules":[{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"}],"types":[{"html_id":"secp256k1/Bitcoin","path":"Bitcoin.html","kind":"module","full_name":"Bitcoin","name":"Bitcoin","abstract":false,"locations":[{"filename":"src/bitcoin.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"BASE_58","name":"BASE_58","value":"\"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz\"","doc":"The Base-58 alphabet for `Bitcoin` addresses is a Base-64 alphabet without\n`0`, `O`, `I`, and `l` to omit similar-looking letters.","summary":"

      The Base-58 alphabet for Bitcoin addresses is a Base-64 alphabet without 0, O, I, and l to omit similar-looking letters.

      "}],"doc":"An example implementation of a `Bitcoin` account using an `Secp256k1`\nkey-pair and a Bitcoin network version identifier; only for educational\npurposes and should not be used in production.","summary":"

      An example implementation of a Bitcoin account using an Secp256k1 key-pair and a Bitcoin network version identifier; only for educational purposes and should not be used in production.

      ","types":[{"html_id":"secp256k1/Bitcoin/Account","path":"Bitcoin/Account.html","kind":"class","full_name":"Bitcoin::Account","name":"Account","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/bitcoin.cr","line_number":29,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Bitcoin","kind":"module","full_name":"Bitcoin","name":"Bitcoin"},"doc":"An example implementation of a `Bitcoin` account using an `Secp256k1`\nkey-pair and a Bitcoin network version identifier; only for educational\npurposes and should not be used in production.","summary":"

      An example implementation of a Bitcoin account using an Secp256k1 key-pair and a Bitcoin network version identifier; only for educational purposes and should not be used in production.

      ","constructors":[{"html_id":"new(key=Key.new,version=Num.new(\"0x00\"))-class-method","name":"new","doc":"Creates a Bitcoin account from a given `Secp256k1::Key` keypay and for the\nspecified network version, e.g., `00` for Bitcoin main network. It creates\na random account if no parameters are supplied.\n\nParameters:\n* `key` (`Secp256k1::Key`): the `Secp256k1` keypair for the account.\n* `version` (`Secp256k1::Num`): the network version indicator.\n\n```\npriv = Secp256k1::Num.new \"18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725\"\nkey = Secp256k1::Key.new priv\naccount = Bitcoin::Account.new key\n# => #,\n# @public_key=#,\n# @y=#>>,\n# @version=#,\n# @address=\"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM\",\n# @address_compressed=\"1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs\",\n# @wif=\"5J1F7GHadZG3sCCKHCwg8Jvys9xUbFsjLnGec4H125Ny1V9nR6V\",\n# @wif_compressed=\"Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C\">\n```","summary":"

      Creates a Bitcoin account from a given Secp256k1::Key keypay and for the specified network version, e.g., 00 for Bitcoin main network.

      ","abstract":false,"args":[{"name":"key","default_value":"Key.new","external_name":"key","restriction":""},{"name":"version","default_value":"Num.new(\"0x00\")","external_name":"version","restriction":""}],"args_string":"(key = Key.new, version = Num.new(\"0x00\"))","args_html":"(key = Key.new, version = Num.new("0x00"))","location":{"filename":"src/bitcoin.cr","line_number":79,"url":null},"def":{"name":"new","args":[{"name":"key","default_value":"Key.new","external_name":"key","restriction":""},{"name":"version","default_value":"Num.new(\"0x00\")","external_name":"version","restriction":""}],"visibility":"Public","body":"_ = allocate\n_.initialize(key, version)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"address:String-instance-method","name":"address","doc":"The public, uncompressed Bitcoin account address.","summary":"

      The public, uncompressed Bitcoin account address.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":35,"url":null},"def":{"name":"address","return_type":"String","visibility":"Public","body":"@address"}},{"html_id":"address_compressed:String-instance-method","name":"address_compressed","doc":"The public, compressed Bitcoin account address.","summary":"

      The public, compressed Bitcoin account address.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":37,"url":null},"def":{"name":"address_compressed","return_type":"String","visibility":"Public","body":"@address_compressed"}},{"html_id":"key:Key-instance-method","name":"key","doc":"The `Secp256k1` keypair for the account.","summary":"

      The Secp256k1 keypair for the account.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":31,"url":null},"def":{"name":"key","return_type":"Key","visibility":"Public","body":"@key"}},{"html_id":"version:Num-instance-method","name":"version","doc":"The network version indicator.","summary":"

      The network version indicator.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":33,"url":null},"def":{"name":"version","return_type":"Num","visibility":"Public","body":"@version"}},{"html_id":"wif:String-instance-method","name":"wif","doc":"The private, uncompressed wallet-import format.","summary":"

      The private, uncompressed wallet-import format.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":39,"url":null},"def":{"name":"wif","return_type":"String","visibility":"Public","body":"@wif"}},{"html_id":"wif_compressed:String-instance-method","name":"wif_compressed","doc":"The private, compressed wallet-import format.","summary":"

      The private, compressed wallet-import format.

      ","abstract":false,"location":{"filename":"src/bitcoin.cr","line_number":41,"url":null},"def":{"name":"wif_compressed","return_type":"String","visibility":"Public","body":"@wif_compressed"}}]}]},{"html_id":"secp256k1/Ethereum","path":"Ethereum.html","kind":"module","full_name":"Ethereum","name":"Ethereum","abstract":false,"locations":[{"filename":"src/ethereum.cr","line_number":15,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false},{"html_id":"secp256k1/Secp256k1","path":"Secp256k1.html","kind":"module","full_name":"Secp256k1","name":"Secp256k1","abstract":false,"locations":[{"filename":"src/secp256k1.cr","line_number":35,"url":null},{"filename":"src/secp256k1/context.cr","line_number":22,"url":null},{"filename":"src/secp256k1/version.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"G","name":"G","value":"Point.new(Num.new(\"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798\"), Num.new(\"483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8\"))","doc":"A commonly used base point `G` with coordinates `x` and `y`\nsatisfying `y^2 = x^3 + 7`.","summary":"

      A commonly used base point G with coordinates x and y satisfying y^2 = x^3 + 7.

      "},{"id":"N","name":"N","value":"Num.new(\"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141\")","doc":"The order `n` of `G` defines the finite size of the Secp256k1 field `E`.","summary":"

      The order n of G defines the finite size of the Secp256k1 field E.

      "},{"id":"P","name":"P","value":"Num.new(\"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f\")","doc":"The elliptic curve domain parameters over `F_p` associated with a\nKoblitz curve `Secp256k1` are specified by the sextuple\n`T = (p, a, b, G, n, h)` where the finite field `F_p` is defined by\nthe prime `p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1`.","summary":"

      The elliptic curve domain parameters over F_p associated with a Koblitz curve Secp256k1 are specified by the sextuple T = (p, a, b, G, n, h) where the finite field F_p is defined by the prime p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1.

      "},{"id":"VERSION","name":"VERSION","value":"\"0.5.0\"","doc":"The `VERSION` of the `Secp256k1` module.","summary":"

      The VERSION of the Secp256k1 module.

      "}],"doc":"Provides the `Secp256k1` module with the elliptic curve parameters\nused by the `Bitcoin`, `Ethereum`, and `Polkadot` blockchains. It's\nprimarily used to generate key-pairs as well as signing messages and\nrecoverying signatures.\n\nRef: [secg.org/sec2-v2.pdf](https://www.secg.org/sec2-v2.pdf)","summary":"

      Provides the Secp256k1 module with the elliptic curve parameters used by the Bitcoin, Ethereum, and Polkadot blockchains.

      ","types":[{"html_id":"secp256k1/Secp256k1/Context","path":"Secp256k1/Context.html","kind":"class","full_name":"Secp256k1::Context","name":"Context","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/context.cr","line_number":22,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a `Secp256k1` context to allow signing arbitrary data,\nrecovering public keys, and verifying signatures.\n\n```\nctx = Context.new\n# => #\n```","summary":"

      Provides a Secp256k1 context to allow signing arbitrary data, recovering public keys, and verifying signatures.

      ","instance_methods":[{"html_id":"sign(key:Key,hash:Num):Signature-instance-method","name":"sign","doc":"Signs a message hash or any other arbitrary data with a given keypair.\n\nParameters:\n* `key` (`Key`): the keypair containing a secret to sign the data.\n* `hash` (`Num`): the message or arbirtrary data hash.\n\nReturns a `Signature` proving the given key signed the message hash.\n\n```\nctx = Context.new\nkey = Key.new Num.new \"1f0c122d41ff536b19bfd83537c0dfc290e45cd3c375a43237c8b8fff7ac8af7\"\nhash = Util.sha256 \"Henlo, Wordl\"\nsig = ctx.sign key, hash\n# => #,\n# @s=#,\n# @v=#>\n```","summary":"

      Signs a message hash or any other arbitrary data with a given keypair.

      ","abstract":false,"args":[{"name":"key","external_name":"key","restriction":"Key"},{"name":"hash","external_name":"hash","restriction":"Num"}],"args_string":"(key : Key, hash : Num) : Signature","args_html":"(key : Key, hash : Num) : Signature","location":{"filename":"src/secp256k1/context.cr","line_number":50,"url":null},"def":{"name":"sign","args":[{"name":"key","external_name":"key","restriction":"Key"},{"name":"hash","external_name":"hash","restriction":"Num"}],"return_type":"Signature","visibility":"Public","body":"k = Util.deterministic_k(key.private_key, hash)\nhash = hash.to_big\npriv = key.private_key.to_big\npoint = Curve.mul(G, k)\nr = point.x.to_big % N.to_big\nk_inv = Curve.mod_inv(k, N)\ns = ((hash + (r * priv)) * k_inv.to_big) % N.to_big\nx_mag = point.x.to_big > N.to_big\ny_parity = (point.y.to_big % 2) == 0\nrec_id : Int8 = -1\nif (!y_parity) && x_mag\n rec_id = 3\nelse\n if y_parity && x_mag\n rec_id = 2\n else\n if (!y_parity) && (!x_mag)\n rec_id = 1\n else\n rec_id = 0\n end\n end\nend\nr = Num.new(r)\ns = Num.new(s)\nv = Num.new(BigInt.new(rec_id))\nSignature.new(r, s, v)\n"}},{"html_id":"verify(sig:Signature,hash:Num,publ:Point):Bool-instance-method","name":"verify","doc":"Verifies that a given signature for a given message hash matches\nthe provided public key.\n\nParameters:\n* `sig` (`Signature`): the signature to be verified.\n* `hash` (`Num`): the message or arbirtrary data hash.\n* `publ` (`Point`): the public key to match.\n\nReturns _true_ if the signature verifies.\n\n```\nctx = Context.new\nr = Num.new \"c4079db44240b7afe94985c69fc89602e33629fd9b8623d711c30ce6378b33df\"\ns = Num.new \"6842c1b63c94bdb8e4f5ae88fb65f7a98b77b197c8323004fb47ef57fab29053\"\nv = Num.new \"00\"\nsig = Signature.new r, s, v\nhash = Util.sha256 \"Henlo, Wordl\"\npubl = Point.new \"0416008a369439f1a8a75cf974860bed5b10180518d6b1dd3ac847f423fd375d6aa29474394f0cd79d2ea543507d069e97339284f01bdbfd27392daec0ec553816\"\nctx.verify sig, hash, publ\n# => true\n```","summary":"

      Verifies that a given signature for a given message hash matches the provided public key.

      ","abstract":false,"args":[{"name":"sig","external_name":"sig","restriction":"Signature"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"publ","external_name":"publ","restriction":"Point"}],"args_string":"(sig : Signature, hash : Num, publ : Point) : Bool","args_html":"(sig : Signature, hash : Num, publ : Point) : Bool","location":{"filename":"src/secp256k1/context.cr","line_number":97,"url":null},"def":{"name":"verify","args":[{"name":"sig","external_name":"sig","restriction":"Signature"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"publ","external_name":"publ","restriction":"Point"}],"return_type":"Bool","visibility":"Public","body":"s_inv = Curve.mod_inv(sig.s, N)\np0 = Curve.mul(G, (hash.to_big * s_inv.to_big) % N.to_big)\np1 = Curve.mul(publ, (sig.r.to_big * s_inv.to_big) % N.to_big)\np = Curve.add(p0, p1)\nsig.r.to_big === p.x.to_big\n"}}]},{"html_id":"secp256k1/Secp256k1/Curve","path":"Secp256k1/Curve.html","kind":"module","full_name":"Secp256k1::Curve","name":"Curve","abstract":false,"locations":[{"filename":"src/secp256k1/curve.cr","line_number":18,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"secp256k1/Secp256k1/Curve","kind":"module","full_name":"Secp256k1::Curve","name":"Curve"}],"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Implements 256-bit `Secp256k1` Koblitz elliptic curve operations.\n\nRef: [secg.org/sec2-v2.pdf](https://www.secg.org/sec2-v2.pdf)","summary":"

      Implements 256-bit Secp256k1 Koblitz elliptic curve operations.

      ","instance_methods":[{"html_id":"add(p:Point,q:Point,prime=P):Point-instance-method","name":"add","doc":"Computes the elliptic curve jive addition of point `p(x, y)` and `q(x, y)`.\nIt _draws_ a line between `p` and `q` which will intersect the\ncurve in the point `r` which will be mirrored over the `x`-axis.\n\nParamters:\n* `p` (`Num`): the point `p(x, y)` to be used in the jive addition.\n* `q` (`Num`): the point `q(x, y)` to be used in the jive addition.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Point` containing the result of the intersection.\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\nq = Point.new Num.new \"7e17f60baa7b8dc8581a55f7be1ea263c6a88452cf3f0a3f710651767654946c\"\nCurve.add p, q\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve jive addition of point p(x, y) and q(x, y).

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"q","external_name":"q","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(p : Point, q : Point, prime = P) : Point","args_html":"(p : Point, q : Point, prime = P) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":82,"url":null},"def":{"name":"add","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"q","external_name":"q","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Point","visibility":"Public","body":"if prime.is_a?(Num)\n prime = prime.to_big\nend\np_x = p.x.to_big\np_y = p.y.to_big\nq_x = q.x.to_big\nq_y = q.y.to_big\nx_delta = q_x - p_x\nx_inv = mod_inv(x_delta)\ny_delta = q_y - p_y\nm = (y_delta * x_inv.to_big) % prime\nx = (((m * m) - p_x) - q_x) % prime\ny = ((m * (p_x - x)) - p_y) % prime\nx = Num.new(x)\ny = Num.new(y)\nPoint.new(x, y)\n"}},{"html_id":"double(p:Point,prime=P):Point-instance-method","name":"double","doc":"Computes the elliptic curve juke point doubling of `p(x, y)`.\nThis is a special case of addition where both points are the same.\nIt _draws_ a tangent line at `p` which will intersect the curve\nat point `r` which will be mirrored over the `x`-axis.\n\nParamters:\n* `p` (`Point`): the point `p(x, y)` to be used in the juke doubling.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Point` as a result of the intersection.\n\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\nCurve.double p\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve juke point doubling of p(x, y).

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(p : Point, prime = P) : Point","args_html":"(p : Point, prime = P) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":123,"url":null},"def":{"name":"double","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Point","visibility":"Public","body":"if prime.is_a?(Num)\n prime = prime.to_big\nend\np_x = p.x.to_big\np_y = p.y.to_big\nlam_numer = (3 * p_x) * p_x\nlam_denom = 2 * p_y\nlam_inv = mod_inv(Num.new(lam_denom))\nlam = (lam_numer * lam_inv.to_big) % prime\nx = ((lam * lam) - (2 * p_x)) % prime\ny = ((lam * (p_x - x)) - p_y) % prime\nx = Num.new(x)\ny = Num.new(y)\nPoint.new(x, y)\n"}},{"html_id":"mod_inv(a:Num|BigInt,prime=P):Num-instance-method","name":"mod_inv","doc":"Computes the elliptic curve modular multiplicative inverse of `a`.\n\nParemeters:\n* `a` (`Num | BigInt`): the integer that we want the modular inverse of.\n* `prime` (`Num`): the prime number that shapes the field (default `P`).\n\nReturns a `Num` containing the mod inverse.\n\n```\na = Num.new \"ea678c668356d16d8bf5c69f95c1055e39bd24174605f64846e27c3ae6a88d81\"\nCurve.mod_inv a\n# => #\n```","summary":"

      Computes the elliptic curve modular multiplicative inverse of a.

      ","abstract":false,"args":[{"name":"a","external_name":"a","restriction":"Num | BigInt"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"args_string":"(a : Num | BigInt, prime = P) : Num","args_html":"(a : Num | BigInt, prime = P) : Num","location":{"filename":"src/secp256k1/curve.cr","line_number":37,"url":null},"def":{"name":"mod_inv","args":[{"name":"a","external_name":"a","restriction":"Num | BigInt"},{"name":"prime","default_value":"P","external_name":"prime","restriction":""}],"return_type":"Num","visibility":"Public","body":"if a.is_a?(Num)\n a = a.to_big\nend\nif prime.is_a?(Num)\n prime = prime.to_big\nend\nm_low = 1\nm_high = 0\nv_low = a % prime\nv_high = prime\nwhile v_low > 1\n v_ratio = v_high // v_low\n m_low_r = m_low * v_ratio\n v_low_r = v_low * v_ratio\n m = m_high - m_low_r\n v = v_high - v_low_r\n m_high = m_low\n v_high = v_low\n m_low = m\n v_low = v\nend\nNum.new(m_low % prime)\n"}},{"html_id":"mul(p:Point,s:Num|BigInt):Point-instance-method","name":"mul","doc":"Computes the elliptic curve sequence multiplication of point `p(x, y)`\nand a skalar `s`; with `s` being a private key within the elliptic\ncurve field size of `N`.\n\nParamters:\n* `p` (`Point`): the point `p(x, y)` to be used in the sequencing.\n* `s` (`Num | BigInt`): a skalar, in most cases a private key.\n\nReturns a `Point` as a result of the multiplication.\n\n```\np = Point.new Num.new \"5cb1eec17e38b004a8fd90fa8e423432430f60d76c30bb33f4091243c029e86d\"\ns = Num.new \"f51ad125548b7a283ebf15ab830a25c850d4d863078c48cc9993b79ee18ee11e\"\nCurve.mul p, s\n# => #,\n# @y=#>\n```","summary":"

      Computes the elliptic curve sequence multiplication of point p(x, y) and a skalar s; with s being a private key within the elliptic curve field size of N.

      ","abstract":false,"args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"s","external_name":"s","restriction":"Num | BigInt"}],"args_string":"(p : Point, s : Num | BigInt) : Point","args_html":"(p : Point, s : Num | BigInt) : Point","location":{"filename":"src/secp256k1/curve.cr","line_number":162,"url":null},"def":{"name":"mul","args":[{"name":"p","external_name":"p","restriction":"Point"},{"name":"s","external_name":"s","restriction":"Num | BigInt"}],"return_type":"Point","visibility":"Public","body":"if s.is_a?(Num)\n s = s.to_big\nend\nif (s === 0) || s >= N.to_big\n raise(\"Invalid scalar: outside of Secp256k1 field dimension.\")\nend\ns_bin = s.to_s(2)\nq = p\ns_bin.each_char_with_index do |char, index|\n if index === 0\n next\n end\n q = double(q)\n if char === '1'\n q = add(q, p)\n end\nend\nq\n"}}]},{"html_id":"secp256k1/Secp256k1/Key","path":"Secp256k1/Key.html","kind":"class","full_name":"Secp256k1::Key","name":"Key","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/key.cr","line_number":21,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a `Secp256k1` keypair containing a secret number (private key)\nand a public point on the elliptic curve (public key).\n\nProperties:\n* `private_key` (`Num`): the secret number representing the private key.\n* `public_key` (`Point`): the point on the elliptic curve representing the public key.","summary":"

      Provides a Secp256k1 keypair containing a secret number (private key) and a public point on the elliptic curve (public key).

      ","constructors":[{"html_id":"new(priv:Num)-class-method","name":"new","doc":"Creates a public-private keypair from an existing private key.\n\nParameters:\n* `priv` (`Num`): the private key for the keypair.\n\n```\npriv = Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\nKey.new priv\n# => #,\n# @public_key=#,\n# @y=#>>\n```","summary":"

      Creates a public-private keypair from an existing private key.

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"args_string":"(priv : Num)","args_html":"(priv : Num)","location":{"filename":"src/secp256k1/key.cr","line_number":74,"url":null},"def":{"name":"new","args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(priv)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new-class-method","name":"new","doc":"Creates a new, random `Secp256k1` keypair.\n\n```\nKey.new\n# => #,\n# @public_key=#,\n# @y=#>>\n```","summary":"

      Creates a new, random Secp256k1 keypair.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":46,"url":null},"def":{"name":"new","visibility":"Public","body":"_ = allocate\n_.initialize\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"private_bytes:Bytes-instance-method","name":"private_bytes","doc":"Returns the private key as binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_bytes\n# => Bytes[60, 207, 132, 130, 12, 32, 213, 232, 197, 54, 186, 132, 197, 43, 164, 16, 55, 91, 41, 177, 129, 43, 95, 126, 114, 36, 69, 201, 105, 160, 251, 48]\n```","summary":"

      Returns the private key as binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":95,"url":null},"def":{"name":"private_bytes","return_type":"Bytes","visibility":"Public","body":"@private_key.to_zpadded_bytes"}},{"html_id":"private_hex:String-instance-method","name":"private_hex","doc":"Returns the private key as hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").private_hex\n# => \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\"\n```","summary":"

      Returns the private key as hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":85,"url":null},"def":{"name":"private_hex","return_type":"String","visibility":"Public","body":"@private_key.to_zpadded_hex"}},{"html_id":"private_key:Num-instance-method","name":"private_key","doc":"The secret number representing the private key.","summary":"

      The secret number representing the private key.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":23,"url":null},"def":{"name":"private_key","return_type":"Num","visibility":"Public","body":"@private_key"}},{"html_id":"public_bytes:Bytes-instance-method","name":"public_bytes","doc":"Returns the public key as uncompressed, binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes\n# => Bytes[4, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162, 129, 54, 61, 41, 142, 74, 64, 235, 203, 19, 241, 175, 168, 90, 11, 148, 185, 103, 242, 67, 238, 89, 165, 144, 16, 203, 93, 234, 240, 215, 182, 108]\n```","summary":"

      Returns the public key as uncompressed, binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":125,"url":null},"def":{"name":"public_bytes","return_type":"Bytes","visibility":"Public","body":"(Num.new(@public_key.uncompressed)).to_bytes"}},{"html_id":"public_bytes_compressed:Bytes-instance-method","name":"public_bytes_compressed","doc":"Returns the public key as compressed, binary byte slice.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_bytes_compressed\n# => Bytes[2, 205, 74, 135, 18, 238, 110, 252, 21, 181, 171, 227, 124, 13, 191, 169, 121, 216, 156, 66, 125, 63, 226, 75, 7, 96, 8, 222, 206, 254, 148, 219, 162]\n```","summary":"

      Returns the public key as compressed, binary byte slice.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":135,"url":null},"def":{"name":"public_bytes_compressed","return_type":"Bytes","visibility":"Public","body":"(Num.new(@public_key.compressed)).to_bytes"}},{"html_id":"public_hex:String-instance-method","name":"public_hex","doc":"Returns the public key as uncompressed, hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex\n# => \"04cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba281363d298e4a40ebcb13f1afa85a0b94b967f243ee59a59010cb5deaf0d7b66c\"\n```","summary":"

      Returns the public key as uncompressed, hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":105,"url":null},"def":{"name":"public_hex","return_type":"String","visibility":"Public","body":"@public_key.uncompressed"}},{"html_id":"public_hex_compressed:String-instance-method","name":"public_hex_compressed","doc":"Returns the public key as compressed, hexadecimal string literal.\n\n```\nKey.new(Num.new \"3ccf84820c20d5e8c536ba84c52ba410375b29b1812b5f7e722445c969a0fb30\").public_hex_compressed\n# => \"02cd4a8712ee6efc15b5abe37c0dbfa979d89c427d3fe24b076008decefe94dba2\"\n```","summary":"

      Returns the public key as compressed, hexadecimal string literal.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":115,"url":null},"def":{"name":"public_hex_compressed","return_type":"String","visibility":"Public","body":"@public_key.compressed"}},{"html_id":"public_key:Point-instance-method","name":"public_key","doc":"The point on the elliptic curve representing the public key.","summary":"

      The point on the elliptic curve representing the public key.

      ","abstract":false,"location":{"filename":"src/secp256k1/key.cr","line_number":25,"url":null},"def":{"name":"public_key","return_type":"Point","visibility":"Public","body":"@public_key"}}]},{"html_id":"secp256k1/Secp256k1/Num","path":"Secp256k1/Num.html","kind":"class","full_name":"Secp256k1::Num","name":"Num","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/num.cr","line_number":25,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a class to conveniently handle big numbers on the elliptic\ncurve. It allows to easily access decimal, hexadecimal, and binary\nrepresentations of the numeric. In addition, it implements some\nutilities such as zpadding or asserting hexadecimal strings. It's suited\nto temporarily handle unencrypted private keys.\n\nProperties:\n* `hex` (`String`): the hexadecimal string representation of the number.\n* `dec` (`BigInt`): the decimal big-integer representation of the number.\n* `bin` (`Bytes`): the binary bytes-slice represenation of the number.","summary":"

      Provides a class to conveniently handle big numbers on the elliptic curve.

      ","constructors":[{"html_id":"new(hex:String)-class-method","name":"new","doc":"Creates a number from a hexadecimal string literal.\n\nParameters:\n* `hex` (`String`): a hexadecimal string representating the number.\n\n```\nNum.new \"568a0f505bde902db4a6afd207c794c7845fe7715da5999bb276d453c702a46d\"\n# => #\n```","summary":"

      Creates a number from a hexadecimal string literal.

      ","abstract":false,"args":[{"name":"hex","external_name":"hex","restriction":"String"}],"args_string":"(hex : String)","args_html":"(hex : String)","location":{"filename":"src/secp256k1/num.cr","line_number":67,"url":null},"def":{"name":"new","args":[{"name":"hex","external_name":"hex","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(hex)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(num:BigInt)-class-method","name":"new","doc":"Creates a number from a big integer numeric.\n\nParameters:\n* `dec` (`BigInt`): the decimal big-integer representating the number.\n\n```\nNum.new BigInt.new \"39142835565766237398843902819171565157710677457569850027793715608438337348717\"\n# => #\n```","summary":"

      Creates a number from a big integer numeric.

      ","abstract":false,"args":[{"name":"num","external_name":"num","restriction":"BigInt"}],"args_string":"(num : BigInt)","args_html":"(num : BigInt)","location":{"filename":"src/secp256k1/num.cr","line_number":87,"url":null},"def":{"name":"new","args":[{"name":"num","external_name":"num","restriction":"BigInt"}],"visibility":"Public","body":"_ = allocate\n_.initialize(num)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(bin:Slice(UInt8))-class-method","name":"new","doc":"Creates a number from a binary bytes slice.\n\nParameters:\n* `bin` (`Bytes`): the binary bytes-slice represenating the number.\n\n```\nNum.new Bytes[86, 138, 15, 80, 91, 222, 144, 45, 180, 166, 175, 210, 7, 199, 148, 199, 132, 95, 231, 113, 93, 165, 153, 155, 178, 118, 212, 83, 199, 2, 164, 109]\n# => #\n```","summary":"

      Creates a number from a binary bytes slice.

      ","abstract":false,"args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"args_string":"(bin : Slice(UInt8))","args_html":"(bin : Slice(UInt8))","location":{"filename":"src/secp256k1/num.cr","line_number":107,"url":null},"def":{"name":"new","args":[{"name":"bin","external_name":"bin","restriction":"Slice(UInt8)"}],"visibility":"Public","body":"_ = allocate\n_.initialize(bin)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new-class-method","name":"new","doc":"Creates a random number using `Random::Secure` that can be used as\na secret (private key).\n\n```\nNum.new\n# => #\n```","summary":"

      Creates a random number using Random::Secure that can be used as a secret (private key).

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":43,"url":null},"def":{"name":"new","visibility":"Public","body":"_ = allocate\n_.initialize\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"bin:Slice(UInt8)-instance-method","name":"bin","doc":"The binary bytes-slice represenation of the number.","summary":"

      The binary bytes-slice represenation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":31,"url":null},"def":{"name":"bin","return_type":"Slice(UInt8)","visibility":"Public","body":"@bin"}},{"html_id":"dec:BigInt-instance-method","name":"dec","doc":"The decimal big-integer representation of the number.","summary":"

      The decimal big-integer representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":29,"url":null},"def":{"name":"dec","return_type":"BigInt","visibility":"Public","body":"@dec"}},{"html_id":"hex:String-instance-method","name":"hex","doc":"The hexadecimal string representation of the number.","summary":"

      The hexadecimal string representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":27,"url":null},"def":{"name":"hex","return_type":"String","visibility":"Public","body":"@hex"}},{"html_id":"to_big:BigInt-instance-method","name":"to_big","doc":"Returns a big-integer representation of the number.\n\n```\nNum.new(Bytes[137]).to_big\n# => 137\n```","summary":"

      Returns a big-integer representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":156,"url":null},"def":{"name":"to_big","return_type":"BigInt","visibility":"Public","body":"@dec"}},{"html_id":"to_bytes:Bytes-instance-method","name":"to_bytes","doc":"Returns a binary byte-slice representation of the number.\n\n```\nNum.new(\"0x89\").to_bytes\n# => Bytes[137]\n```","summary":"

      Returns a binary byte-slice representation of the number.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":166,"url":null},"def":{"name":"to_bytes","return_type":"Bytes","visibility":"Public","body":"@bin"}},{"html_id":"to_hex:String-instance-method","name":"to_hex","doc":"Returns an unprefixed hexadecimal string representation.\n\n```\nNum.new(Bytes[137]).to_hex\n# => \"89\"\n```","summary":"

      Returns an unprefixed hexadecimal string representation.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":119,"url":null},"def":{"name":"to_hex","return_type":"String","visibility":"Public","body":"@hex"}},{"html_id":"to_prefixed_hex:String-instance-method","name":"to_prefixed_hex","doc":"Returns an `0x`-prefixed hexadecimal string representation.\n\n```\nNum.new(Bytes[137]).to_prefixed_hex\n# => \"0x89\"\n```","summary":"

      Returns an 0x-prefixed hexadecimal string representation.

      ","abstract":false,"location":{"filename":"src/secp256k1/num.cr","line_number":129,"url":null},"def":{"name":"to_prefixed_hex","return_type":"String","visibility":"Public","body":"\"0x#{@hex}\""}},{"html_id":"to_zpadded_bytes(length=32):Bytes-instance-method","name":"to_zpadded_bytes","doc":"Returns a z-padded byte-slice binary representation.\n\nParameters:\n* `length` (`Int`): the byte-size of the final z-padded slice (default `32`).\n\n```\nNum.new(Bytes[137]).to_zpadded_bytes\n# => Bytes[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137]\n```","summary":"

      Returns a z-padded byte-slice binary representation.

      ","abstract":false,"args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"args_string":"(length = 32) : Bytes","args_html":"(length = 32) : Bytes","location":{"filename":"src/secp256k1/num.cr","line_number":179,"url":null},"def":{"name":"to_zpadded_bytes","args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"return_type":"Bytes","visibility":"Public","body":"zpadded_bytes = @bin\nwhile zpadded_bytes.size < length\n zpadded_bytes = Util.concat_bytes(Bytes[0], zpadded_bytes)\nend\nzpadded_bytes\n"}},{"html_id":"to_zpadded_hex(length=32):String-instance-method","name":"to_zpadded_hex","doc":"Returns a z-padded hexadecimal string representation.\n\nParameters:\n* `length` (`Int`): the byte-size of the final z-padded hex-string (default `32`).\n\n```\nNum.new(Bytes[137]).to_zpadded_hex\n# => \"0000000000000000000000000000000000000000000000000000000000000089\"\n```","summary":"

      Returns a z-padded hexadecimal string representation.

      ","abstract":false,"args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"args_string":"(length = 32) : String","args_html":"(length = 32) : String","location":{"filename":"src/secp256k1/num.cr","line_number":142,"url":null},"def":{"name":"to_zpadded_hex","args":[{"name":"length","default_value":"32","external_name":"length","restriction":""}],"return_type":"String","visibility":"Public","body":"zpadded_hex = @hex\nwhile zpadded_hex.size < (length * 2)\n zpadded_hex = \"0#{zpadded_hex}\"\nend\nzpadded_hex\n"}}]},{"html_id":"secp256k1/Secp256k1/Point","path":"Secp256k1/Point.html","kind":"class","full_name":"Secp256k1::Point","name":"Point","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/point.cr","line_number":30,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a point in the two-dimensional space of any elliptic curve.\nIn most cases, such a point on a given curve represents a public key.\nHowever, for keypairs, a `Key` type shall be used!\n\nProperties:\n* `x` (`Num`): the position on the x-axis.\n* `y` (`Num`): the position on the y-axis.","summary":"

      Provides a point in the two-dimensional space of any elliptic curve.

      ","constructors":[{"html_id":"new(x:Num,y:Num)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing the x- and y-coordinates (public key).\n\nParameters:\n* `x` (`Num`): the position on the x-axis.\n* `y` (`Num`): the position on the y-axis.\n\n```\nx = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ny = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nPoint.new x, y\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing the x- and y-coordinates (public key).

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Num"},{"name":"y","external_name":"y","restriction":"Num"}],"args_string":"(x : Num, y : Num)","args_html":"(x : Num, y : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":58,"url":null},"def":{"name":"new","args":[{"name":"x","external_name":"x","restriction":"Num"},{"name":"y","external_name":"y","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(x, y)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(priv:Num)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing a random number (private key). Note, that the\nprivate key will be consumed by this constructor and should only be used\nto retrieve a public key. To manage keypairs, use the `Key` type instead.\n\nParameters:\n* `priv` (`Num`): the random number giving access to the point.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new priv\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing a random number (private key).

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"args_string":"(priv : Num)","args_html":"(priv : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":84,"url":null},"def":{"name":"new","args":[{"name":"priv","external_name":"priv","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(priv)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}},{"html_id":"new(pub:String)-class-method","name":"new","doc":"Provides a public point in the two-dimensional space on the given `Secp256k1`\nelliptic curve by passing a compressed or uncompressed public key.\n\nParameters:\n* `pub` (`String`): the public key string (compressed or uncompressed).\n\n```\npub = \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\"\nPoint.new pub\n# => #,\n# @y=#>\n```","summary":"

      Provides a public point in the two-dimensional space on the given Secp256k1 elliptic curve by passing a compressed or uncompressed public key.

      ","abstract":false,"args":[{"name":"pub","external_name":"pub","restriction":"String"}],"args_string":"(pub : String)","args_html":"(pub : String)","location":{"filename":"src/secp256k1/point.cr","line_number":109,"url":null},"def":{"name":"new","args":[{"name":"pub","external_name":"pub","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(pub)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"compressed:String-instance-method","name":"compressed","doc":"Returns a prefixed, compressed public key string for the given point\nin the format `prefix|x|y`.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new(priv).compressed\n# => \"03aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f\"\n```","summary":"

      Returns a prefixed, compressed public key string for the given point in the format prefix|x|y.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":161,"url":null},"def":{"name":"compressed","return_type":"String","visibility":"Public","body":"prefix = 2 + (@y.to_big % 2)\nprefix = \"0#{prefix}\"\n\"#{prefix}#{@x.to_zpadded_hex}\"\n"}},{"html_id":"uncompressed:String-instance-method","name":"uncompressed","doc":"Returns a prefixed, uncompressed public key string for the given point\nin the format `04|x|y`.\n\n```\npriv = Num.new \"e50932676c9901f259659d62f0c56fd899feca3f57ecab147a5ef8a0b59defc3\"\nPoint.new(priv).uncompressed\n# => \"04aff8674d6b96a6c58dbab08b903565363271308888340a2caddf88e56165930f21f4c49cfe90da39c254a51b8ee8afcdd8c02dd566f13582c23e104c7ed5936b\"\n```","summary":"

      Returns a prefixed, uncompressed public key string for the given point in the format 04|x|y.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":148,"url":null},"def":{"name":"uncompressed","return_type":"String","visibility":"Public","body":"prefix = \"04\"\n\"#{prefix}#{@x.to_zpadded_hex}#{@y.to_zpadded_hex}\"\n"}},{"html_id":"x:Num-instance-method","name":"x","doc":"The position on the x-axis.","summary":"

      The position on the x-axis.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":32,"url":null},"def":{"name":"x","return_type":"Num","visibility":"Public","body":"@x"}},{"html_id":"x=(x:Num)-instance-method","name":"x=","doc":"The position on the x-axis.","summary":"

      The position on the x-axis.

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Num"}],"args_string":"(x : Num)","args_html":"(x : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":32,"url":null},"def":{"name":"x=","args":[{"name":"x","external_name":"x","restriction":"Num"}],"visibility":"Public","body":"@x = x"}},{"html_id":"y:Num-instance-method","name":"y","doc":"The position on the y-axis.","summary":"

      The position on the y-axis.

      ","abstract":false,"location":{"filename":"src/secp256k1/point.cr","line_number":35,"url":null},"def":{"name":"y","return_type":"Num","visibility":"Public","body":"@y"}},{"html_id":"y=(y:Num)-instance-method","name":"y=","doc":"The position on the y-axis.","summary":"

      The position on the y-axis.

      ","abstract":false,"args":[{"name":"y","external_name":"y","restriction":"Num"}],"args_string":"(y : Num)","args_html":"(y : Num)","location":{"filename":"src/secp256k1/point.cr","line_number":35,"url":null},"def":{"name":"y=","args":[{"name":"y","external_name":"y","restriction":"Num"}],"visibility":"Public","body":"@y = y"}}]},{"html_id":"secp256k1/Secp256k1/Signature","path":"Secp256k1/Signature.html","kind":"class","full_name":"Secp256k1::Signature","name":"Signature","abstract":false,"superclass":{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"secp256k1/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"secp256k1/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/secp256k1/signature.cr","line_number":22,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides an ECDSA Signature containing the random point `r`, the\nsignature proof `s`, and the recovery id or `v` value.\n\nProperties:\n* `r` (`Num`): the `x` coordinate of a random point `R` on the curve.\n* `s` (`Num`): the signature proof of a message.\n* `v` (`Num`): the recovery id or `v` value.","summary":"

      Provides an ECDSA Signature containing the random point #r, the signature proof #s, and the recovery id or #v value.

      ","constructors":[{"html_id":"new(r:Num,s:Num,v:Num)-class-method","name":"new","doc":"Provides an ECDSA Signature containing the random point `r`, the\nsignature proof `s`, and the recovery id or `v` value.\n\nParameters:\n* `r` (`Num`): the `x` coordinate of a random point `R` on the curve.\n* `s` (`Num`): the signature proof of a message.\n* `v` (`Num`): the recovery id or `v` value.\n\n```\nr = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ns = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nv = Num.new \"00\"\nSignature.new r, s, v\n# => #,\n# @s=#,\n# @v=#>\n```","summary":"

      Provides an ECDSA Signature containing the random point #r, the signature proof #s, and the recovery id or #v value.

      ","abstract":false,"args":[{"name":"r","external_name":"r","restriction":"Num"},{"name":"s","external_name":"s","restriction":"Num"},{"name":"v","external_name":"v","restriction":"Num"}],"args_string":"(r : Num, s : Num, v : Num)","args_html":"(r : Num, s : Num, v : Num)","location":{"filename":"src/secp256k1/signature.cr","line_number":59,"url":null},"def":{"name":"new","args":[{"name":"r","external_name":"r","restriction":"Num"},{"name":"s","external_name":"s","restriction":"Num"},{"name":"v","external_name":"v","restriction":"Num"}],"visibility":"Public","body":"_ = allocate\n_.initialize(r, s, v)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"}}],"instance_methods":[{"html_id":"compact:String-instance-method","name":"compact","doc":"Returns a compact `String` containing the concatenated signature\nin the form `r|s|v`.\n\n```\nr = Num.new \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5\"\ns = Num.new \"cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae0\"\nv = Num.new \"00\"\nSignature.new(r, s, v).compact\n# => \"efc4f8d8bfc778463e4d4916d88bf3f057e6dc96cb2adc26dfb91959c4bef4a5cecd9a83fefafcb3cf99fde0c340bbe2fed9cdd0d25b53f4e08254acefb69ae000\"\n```","summary":"

      Returns a compact String containing the concatenated signature in the form r|s|v.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":75,"url":null},"def":{"name":"compact","return_type":"String","visibility":"Public","body":"\"#{r.to_zpadded_hex}#{s.to_zpadded_hex}#{v.to_hex}\""}},{"html_id":"r:Num-instance-method","name":"r","doc":"The `x` coordinate of a random point `R` on the curve.","summary":"

      The x coordinate of a random point R on the curve.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":24,"url":null},"def":{"name":"r","return_type":"Num","visibility":"Public","body":"@r"}},{"html_id":"s:Num-instance-method","name":"s","doc":"The signature proof of a message.","summary":"

      The signature proof of a message.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":27,"url":null},"def":{"name":"s","return_type":"Num","visibility":"Public","body":"@s"}},{"html_id":"v:Num-instance-method","name":"v","doc":"The recovery id or `v` value.","summary":"

      The recovery id or #v value.

      ","abstract":false,"location":{"filename":"src/secp256k1/signature.cr","line_number":30,"url":null},"def":{"name":"v","return_type":"Num","visibility":"Public","body":"@v"}}]},{"html_id":"secp256k1/Secp256k1/Util","path":"Secp256k1/Util.html","kind":"module","full_name":"Secp256k1::Util","name":"Util","abstract":false,"locations":[{"filename":"src/secp256k1/util.cr","line_number":17,"url":null}],"repository_name":"secp256k1","program":false,"enum":false,"alias":false,"const":false,"extended_modules":[{"html_id":"secp256k1/Secp256k1/Util","kind":"module","full_name":"Secp256k1::Util","name":"Util"}],"namespace":{"html_id":"secp256k1/Secp256k1","kind":"module","full_name":"Secp256k1","name":"Secp256k1"},"doc":"Provides a collection of utilities for convenience, e.g., to bind\nrelevant hashing algorithms, or to concatenate byte slices.","summary":"

      Provides a collection of utilities for convenience, e.g., to bind relevant hashing algorithms, or to concatenate byte slices.

      ","instance_methods":[{"html_id":"concat_bytes(x:Bytes,y:Bytes):Bytes-instance-method","name":"concat_bytes","doc":"Concatenates two byte slices in the order provided, i.e., `x|y`.\n\nParameters:\n* `x` (`Bytes`): a byte slice.\n* `y` (`Bytes`): another byte slice.\n\nReturns a concatenated `Bytes` slice.\n\n```\nUtil.concat_bytes Bytes[1, 2, 3], Bytes[9, 8, 7]\n# => Bytes[1, 2, 3, 9, 8, 7]\n```","summary":"

      Concatenates two byte slices in the order provided, i.e., x|y.

      ","abstract":false,"args":[{"name":"x","external_name":"x","restriction":"Bytes"},{"name":"y","external_name":"y","restriction":"Bytes"}],"args_string":"(x : Bytes, y : Bytes) : Bytes","args_html":"(x : Bytes, y : Bytes) : Bytes","location":{"filename":"src/secp256k1/util.cr","line_number":177,"url":null},"def":{"name":"concat_bytes","args":[{"name":"x","external_name":"x","restriction":"Bytes"},{"name":"y","external_name":"y","restriction":"Bytes"}],"return_type":"Bytes","visibility":"Public","body":"z = IO::Memory.new(x.bytesize + y.bytesize)\nx.each do |b|\n z.write_bytes(UInt8.new(b))\nend\ny.each do |b|\n z.write_bytes(UInt8.new(b))\nend\nreturn z.to_slice\n"}},{"html_id":"deterministic_k(priv:Num,hash:Num,order=N):Num-instance-method","name":"deterministic_k","doc":"Provides a deterministic secret based on private key and message hash\nas defined in RFC-6979.\n\nRef: [datatracker.ietf.org/doc/html/rfc6979](https://datatracker.ietf.org/doc/html/rfc6979)\n\nParameters:\n* `priv` (`Num`): the private key or secret number.\n* `hash` (`Num`): the message hash or arbirtrary data hash.\n* `order` (`Num`): the order of the curve over `G` (default `N`).\n\nReturns a deterministically random number of type `Num`.\n\n```\npriv = Num.new \"3b74fcc0b0c419a00d2d9e88b15fbd99e03920138da22e2a00c327b88d24cf45\"\nhash = Util.sha256 \"Henlo, Wordl\"\nUtil.deterministic_k(priv, hash)\n# => #\n```","summary":"

      Provides a deterministic secret based on private key and message hash as defined in RFC-6979.

      ","abstract":false,"args":[{"name":"priv","external_name":"priv","restriction":"Num"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"order","default_value":"N","external_name":"order","restriction":""}],"args_string":"(priv : Num, hash : Num, order = N) : Num","args_html":"(priv : Num, hash : Num, order = N) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":135,"url":null},"def":{"name":"deterministic_k","args":[{"name":"priv","external_name":"priv","restriction":"Num"},{"name":"hash","external_name":"hash","restriction":"Num"},{"name":"order","default_value":"N","external_name":"order","restriction":""}],"return_type":"Num","visibility":"Public","body":"order_size = order.hex.size // 2\nv = Num.new(Bytes.new(order_size, 1))\nk = Num.new(Bytes.new(order_size, 0))\nconcat = Util.concat_bytes(v.bin, Bytes[0])\nconcat = Util.concat_bytes(concat, priv.bin)\nconcat = Util.concat_bytes(concat, hash.bin)\nk = OpenSSL::HMAC.digest(:sha256, k.bin, concat)\nv = OpenSSL::HMAC.digest(:sha256, k, v.bin)\nconcat = Util.concat_bytes(v, Bytes[0])\nconcat = Util.concat_bytes(concat, priv.bin)\nconcat = Util.concat_bytes(concat, hash.bin)\nk = OpenSSL::HMAC.digest(:sha256, k, concat)\nv = OpenSSL::HMAC.digest(:sha256, k, v)\nwhile true\n t = IO::Memory.new.to_slice\n while t.size < order_size\n v = OpenSSL::HMAC.digest(:sha256, k, v)\n t = Util.concat_bytes(t, v)\n end\n secret = Num.new(t)\n if secret.dec < order.dec && secret.dec > 0\n return secret\n end\n increment = Util.concat_bytes(v, Bytes[0])\n k = OpenSSL::HMAC.digest(:sha256, k, increment)\n v = OpenSSL::HMAC.digest(:sha256, k, v)\nend\n"}},{"html_id":"keccak(data:Num|Bytes|String,entropy=256):Num-instance-method","name":"keccak","doc":"Operating a Keccak hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed.\n* `entropy` (`Int32`): the required entropy (default `256`).\n\nReturns a `Num` representing the Keccak hash.\n\n```\nUtil.keccak(Num.new \"0xdeadbeef\").hex\n# => \"d4fd4e189132273036449fc9e11198c739161b4c0116a9a2dccdfa1c492006f1\"\n\nUtil.keccak(\"0xdeadbeef\").hex\n# => \"4f440a001006a49f24a7de53c04eca3f79aef851ac58e460c9630d044277c8b0\"\n```","summary":"

      Operating a Keccak hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"args_string":"(data : Num | Bytes | String, entropy = 256) : Num","args_html":"(data : Num | Bytes | String, entropy = 256) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":35,"url":null},"def":{"name":"keccak","args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"return_type":"Num","visibility":"Public","body":"keccak = Digest::Keccak3.new(entropy)\nif data.is_a?(Num)\n return Num.new((keccak.update(data.to_bytes)).hexdigest)\nelse\n return Num.new((keccak.update(data)).hexdigest)\nend\n"}},{"html_id":"ripemd160(data:Num|Bytes|String):Num-instance-method","name":"ripemd160","doc":"Operating a RIPEMD-160 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed.\n\nReturns a `Num` representing the RIPEMD hash.\n\n```\nUtil.ripemd160(Num.new \"0xdeadbeef\").hex\n# => \"226821c2f5423e11fe9af68bd285c249db2e4b5a\"\n\nUtil.ripemd160(\"0xdeadbeef\").hex\n# => \"4caf817f14e84b564e47afd19966e5d123ee0183\"\n```","summary":"

      Operating a RIPEMD-160 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"}],"args_string":"(data : Num | Bytes | String) : Num","args_html":"(data : Num | Bytes | String) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":105,"url":null},"def":{"name":"ripemd160","args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"}],"return_type":"Num","visibility":"Public","body":"ripemd = OpenSSL::Digest.new(\"RIPEMD160\")\nif data.is_a?(Num)\n return Num.new((ripemd.update(data.to_bytes)).final.hexstring)\nelse\n return Num.new((ripemd.update(data)).final.hexstring)\nend\n"}},{"html_id":"sha256(data:Num|Bytes|String):Num-instance-method","name":"sha256","doc":"Operating a SHA2-256 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed.\n\nReturns a `Num` representing the SHA2 hash.\n\n```\nUtil.sha256(Num.new \"0xdeadbeef\").hex\n# => \"5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953\"\n\nUtil.sha256(\"0xdeadbeef\").hex\n# => \"4142710b9b4caaeb000b8e5de271bbebac7f509aab2f5e61d1ed1958bfe6d583\"\n```","summary":"

      Operating a SHA2-256 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"}],"args_string":"(data : Num | Bytes | String) : Num","args_html":"(data : Num | Bytes | String) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":82,"url":null},"def":{"name":"sha256","args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"}],"return_type":"Num","visibility":"Public","body":"sha2 = OpenSSL::Digest.new(\"SHA256\")\nif data.is_a?(Num)\n return Num.new((sha2.update(data.to_bytes)).final.hexstring)\nelse\n return Num.new((sha2.update(data)).final.hexstring)\nend\n"}},{"html_id":"sha3(data:Num|Bytes|String,entropy=256):Num-instance-method","name":"sha3","doc":"Operating a SHA3 hash on a binary/number or string literal.\n\nParameters:\n* `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed.\n* `entropy` (`Int32`): the required entropy (default `256`).\n\nReturns a `Num` representing the SHA3 hash.\n\n```\nUtil.sha3(Num.new \"0xdeadbeef\").hex\n# => \"352b82608dad6c7ac3dd665bc2666e5d97803cb13f23a1109e2105e93f42c448\"\n\nUtil.sha3(\"0xdeadbeef\").hex\n# => \"c12811e13ed75afe3e0945ef34e8a25b9d321a46e131c6463731de25a21b39eb\"\n```","summary":"

      Operating a SHA3 hash on a binary/number or string literal.

      ","abstract":false,"args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"args_string":"(data : Num | Bytes | String, entropy = 256) : Num","args_html":"(data : Num | Bytes | String, entropy = 256) : Num","location":{"filename":"src/secp256k1/util.cr","line_number":59,"url":null},"def":{"name":"sha3","args":[{"name":"data","external_name":"data","restriction":"Num | Bytes | String"},{"name":"entropy","default_value":"256","external_name":"entropy","restriction":""}],"return_type":"Num","visibility":"Public","body":"sha3 = Digest::SHA3.new(entropy)\nif data.is_a?(Num)\n return Num.new((sha3.update(data.to_bytes)).hexdigest)\nelse\n return Num.new((sha3.update(data)).hexdigest)\nend\n"}}]}]}]}}) \ No newline at end of file diff --git a/spec/bitcoin_spec.cr b/spec/bitcoin_spec.cr new file mode 100644 index 0000000..9de14b1 --- /dev/null +++ b/spec/bitcoin_spec.cr @@ -0,0 +1,40 @@ +# Copyright 2019-2022 Afr Schoe @q9f +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "./spec_helper" +include Bitcoin + +describe Bitcoin do + it "can generate valid bitcoin addresses" do + prv = Num.new "18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725" + key = Key.new prv + btc = Account.new key + btc.version.hex.should eq "00" + btc.address.should eq "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM" + btc.address_compressed.should eq "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" + btc.wif.should eq "5J1F7GHadZG3sCCKHCwg8Jvys9xUbFsjLnGec4H125Ny1V9nR6V" + btc.wif_compressed.should eq "Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C" + end + + it "can generate valid dogecoin addresses" do + prv = Num.new "8c2b790d6645847fb70cdd7c14404f4c0a59966527c21aa286fc6f6d802e7d18" + key = Key.new prv + btc = Account.new key, Num.new "1e" + btc.version.hex.should eq "1e" + btc.address.should eq "DDh3RAMeWnTWfH6q11uWkF74vMbMxqxa8X" + btc.address_compressed.should eq "DP9Q6DP1GVjUAtcJcaCeR1psedXoC12Jtu" + btc.wif.should eq "6KCMKj71s2X7vT8N8XHgh3CZsbwS5uVUxTEuAFZCNapyZbCbm6L" + btc.wif_compressed.should eq "QTK6heqYoohwYvKWGCgeBii46MDFiegiPkpMDqF7CGJkeVEDqVWg" + end +end diff --git a/spec/ethereum_spec.cr b/spec/ethereum_spec.cr new file mode 100644 index 0000000..8c04fce --- /dev/null +++ b/spec/ethereum_spec.cr @@ -0,0 +1,18 @@ +# Copyright 2019-2022 Afr Schoe @q9f +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "./spec_helper" + +describe Ethereum do +end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 52e3cf7..a987547 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -13,6 +13,8 @@ # limitations under the License. require "spec" +require "../src/bitcoin" +require "../src/ethereum" require "../src/secp256k1" include Secp256k1 diff --git a/src/bitcoin.cr b/src/bitcoin.cr new file mode 100644 index 0000000..faea658 --- /dev/null +++ b/src/bitcoin.cr @@ -0,0 +1,139 @@ +# Copyright 2019-2022 Afr Schoe @q9f +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require "./secp256k1" +include Secp256k1 + +# An example implementation of a `Bitcoin` account using an `Secp256k1` +# key-pair and a Bitcoin network version identifier; only for educational +# purposes and should not be used in production. +module Bitcoin + # The Base-58 alphabet for `Bitcoin` addresses is a Base-64 alphabet without + # `0`, `O`, `I`, and `l` to omit similar-looking letters. + BASE_58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + + # An example implementation of a `Bitcoin` account using an `Secp256k1` + # key-pair and a Bitcoin network version identifier; only for educational + # purposes and should not be used in production. + class Account + # The `Secp256k1` keypair for the account. + getter key : Key + # The network version indicator. + getter version : Num + # The public, uncompressed Bitcoin account address. + getter address : String + # The public, compressed Bitcoin account address. + getter address_compressed : String + # The private, uncompressed wallet-import format. + getter wif : String + # The private, compressed wallet-import format. + getter wif_compressed : String + + # Creates a Bitcoin account from a given `Secp256k1::Key` keypay and for the + # specified network version, e.g., `00` for Bitcoin main network. It creates + # a random account if no parameters are supplied. + # + # Parameters: + # * `key` (`Secp256k1::Key`): the `Secp256k1` keypair for the account. + # * `version` (`Secp256k1::Num`): the network version indicator. + # + # ``` + # priv = Secp256k1::Num.new "18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725" + # key = Secp256k1::Key.new priv + # account = Bitcoin::Account.new key + # # => #, + # # @public_key=#, + # # @y=#>>, + # # @version=#, + # # @address="16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM", + # # @address_compressed="1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs", + # # @wif="5J1F7GHadZG3sCCKHCwg8Jvys9xUbFsjLnGec4H125Ny1V9nR6V", + # # @wif_compressed="Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C"> + # ``` + def initialize(key = Key.new, version = Num.new "0x00") + if version.to_big < 0 || version.to_big > 127 + raise "Invalid version byte provided (out of range: #{version.to_prefixed_hex})" + end + @key = key + @version = version + @address = get_address + @address_compressed = get_address true + @wif = get_wif + @wif_compressed = get_wif true + end + + # Generates the public address for this account. + private def get_address(compressed = false) : String + pub_key = Num.new @key.public_bytes + if compressed + pub_key = Num.new @key.public_bytes_compressed + end + hash_0 = Util.sha256 pub_key.to_zpadded_bytes pub_key.bin.size + hash_1 = Util.ripemd160 hash_0.to_zpadded_bytes + versioned = Util.concat_bytes @version.to_bytes, hash_1.to_zpadded_bytes 20 + hash_2 = Util.sha256 versioned + hash_3 = Util.sha256 hash_2.to_zpadded_bytes + binary = Util.concat_bytes versioned, hash_3.to_zpadded_bytes[0, 4] + encode_base58 Num.new binary + end + + # Generates the private wallet-import format for this account. + private def get_wif(compressed = false) : String + wif_version = Num.new @version.dec + 128 + compression_byte = "" + if compressed + compression_byte = "01" + end + versioned = Num.new "#{wif_version.to_hex}#{@key.private_hex}#{compression_byte}" + hash_0 = Util.sha256 versioned + hash_1 = Util.sha256 hash_0 + binary = Util.concat_bytes versioned.to_bytes, hash_1.to_zpadded_bytes[0, 4] + encode_base58 Num.new binary + end + + # Encode a given numeric with BASE58. + private def encode_base58(num : Num) : String + big = num.to_big + hex = num.to_hex + encoded = String.new + while big > 0 + big, rem = big.divmod 58 + encoded += BASE_58[rem.to_i % 58] + end + i, s = 0, 2 + current_byte = hex[i, s] + while current_byte.to_i(16) === 0 + encoded = "#{encoded}1" + i += s + current_byte = hex[i, s] + end + encoded.reverse + end + end +end diff --git a/src/ethereum.cr b/src/ethereum.cr new file mode 100644 index 0000000..5307bb8 --- /dev/null +++ b/src/ethereum.cr @@ -0,0 +1,16 @@ +# Copyright 2019-2022 Afr Schoe @q9f +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +module Ethereum +end diff --git a/src/secp256k1/key.cr b/src/secp256k1/key.cr index 69cf49b..0126e72 100644 --- a/src/secp256k1/key.cr +++ b/src/secp256k1/key.cr @@ -20,9 +20,9 @@ # * `public_key` (`Point`): the point on the elliptic curve representing the public key. class Secp256k1::Key # The secret number representing the private key. - property private_key : Num + getter private_key : Num # The point on the elliptic curve representing the public key. - property public_key : Point + getter public_key : Point # Creates a new, random `Secp256k1` keypair. # diff --git a/src/secp256k1/num.cr b/src/secp256k1/num.cr index 380ca36..4d2fd4f 100644 --- a/src/secp256k1/num.cr +++ b/src/secp256k1/num.cr @@ -24,11 +24,11 @@ # * `bin` (`Bytes`): the binary bytes-slice represenation of the number. class Secp256k1::Num # The hexadecimal string representation of the number. - property hex : String + getter hex : String # The decimal big-integer representation of the number. - property dec : BigInt + getter dec : BigInt # The binary bytes-slice represenation of the number. - property bin : Slice(UInt8) + getter bin : Slice(UInt8) # Creates a random number using `Random::Secure` that can be used as # a secret (private key). diff --git a/src/secp256k1/signature.cr b/src/secp256k1/signature.cr index 2d3f5fd..12d1445 100644 --- a/src/secp256k1/signature.cr +++ b/src/secp256k1/signature.cr @@ -21,13 +21,13 @@ # * `v` (`Num`): the recovery id or `v` value. class Secp256k1::Signature # The `x` coordinate of a random point `R` on the curve. - property r : Num + getter r : Num # The signature proof of a message. - property s : Num + getter s : Num # The recovery id or `v` value. - property v : Num + getter v : Num # Provides an ECDSA Signature containing the random point `r`, the # signature proof `s`, and the recovery id or `v` value. diff --git a/src/secp256k1/util.cr b/src/secp256k1/util.cr index 973dbe2..ad7655f 100644 --- a/src/secp256k1/util.cr +++ b/src/secp256k1/util.cr @@ -20,7 +20,7 @@ module Secp256k1::Util # Operating a Keccak hash on a binary/number or string literal. # # Parameters: - # * `data` (`Num | String`): the binary numeric or string literal to be hashed. + # * `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed. # * `entropy` (`Int32`): the required entropy (default `256`). # # Returns a `Num` representing the Keccak hash. @@ -32,19 +32,19 @@ module Secp256k1::Util # Util.keccak("0xdeadbeef").hex # # => "4f440a001006a49f24a7de53c04eca3f79aef851ac58e460c9630d044277c8b0" # ``` - def keccak(data : Num | String, entropy = 256) : Num + def keccak(data : Num | Bytes | String, entropy = 256) : Num keccak = Digest::Keccak3.new entropy - if data.is_a? String - return Num.new keccak.update(data).hexdigest - else + if data.is_a? Num return Num.new keccak.update(data.to_bytes).hexdigest + else + return Num.new keccak.update(data).hexdigest end end # Operating a SHA3 hash on a binary/number or string literal. # # Parameters: - # * `data` (`Num | String`): the binary numeric or string literal to be hashed. + # * `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed. # * `entropy` (`Int32`): the required entropy (default `256`). # # Returns a `Num` representing the SHA3 hash. @@ -56,19 +56,19 @@ module Secp256k1::Util # Util.sha3("0xdeadbeef").hex # # => "c12811e13ed75afe3e0945ef34e8a25b9d321a46e131c6463731de25a21b39eb" # ``` - def sha3(data : Num | String, entropy = 256) : Num + def sha3(data : Num | Bytes | String, entropy = 256) : Num sha3 = Digest::SHA3.new entropy - if data.is_a? String - return Num.new sha3.update(data).hexdigest - else + if data.is_a? Num return Num.new sha3.update(data.to_bytes).hexdigest + else + return Num.new sha3.update(data).hexdigest end end # Operating a SHA2-256 hash on a binary/number or string literal. # # Parameters: - # * `data` (`Num | String`): the binary numeric or string literal to be hashed. + # * `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed. # # Returns a `Num` representing the SHA2 hash. # @@ -79,19 +79,19 @@ module Secp256k1::Util # Util.sha256("0xdeadbeef").hex # # => "4142710b9b4caaeb000b8e5de271bbebac7f509aab2f5e61d1ed1958bfe6d583" # ``` - def sha256(data : Num | String) : Num + def sha256(data : Num | Bytes | String) : Num sha2 = OpenSSL::Digest.new "SHA256" - if data.is_a? String - return Num.new sha2.update(data).final.hexstring - else + if data.is_a? Num return Num.new sha2.update(data.to_bytes).final.hexstring + else + return Num.new sha2.update(data).final.hexstring end end # Operating a RIPEMD-160 hash on a binary/number or string literal. # # Parameters: - # * `data` (`Num | String`): the binary numeric or string literal to be hashed. + # * `data` (`Num | Bytes | String`): the binary numeric or string literal to be hashed. # # Returns a `Num` representing the RIPEMD hash. # @@ -102,12 +102,12 @@ module Secp256k1::Util # Util.ripemd160("0xdeadbeef").hex # # => "4caf817f14e84b564e47afd19966e5d123ee0183" # ``` - def ripemd160(data : Num | String) : Num + def ripemd160(data : Num | Bytes | String) : Num ripemd = OpenSSL::Digest.new "RIPEMD160" - if data.is_a? String - return Num.new ripemd.update(data).final.hexstring - else + if data.is_a? Num return Num.new ripemd.update(data.to_bytes).final.hexstring + else + return Num.new ripemd.update(data).final.hexstring end end