schnorr 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.travis.yml +1 -0
 - data/README.md +54 -2
 - data/lib/schnorr.rb +27 -1
 - data/lib/schnorr/mu_sig.rb +84 -0
 - data/lib/schnorr/mu_sig/session.rb +51 -0
 - data/lib/schnorr/version.rb +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: 552fd9baac0e3e4242003e0844c1e5d08dc69f46bf6b605f59293f9793c2c8a1
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 4de25e1831dc171450435256e4e15f5734bfa8da522c57b5ffb90c9d0f1c32f9
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: dcff61f96ee167a43e31fa71b196c118ae8471c949271282c8d0f7b7bee3cc0ce94323d24e70c43619fdd3571f0084e652c1d251e0c07c59deccf63155757085
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 891acabe7a536901ae0209798df11a6f3031dc90e534446ac8982a225ce1ce21c1d011d4e4378942af7cd52c11962082690c4bd51830d604fb0ff31d1a057391
         
     | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -98,9 +98,61 @@ Schnorr.valid_sig?(message, public_key, signature, group: ECDSA::Group::xxx) 
     | 
|
| 
       98 
98 
     | 
    
         | 
| 
       99 
99 
     | 
    
         
             
            Note: But this library has only been tested with `secp256k1`. So another curve are not tested.
         
     | 
| 
       100 
100 
     | 
    
         | 
| 
      
 101 
     | 
    
         
            +
            ### MuSig
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            The MuSig signature scheme is based on the implementation of the 
         
     | 
