schnorr 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -1
- data/lib/schnorr/version.rb +1 -1
- data/lib/schnorr.rb +43 -1
- data/schnorrrb.gemspec +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27c028f23478e028b813e4bf12bbb1bd6b9f92b75d758554c71e298b0f3a9077
|
4
|
+
data.tar.gz: 2943cdc9afc73fecc8804b6c498ef0f55a850a63b71422ecf716c0d3b496e164
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94e5c230cbda7f0fa66a30da0f3a62d2950aaf42b34e2c0d24980f65616d0c31b5b289eac48eaf717fd3052d3ea57d8664d373bec16298c36611c38d51162804
|
7
|
+
data.tar.gz: f83ad1edee227ee190495ae58743dc461ca1e0753925ad3c01fe6d68ab92bf02b8e4d00c3043fdb1eb2f2bd568791e0f80b3615d478c6c99f66565a72090eddf
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Schnorrrb [![Build Status](https://travis-ci.org/chaintope/schnorrrb.svg?branch=master)](https://travis-ci.org/chaintope/schnorrrb) [![Gem Version](https://badge.fury.io/rb/
|
1
|
+
# Schnorrrb [![Build Status](https://travis-ci.org/chaintope/schnorrrb.svg?branch=master)](https://travis-ci.org/chaintope/schnorrrb) [![Gem Version](https://badge.fury.io/rb/schnorr.svg)](https://badge.fury.io/rb/schnorr) [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
|
2
2
|
|
3
3
|
This is a Ruby implementation of the Schnorr signature scheme over the elliptic curve.
|
4
4
|
This implementation relies on the [ecdsa gem](https://github.com/DavidEGrayson/ruby_ecdsa) for operate elliptic curves.
|
@@ -65,6 +65,27 @@ result = Schnorr.valid_sig?(message, public_key, signature)
|
|
65
65
|
sig = Schnorr::Signature.decode(signature)
|
66
66
|
```
|
67
67
|
|
68
|
+
### Batch verification
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
require 'schnorr'
|
72
|
+
|
73
|
+
pubkeys = ['03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B'].pack('H*')
|
74
|
+
pubkeys << ['02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659'].pack('H*')
|
75
|
+
...
|
76
|
+
|
77
|
+
messages = ['5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C'].pack('H*')
|
78
|
+
messages << ['243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89'].pack('H*')
|
79
|
+
...
|
80
|
+
|
81
|
+
signatures = [`00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380`].pack('H*')
|
82
|
+
signatures << [`787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF68FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C`].pack('H*')
|
83
|
+
...
|
84
|
+
|
85
|
+
# batch verify signature.(result is true or false)
|
86
|
+
result = Schnorr.valid_sig?(messages, pubkeys, signatures)
|
87
|
+
```
|
88
|
+
|
68
89
|
### Change elliptic curve
|
69
90
|
|
70
91
|
This library use `secp256k1` curve as default. If you use another curve, you need to specify curve as following:
|
data/lib/schnorr/version.rb
CHANGED
data/lib/schnorr.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ecdsa'
|
2
|
+
require 'securerandom'
|
2
3
|
require_relative 'schnorr/signature'
|
3
4
|
|
4
5
|
module Schnorr
|
@@ -39,6 +40,48 @@ module Schnorr
|
|
39
40
|
false
|
40
41
|
end
|
41
42
|
|
43
|
+
# Batch verification
|
44
|
+
# @param messages (Array[String]) The array of message with binary format.
|
45
|
+
# @param public_keys (Array[String]) The array of public key with binary format.
|
46
|
+
# @param signatures (Array[String]) The array of signatures with binary format.
|
47
|
+
# @param group (ECDSA::Group) The curve that is being used.
|
48
|
+
# @return (Boolean) whether signature is valid.
|
49
|
+
def valid_sigs?(messages, public_keys, signatures, group: ECDSA::Group::Secp256k1)
|
50
|
+
raise ArgumentError, 'all parameters must be an array with the same length.' if messages.size != public_keys.size || public_keys.size != signatures.size
|
51
|
+
field = group.field
|
52
|
+
pubkeys = public_keys.map{|p| ECDSA::Format::PointOctetString.decode(p, group)}
|
53
|
+
sigs = signatures.map do|signature|
|
54
|
+
sig = Schnorr::Signature.decode(signature)
|
55
|
+
raise Schnorr::InvalidSignatureError, 'Invalid signature: r is not in the field.' unless field.include?(sig.r)
|
56
|
+
raise Schnorr::InvalidSignatureError, 'Invalid signature: s is not in the field.' unless field.include?(sig.s)
|
57
|
+
raise Schnorr::InvalidSignatureError, 'Invalid signature: r is zero.' if sig.r.zero?
|
58
|
+
raise Schnorr::InvalidSignatureError, 'Invalid signature: s is zero.' if sig.s.zero?
|
59
|
+
sig
|
60
|
+
end
|
61
|
+
left = 0
|
62
|
+
right = nil
|
63
|
+
pubkeys.each_with_index do |pubkey, i|
|
64
|
+
r = sigs[i].r
|
65
|
+
s = sigs[i].s
|
66
|
+
e = create_challenge(r, pubkey, messages[i], field, group)
|
67
|
+
c = field.mod(r.pow(3) + 7)
|
68
|
+
y = c.pow((field.prime + 1)/4, field.prime)
|
69
|
+
raise Schnorr::InvalidSignatureError, 'c is not equal to y^2.' unless c == y.pow(2, field.prime)
|
70
|
+
r_point = ECDSA::Point.new(group, r, y)
|
71
|
+
if i == 0
|
72
|
+
left = s
|
73
|
+
right = r_point + pubkey.multiply_by_scalar(e)
|
74
|
+
else
|
75
|
+
a = 1 + SecureRandom.random_number(group.order - 1)
|
76
|
+
left += (a * s)
|
77
|
+
right += (r_point.multiply_by_scalar(a) + pubkey.multiply_by_scalar(a * e))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
group.new_point(left) == right
|
81
|
+
rescue InvalidSignatureError, ECDSA::Format::DecodeError
|
82
|
+
false
|
83
|
+
end
|
84
|
+
|
42
85
|
# Verifies the given {Signature} and raises an {InvalidSignatureError} if it is invalid.
|
43
86
|
# @param message (String) A message to be signed with binary format.
|
44
87
|
# @param public_key (String) The public key with binary format.
|
@@ -59,7 +102,6 @@ module Schnorr
|
|
59
102
|
|
60
103
|
r = group.new_point(sig.s) + pubkey.multiply_by_scalar(e).negate
|
61
104
|
|
62
|
-
|
63
105
|
if r.infinity? || ECDSA::PrimeField.jacobi(r.y, group.field.prime) != 1 || r.x != sig.r
|
64
106
|
raise Schnorr::InvalidSignatureError, 'signature verification failed.'
|
65
107
|
end
|
data/schnorrrb.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "schnorr"
|
8
8
|
spec.version = Schnorr::VERSION
|
9
9
|
spec.authors = ["azuchi"]
|
10
|
-
spec.email = ["azuchi@
|
10
|
+
spec.email = ["azuchi@chaintope.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{The ruby implementation of Schnorr signature.}
|
13
13
|
spec.description = %q{The ruby implementation of Schnorr signature.}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schnorr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ecdsa
|
@@ -68,7 +68,7 @@ dependencies:
|
|
68
68
|
version: '3.0'
|
69
69
|
description: The ruby implementation of Schnorr signature.
|
70
70
|
email:
|
71
|
-
- azuchi@
|
71
|
+
- azuchi@chaintope.com
|
72
72
|
executables: []
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
@@ -108,7 +108,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0'
|
110
110
|
requirements: []
|
111
|
-
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.7.8
|
112
113
|
signing_key:
|
113
114
|
specification_version: 4
|
114
115
|
summary: The ruby implementation of Schnorr signature.
|