| 
      
 104 
     | 
    
         
            +
            [secp256k1-zkp](https://github.com/ElementsProject/secp256k1-zkp/blob/secp256k1-zkp/src/modules/musig/musig.md) 
         
     | 
| 
      
 105 
     | 
    
         
            +
            and [bip-schnorr](https://github.com/guggero/bip-schnorr).
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
            Note: In this scheme, this library only supports secp256k1 curve.
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 110 
     | 
    
         
            +
            require 'schnorr'
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            # Key generation
         
     | 
| 
      
 113 
     | 
    
         
            +
            ## First, MuSig participants must compute combined public key.
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
            combined_pubkey = Schnorr::MuSig.pubkey_combine(pubkeys) # pubkeys is an array of public key with binary format.
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            ## combined_pubkey is the point which added the point which performed the following multiplication to each participant's public key.
         
     | 
| 
      
 118 
     | 
    
         
            +
            ## SHA256(TAG || TAG || ell || pubkey index) * Participant's Pubkey Point
         
     | 
| 
      
 119 
     | 
    
         
            +
            ## ell is calculated by SHA256(pubkey1 + pubkey2 + .... pubkeyn) 
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
            ell = Schnorr::MuSig.compute_ell(pubkeys)
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
            # Signing participant
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
            ## the signer create new session
         
     | 
| 
      
 126 
     | 
    
         
            +
            session = Schnorr::MuSig.session_initialize(nil, private_key, message, combined_pubkey, ell, index) # index = 0
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            ## each participant use same session id
         
     | 
| 
      
 129 
     | 
    
         
            +
            session_id = session.id
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            ## each participant create own session.
         
     | 
| 
      
 132 
     | 
    
         
            +
            session = Schnorr::MuSig.session_initialize(session_id, private_key, message, combined_pubkey, ell, index)
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
            ## participant send his nonce and collect other participant's nonce.
         
     | 
| 
      
 135 
     | 
    
         
            +
            session.nonce
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            other_nonces = [...]
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
            ## If collect all participant's nonce, then calculate combined nonce.
         
     | 
| 
      
 140 
     | 
    
         
            +
            ## In this method, if jacobi(y(combined_point)) != 1, 
         
     | 
| 
      
 141 
     | 
    
         
            +
            ## combined_point changed to combined_point.negate and session#nonce_negate changed to true.
         
     | 
| 
      
 142 
     | 
    
         
            +
            combined_nonce = session.nonce_combine(other_nonces)
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
            ## each participants create partial signature
         
     | 
| 
      
 145 
     | 
    
         
            +
            partial_sig = session.partial_sign(message, combined_nonce, combined_pubkey)
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
            ## Aggregate signature.
         
     | 
| 
      
 148 
     | 
    
         
            +
            signature = Schnorr::MuSig.partial_sig_combine(combined_nonce, signatures)
         
     | 
| 
      
 149 
     | 
    
         
            +
             
         
     | 
| 
      
 150 
     | 
    
         
            +
            ## Verify. If signature is valid, following method will return true.
         
     | 
| 
      
 151 
     | 
    
         
            +
            Schnorr.valid_sig?(message, combined_pubkey, signature.encode) 
         
     | 
| 
      
 152 
     | 
    
         
            +
            ```
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
       101 
154 
     | 
    
         
             
            ## TODO
         
     | 
| 
       102 
155 
     | 
    
         | 
| 
       103 
156 
     | 
    
         
             
            The following is unimplemented now.
         
     | 
| 
       104 
157 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
            *  
     | 
| 
       106 
     | 
    
         
            -
            * MuSig
         
     | 
| 
      
 158 
     | 
    
         
            +
            * (t, n) threshold signature.
         
     | 
    
        data/lib/schnorr.rb
    CHANGED
    
    | 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'ecdsa'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'securerandom'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require_relative 'schnorr/signature'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'schnorr/mu_sig'
         
     | 
| 
       4 
5 
     | 
    
         | 
| 
       5 
6 
     | 
    
         
             
            module Schnorr
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
         @@ -115,6 +116,31 @@ module Schnorr 
     | 
|
| 
       115 
116 
     | 
    
         
             
                field.mod(ECDSA.normalize_digest(Digest::SHA256.digest(r + public_key + message), group.bit_length))
         
     | 
| 
       116 
117 
     | 
    
         
             
              end
         
     | 
| 
       117 
118 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
               
     | 
| 
      
 119 
     | 
    
         
            +
              class ::Integer
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                def to_hex
         
     | 
| 
      
 122 
     | 
    
         
            +
                  hex = to_s(16)
         
     | 
| 
      
 123 
     | 
    
         
            +
                  hex.rjust((hex.length / 2.0).ceil * 2, '0')
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                def method_missing(method, *args)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  return mod_pow(args[0], args[1]) if method == :pow && args.length < 3
         
     | 
| 
      
 128 
     | 
    
         
            +
                  super
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                # alternative implementation of Integer#pow for ruby 2.4 and earlier.
         
     | 
| 
      
 132 
     | 
    
         
            +
                def mod_pow(x, y)
         
     | 
| 
      
 133 
     | 
    
         
            +
                  return self ** x unless y
         
     | 
| 
      
 134 
     | 
    
         
            +
                  b = self
         
     | 
| 
      
 135 
     | 
    
         
            +
                  result = 1
         
     | 
| 
      
 136 
     | 
    
         
            +
                  while x > 0
         
     | 
| 
      
 137 
     | 
    
         
            +
                    result = (result * b) % y if (x & 1) == 1
         
     | 
| 
      
 138 
     | 
    
         
            +
                    x >>= 1
         
     | 
| 
      
 139 
     | 
    
         
            +
                    b = (b * b) % y
         
     | 
| 
      
 140 
     | 
    
         
            +
                  end
         
     | 
| 
      
 141 
     | 
    
         
            +
                  result
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
              end
         
     | 
| 
       119 
145 
     | 
    
         | 
| 
       120 
146 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,84 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'mu_sig/session'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Schnorr
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              # https://github.com/ElementsProject/secp256k1-zkp/blob/secp256k1-zkp/src/modules/musig/musig.md
         
     | 
| 
      
 6 
     | 
    
         
            +
              module MuSig
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                # SHA256("MuSig coefficient")
         
     | 
| 
      
 9 
     | 
    
         
            +
                TAG = ['74894a2bec01af68225002cae9b0430ab63151ede5d31f641791976c7140b57b'].pack('H*')
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                module_function
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                # Computes ell = SHA256(pk[0], ..., pk[np-1])
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @param public_keys (Array[String]) The set of public keys with binary format.
         
     | 
| 
      
 15 
     | 
    
         
            +
                # @return (String) ell
         
     | 
| 
      
 16 
     | 
    
         
            +
                def compute_ell(public_keys)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  Digest::SHA256.digest(public_keys.join)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                # Combine public keys.
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @param public_keys (Array[String]) The set of public keys with binary format.
         
     | 
| 
      
 22 
     | 
    
         
            +
                # @return (String) a combined public key point with binary format.
         
     | 
| 
      
 23 
     | 
    
         
            +
                def pubkey_combine(public_keys, ell: nil)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  ell = compute_ell(public_keys) unless ell
         
     | 
| 
      
 25 
     | 
    
         
            +
                  points = public_keys.map.with_index do |p, idx|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    xi = ECDSA::Format::PointOctetString.decode(p, ECDSA::Group::Secp256k1)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    xi.multiply_by_scalar(coefficient(ell, idx))
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  sum = points.inject(:+)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  ECDSA::Format::PointOctetString.encode(sum, compression: true)
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                # Computes MuSig coefficient SHA256(TAG || TAG || ++ell++ || ++idx++).
         
     | 
| 
      
 34 
     | 
    
         
            +
                # @param ell (String) a ell with binary format.
         
     | 
| 
      
 35 
     | 
    
         
            +
                # @param idx (Integer) an index of public key.
         
     | 
| 
      
 36 
     | 
    
         
            +
                # @return (Integer) coefficient value.
         
     | 
| 
      
 37 
     | 
    
         
            +
                def coefficient(ell, idx)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  field = ECDSA::PrimeField.new(ECDSA::Group::Secp256k1.order)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  field.mod(Digest::SHA256.digest(TAG + TAG + ell + [idx].pack('I*')).unpack('H*').first.to_i(16))
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                # Initialize session to signer starts the session.
         
     | 
| 
      
 43 
     | 
    
         
            +
                # @param session_id (String) if ++session_id++ is nil, generate new one.
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @param private_key (Integer) a private key.
         
     | 
| 
      
 45 
     | 
    
         
            +
                # @param message (String) a message for sign with binary format.
         
     | 
| 
      
 46 
     | 
    
         
            +
                # @param combined_pubkey (String) combined public key with binary format.
         
     | 
| 
      
 47 
     | 
    
         
            +
                # @param ell (String) ell with binary format.
         
     | 
| 
      
 48 
     | 
    
         
            +
                # @param index (Integer) public key index.
         
     | 
| 
      
 49 
     | 
    
         
            +
                # @return (Schnorr::MuSig::Session) session object.
         
     | 
| 
      
 50 
     | 
    
         
            +
                def session_initialize(session_id, private_key, message, combined_pubkey, ell, index)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  raise ArgumentError, 'session_id must be 32 bytes.' if session_id && session_id.bytesize != 32
         
     | 
| 
      
 52 
     | 
    
         
            +
                  raise ArgumentError, 'message must be 32 bytes.' unless message.bytesize == 32
         
     | 
| 
      
 53 
     | 
    
         
            +
                  raise ArgumentError, 'combined_pubkey must be 33 bytes.' unless combined_pubkey.bytesize == 33
         
     | 
| 
      
 54 
     | 
    
         
            +
                  raise ArgumentError, 'ell must be 32 bytes.' unless ell.bytesize == 32
         
     | 
| 
      
 55 
     | 
    
         
            +
                  secret = ECDSA::Format::IntegerOctetString.encode(private_key, ECDSA::Group::Secp256k1.byte_length)
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  field = ECDSA::PrimeField.new(ECDSA::Group::Secp256k1.order)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  session = Schnorr::MuSig::Session.new(session_id)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  coefficient = coefficient(ell, index)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  session.secret_key = field.mod(private_key * coefficient)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  session.secret_nonce = Digest::SHA256.digest(session.id + message + combined_pubkey + secret).unpack('H*').first.to_i(16)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  raise ArgumentError, 'secret nonce must be an integer in the ragen 1..n-1' unless field.include?(session.secret_nonce)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  point_r = ECDSA::Group::Secp256k1.new_point(session.secret_nonce)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  session.nonce = ECDSA::Format::PointOctetString.encode(point_r, compression: true)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  session.commitment = Digest::SHA256.digest(session.nonce)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  session
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                # Combine the partial signatures to obtain a complete signature.
         
     | 
| 
      
 70 
     | 
    
         
            +
                # @param combined_nonce (Array)
         
     | 
| 
      
 71 
     | 
    
         
            +
                # @param signatures (Array) co-signer's signature.
         
     | 
| 
      
 72 
     | 
    
         
            +
                # @return (Schnorr::Signature) a combined signature.
         
     | 
| 
      
 73 
     | 
    
         
            +
                def partial_sig_combine(combined_nonce, signatures)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  point_r = ECDSA::Format::PointOctetString.decode(combined_nonce, ECDSA::Group::Secp256k1)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  field = ECDSA::PrimeField.new(ECDSA::Group::Secp256k1.order)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  signature = signatures.inject{|sum, s|field.mod(sum + s)}
         
     | 
| 
      
 77 
     | 
    
         
            +
                  Schnorr::Signature.new(point_r.x, signature)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                private_class_method :coefficient
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Schnorr
         
     | 
| 
      
 2 
     | 
    
         
            +
              module MuSig
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Session
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :id               # binary
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_accessor :secret_key     # Integer
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_accessor :secret_nonce   # Integer
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_accessor :nonce          # binary
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_accessor :commitment     # binary
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_accessor :nonce_negate   # Boolean
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def initialize(session_id = SecureRandom.random_bytes(32))
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @id = session_id
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @nonce_negate = false
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def nonce_negate?
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @nonce_negate
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  # Combine nonce
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # @param nonces (Array[String]) an array of other signer's nonce with binary format.
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # @return (String) combined nonce with binary format.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  def nonce_combine(nonces)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    points = ([nonce]+ nonces).map.with_index {|n, index|ECDSA::Format::PointOctetString.decode(n, ECDSA::Group::Secp256k1)}
         
     | 
| 
      
 26 
     | 
    
         
            +
                    r_point = points.inject(:+)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    unless ECDSA::PrimeField.jacobi(r_point.y, ECDSA::Group::Secp256k1.field.prime) == 1
         
     | 
| 
      
 28 
     | 
    
         
            +
                      self.nonce_negate = true
         
     | 
| 
      
 29 
     | 
    
         
            +
                      r_point = r_point.negate
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                    ECDSA::Format::PointOctetString.encode(r_point, compression: true)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  # Compute partial signature.
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # @param message (String) a message for signature with binary format.
         
     | 
| 
      
 36 
     | 
    
         
            +
                  # @param combined_nonce (String) combined nonce with binary format.
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # @param combined_pubkey (String) combined public key with binary format.
         
     | 
| 
      
 38 
     | 
    
         
            +
                  # @return (Integer) a partial signature.
         
     | 
| 
      
 39 
     | 
    
         
            +
                  def partial_sign(message, combined_nonce, combined_pubkey)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    field = ECDSA::PrimeField.new(ECDSA::Group::Secp256k1.order)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    point_r = ECDSA::Format::PointOctetString.decode(combined_nonce, ECDSA::Group::Secp256k1)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    point_p = ECDSA::Format::PointOctetString.decode(combined_pubkey, ECDSA::Group::Secp256k1)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    e = Schnorr.create_challenge(point_r.x, point_p, message, field, point_r.group)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    k = secret_nonce
         
     | 
| 
      
 45 
     | 
    
         
            +
                    k = 0 - k if nonce_negate?
         
     | 
| 
      
 46 
     | 
    
         
            +
                    field.mod(secret_key * e + k)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/schnorr/version.rb
    CHANGED
    
    
    
        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.3.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-04- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2019-04-09 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: ecdsa
         
     | 
| 
         @@ -86,6 +86,8 @@ files: 
     | 
|
| 
       86 
86 
     | 
    
         
             
            - bin/console
         
     | 
| 
       87 
87 
     | 
    
         
             
            - bin/setup
         
     | 
| 
       88 
88 
     | 
    
         
             
            - lib/schnorr.rb
         
     | 
| 
      
 89 
     | 
    
         
            +
            - lib/schnorr/mu_sig.rb
         
     | 
| 
      
 90 
     | 
    
         
            +
            - lib/schnorr/mu_sig/session.rb
         
     | 
| 
       89 
91 
     | 
    
         
             
            - lib/schnorr/signature.rb
         
     | 
| 
       90 
92 
     | 
    
         
             
            - lib/schnorr/version.rb
         
     | 
| 
       91 
93 
     | 
    
         
             
            - schnorrrb.gemspec
         
     | 
| 
         @@ -108,8 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       108 
110 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       109 
111 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       110 
112 
     | 
    
         
             
            requirements: []
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
            rubygems_version: 2.7.8
         
     | 
| 
      
 113 
     | 
    
         
            +
            rubygems_version: 3.0.3
         
     | 
| 
       113 
114 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       114 
115 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       115 
116 
     | 
    
         
             
            summary: The ruby implementation of Schnorr signature.
         
     |