Rebrand to Tutus - update license, workflows, and dependencies

This commit is contained in:
Tutus Development 2025-12-27 15:45:25 +00:00
parent 6724b49798
commit 24720bf5a6
10 changed files with 469 additions and 469 deletions

View File

@ -1,9 +1,9 @@
name: DCO check name: DCO check
on: on:
pull_request: pull_request:
branches: [ "master" ] branches: [ "master" ]
jobs: jobs:
dco: dco:
uses: nspcc-dev/.github/.github/workflows/dco.yml@master uses: nspcc-dev/.github/.github/workflows/dco.yml@master

View File

@ -1,116 +1,116 @@
name: Tests name: Tests
on: on:
pull_request: pull_request:
branches: branches:
- master - master
types: [ opened, synchronize ] types: [ opened, synchronize ]
workflow_dispatch: workflow_dispatch:
jobs: jobs:
lint: lint:
name: Lint name: Lint
uses: nspcc-dev/.github/.github/workflows/go-linter.yml@master uses: nspcc-dev/.github/.github/workflows/go-linter.yml@master
test_cover: test_cover:
name: Coverage name: Coverage
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
CGO_ENABLED: 0 CGO_ENABLED: 0
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '1.25' go-version: '1.25'
cache: true cache: true
- name: Write coverage profile - name: Write coverage profile
run: go test ./... -coverprofile=./coverage.txt -covermode=atomic run: go test ./... -coverprofile=./coverage.txt -covermode=atomic
- name: Upload coverage results to Codecov - name: Upload coverage results to Codecov
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v4
with: with:
fail_ci_if_error: false fail_ci_if_error: false
slug: nspcc-dev/rfc6979 slug: nspcc-dev/rfc6979
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.txt files: ./coverage.txt
verbose: true verbose: true
tests: tests:
name: Run tests name: Run tests
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ] os: [ ubuntu-latest, windows-latest, macos-latest ]
go_versions: [ '1.24', '1.25' ] go_versions: [ '1.24', '1.25' ]
exclude: exclude:
- os: macos-latest - os: macos-latest
go_versions: '1.24' go_versions: '1.24'
- os: windows-latest - os: windows-latest
go_versions: '1.24' go_versions: '1.24'
- os: ubuntu-latest - os: ubuntu-latest
go_versions: '1.25' go_versions: '1.25'
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: '${{ matrix.go_versions }}' go-version: '${{ matrix.go_versions }}'
cache: true cache: true
- name: Run tests - name: Run tests
run: go test -race ./... run: go test -race ./...
codeql: codeql:
name: CodeQL name: CodeQL
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: [ 'go' ] language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more: # Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file. # By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file. # Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main # queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v2 uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project # and modify them (or add more) to build your code if your project
# uses a compiled language # uses a compiled language
#- run: | #- run: |
# make bootstrap # make bootstrap
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v2

46
.gitignore vendored
View File

@ -1,23 +1,23 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects) # Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o *.o
*.a *.a
*.so *.so
# Folders # Folders
_obj _obj
_test _test
# Architecture specific extensions/prefixes # Architecture specific extensions/prefixes
*.[568vq] *.[568vq]
[568vq].out [568vq].out
*.cgo1.go *.cgo1.go
*.cgo2.c *.cgo2.c
_cgo_defun.c _cgo_defun.c
_cgo_gotypes.go _cgo_gotypes.go
_cgo_export.* _cgo_export.*
_testmain.go _testmain.go
*.exe *.exe
.golangci.yml .golangci.yml

View File

@ -1,4 +1,4 @@
language: go language: go
go: go:
- 1.12.x - 1.12.x
- 1.13.x - 1.13.x

42
LICENSE
View File

@ -1,21 +1,21 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2014 Coda Hale Copyright (c) 2014 Coda Hale
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.

84
dsa.go
View File

@ -1,42 +1,42 @@
package rfc6979 package rfc6979
import ( import (
"crypto/dsa" //nolint:staticcheck "crypto/dsa" //nolint:staticcheck
"hash" "hash"
"math/big" "math/big"
) )
// SignDSA signs an arbitrary length hash (which should be the result of hashing // SignDSA signs an arbitrary length hash (which should be the result of hashing
// a larger message) using the private key, priv. It returns the signature as a // a larger message) using the private key, priv. It returns the signature as a
// pair of integers. // pair of integers.
// //
// Deprecated: crypto/dsa package is deprecated in Go, so please swtich to ECDSA. // Deprecated: crypto/dsa package is deprecated in Go, so please swtich to ECDSA.
// This method can be removed in future versions. // This method can be removed in future versions.
func SignDSA(priv *dsa.PrivateKey, hash []byte, alg func() hash.Hash) (r, s *big.Int, err error) { func SignDSA(priv *dsa.PrivateKey, hash []byte, alg func() hash.Hash) (r, s *big.Int, err error) {
n := priv.Q.BitLen() n := priv.Q.BitLen()
if n&7 != 0 { if n&7 != 0 {
err = dsa.ErrInvalidPublicKey err = dsa.ErrInvalidPublicKey
return return
} }
generateSecret(priv.Q, priv.X, alg, hash, func(k *big.Int, z *big.Int, _ []byte) bool { generateSecret(priv.Q, priv.X, alg, hash, func(k *big.Int, z *big.Int, _ []byte) bool {
r = new(big.Int).Exp(priv.G, k, priv.P) r = new(big.Int).Exp(priv.G, k, priv.P)
r.Mod(r, priv.Q) r.Mod(r, priv.Q)
if r.Sign() == 0 { if r.Sign() == 0 {
return false return false
} }
inv := k.ModInverse(k, priv.Q) inv := k.ModInverse(k, priv.Q)
s = new(big.Int).Mul(priv.X, r) s = new(big.Int).Mul(priv.X, r)
s.Add(s, z) s.Add(s, z)
s.Mod(s, priv.Q) s.Mod(s, priv.Q)
s.Mul(s, inv) s.Mul(s, inv)
s.Mod(s, priv.Q) s.Mod(s, priv.Q)
return s.Sign() != 0 return s.Sign() != 0
}) })
return return
} }

View File

@ -1,38 +1,38 @@
package rfc6979 package rfc6979
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"hash" "hash"
"math/big" "math/big"
) )
// SignECDSA signs an arbitrary length hash (which should be the result of // SignECDSA signs an arbitrary length hash (which should be the result of
// hashing a larger message) using the private key, priv. It returns the // hashing a larger message) using the private key, priv. It returns the
// signature as a pair of integers. // signature as a pair of integers.
// //
// Will panic if invalid private key (>N for the curve) is passed. // Will panic if invalid private key (>N for the curve) is passed.
func SignECDSA(priv *ecdsa.PrivateKey, hash []byte, alg func() hash.Hash) (r, s *big.Int) { func SignECDSA(priv *ecdsa.PrivateKey, hash []byte, alg func() hash.Hash) (r, s *big.Int) {
c := priv.Curve c := priv.Curve
N := c.Params().N N := c.Params().N
generateSecret(N, priv.D, alg, hash, func(k *big.Int, e *big.Int, t []byte) bool { generateSecret(N, priv.D, alg, hash, func(k *big.Int, e *big.Int, t []byte) bool {
k.FillBytes(t) k.FillBytes(t)
r, _ = priv.ScalarBaseMult(t) r, _ = priv.ScalarBaseMult(t)
r.Mod(r, N) r.Mod(r, N)
if r.Sign() == 0 { if r.Sign() == 0 {
return false return false
} }
inv := k.ModInverse(k, N) inv := k.ModInverse(k, N)
s = new(big.Int).Mul(priv.D, r) s = new(big.Int).Mul(priv.D, r)
s.Add(s, e) s.Add(s, e)
s.Mul(s, inv) s.Mul(s, inv)
s.Mod(s, N) s.Mod(s, N)
return s.Sign() != 0 return s.Sign() != 0
}) })
return return
} }

View File

@ -1,74 +1,74 @@
package rfc6979 package rfc6979
import ( import (
"crypto/dsa" //nolint:staticcheck "crypto/dsa" //nolint:staticcheck
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic" "crypto/elliptic"
"crypto/rand" "crypto/rand"
"crypto/sha1" "crypto/sha1"
"crypto/sha512" "crypto/sha512"
"fmt" "fmt"
) )
// Generates a 521-bit ECDSA key, uses SHA-512 to sign a message, then verifies // Generates a 521-bit ECDSA key, uses SHA-512 to sign a message, then verifies
// it. // it.
func ExampleSignECDSA() { func ExampleSignECDSA() {
// Generate a key pair. // Generate a key pair.
// You need a high-quality PRNG for this. // You need a high-quality PRNG for this.
k, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) k, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
// Hash a message. // Hash a message.
alg := sha512.New() alg := sha512.New()
alg.Write([]byte("I am a potato.")) alg.Write([]byte("I am a potato."))
hash := alg.Sum(nil) hash := alg.Sum(nil)
// Sign the message. You don't need a PRNG for this. // Sign the message. You don't need a PRNG for this.
r, s := SignECDSA(k, hash, sha512.New) r, s := SignECDSA(k, hash, sha512.New)
if !ecdsa.Verify(&k.PublicKey, hash, r, s) { if !ecdsa.Verify(&k.PublicKey, hash, r, s) {
fmt.Println("Invalid signature!") fmt.Println("Invalid signature!")
} }
// Output: // Output:
} }
// Generates a 1024-bit DSA key, uses SHA-1 to sign a message, then verifies it. // Generates a 1024-bit DSA key, uses SHA-1 to sign a message, then verifies it.
func ExampleSignDSA() { func ExampleSignDSA() {
// Here I'm generating some DSA params, but you should really pre-generate // Here I'm generating some DSA params, but you should really pre-generate
// these and re-use them, since this takes a long time and isn't necessary. // these and re-use them, since this takes a long time and isn't necessary.
k := new(dsa.PrivateKey) k := new(dsa.PrivateKey)
if err := dsa.GenerateParameters(&k.Parameters, rand.Reader, dsa.L1024N160); err != nil { if err := dsa.GenerateParameters(&k.Parameters, rand.Reader, dsa.L1024N160); err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
// Generate a key pair. // Generate a key pair.
// You need a high-quality PRNG for this. // You need a high-quality PRNG for this.
err := dsa.GenerateKey(k, rand.Reader) err := dsa.GenerateKey(k, rand.Reader)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
// Hash a message. // Hash a message.
alg := sha1.New() alg := sha1.New()
alg.Write([]byte("I am a potato.")) alg.Write([]byte("I am a potato."))
hash := alg.Sum(nil) hash := alg.Sum(nil)
// Sign the message. You don't need a PRNG for this. // Sign the message. You don't need a PRNG for this.
r, s, err := SignDSA(k, hash, sha1.New) r, s, err := SignDSA(k, hash, sha1.New)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
if !dsa.Verify(&k.PublicKey, hash, r, s) { if !dsa.Verify(&k.PublicKey, hash, r, s) {
fmt.Println("Invalid signature!") fmt.Println("Invalid signature!")
} }
// Output: // Output:
} }

View File

@ -1,114 +1,114 @@
/* /*
Package rfc6979 is an implementation of RFC 6979's deterministic DSA. Package rfc6979 is an implementation of RFC 6979's deterministic DSA.
Such signatures are compatible with standard Digital Signature Algorithm Such signatures are compatible with standard Digital Signature Algorithm
(DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA) digital (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA) digital
signatures and can be processed with unmodified verifiers, which need not be signatures and can be processed with unmodified verifiers, which need not be
aware of the procedure described therein. Deterministic signatures retain aware of the procedure described therein. Deterministic signatures retain
the cryptographic security features associated with digital signatures but the cryptographic security features associated with digital signatures but
can be more easily implemented in various environments, since they do not can be more easily implemented in various environments, since they do not
need access to a source of high-quality randomness. need access to a source of high-quality randomness.
(https://tools.ietf.org/html/rfc6979) (https://tools.ietf.org/html/rfc6979)
Provides functions similar to crypto/dsa and crypto/ecdsa. Provides functions similar to crypto/dsa and crypto/ecdsa.
*/ */
package rfc6979 package rfc6979
import ( import (
"crypto/hmac" "crypto/hmac"
"hash" "hash"
"math/big" "math/big"
) )
// mac returns an HMAC result for the given key and message as well as // mac returns an HMAC result for the given key and message as well as
// hmac hash instance itself (that can be reused for the same key after reset). // hmac hash instance itself (that can be reused for the same key after reset).
func mac(alg func() hash.Hash, k, m, buf []byte) ([]byte, hash.Hash) { func mac(alg func() hash.Hash, k, m, buf []byte) ([]byte, hash.Hash) {
h := hmac.New(alg, k) h := hmac.New(alg, k)
h.Write(m) h.Write(m)
return h.Sum(buf[:0]), h return h.Sum(buf[:0]), h
} }
// macReuse allows to reuse already initialized hmac for the next // macReuse allows to reuse already initialized hmac for the next
// message using the same key. // message using the same key.
func macReuse(h hash.Hash, m, buf []byte) []byte { func macReuse(h hash.Hash, m, buf []byte) []byte {
h.Reset() h.Reset()
h.Write(m) h.Write(m)
return h.Sum(buf[:0]) return h.Sum(buf[:0])
} }
// https://tools.ietf.org/html/rfc6979#section-2.3.2 // https://tools.ietf.org/html/rfc6979#section-2.3.2
func bits2int(in []byte, qlen int) *big.Int { func bits2int(in []byte, qlen int) *big.Int {
vlen := len(in) * 8 vlen := len(in) * 8
v := new(big.Int).SetBytes(in) v := new(big.Int).SetBytes(in)
if vlen > qlen { if vlen > qlen {
v.Rsh(v, uint(vlen-qlen)) v.Rsh(v, uint(vlen-qlen))
} }
return v return v
} }
// bits2IntModQ implements an integer part of bits2octets defined // bits2IntModQ implements an integer part of bits2octets defined
// in https://tools.ietf.org/html/rfc6979#section-2.3.4 // in https://tools.ietf.org/html/rfc6979#section-2.3.4
func bits2IntModQ(in []byte, q *big.Int, qlen int) *big.Int { func bits2IntModQ(in []byte, q *big.Int, qlen int) *big.Int {
z1 := bits2int(in, qlen) z1 := bits2int(in, qlen)
if z1.Cmp(q) < 0 { if z1.Cmp(q) < 0 {
return z1 return z1
} }
return z1.Sub(z1, q) return z1.Sub(z1, q)
} }
var one = big.NewInt(1) var one = big.NewInt(1)
// https://tools.ietf.org/html/rfc6979#section-3.2 // https://tools.ietf.org/html/rfc6979#section-3.2
func generateSecret(q, x *big.Int, alg func() hash.Hash, hash []byte, test func(*big.Int, *big.Int, []byte) bool) { func generateSecret(q, x *big.Int, alg func() hash.Hash, hash []byte, test func(*big.Int, *big.Int, []byte) bool) {
qlen := q.BitLen() qlen := q.BitLen()
holen := alg().Size() holen := alg().Size()
rolen := (qlen + 7) >> 3 rolen := (qlen + 7) >> 3
var bx = make([]byte, 2*rolen) var bx = make([]byte, 2*rolen)
x.FillBytes(bx[:rolen]) // int2octets per https://tools.ietf.org/html/rfc6979#section-2.3.3 x.FillBytes(bx[:rolen]) // int2octets per https://tools.ietf.org/html/rfc6979#section-2.3.3
var hashInt = bits2IntModQ(hash, q, qlen) var hashInt = bits2IntModQ(hash, q, qlen)
hashInt.FillBytes(bx[rolen:]) // int2octets per https://tools.ietf.org/html/rfc6979#section-2.3.3 hashInt.FillBytes(bx[rolen:]) // int2octets per https://tools.ietf.org/html/rfc6979#section-2.3.3
// Step B // Step B
var v = make([]byte, holen, holen+1+len(bx)) // see appends below var v = make([]byte, holen, holen+1+len(bx)) // see appends below
for i := range holen { for i := range holen {
v[i] = 0x01 v[i] = 0x01
} }
// Step C // Step C
k := make([]byte, holen) k := make([]byte, holen)
// Step D // Step D
k, _ = mac(alg, k, append(append(v, 0x00), bx...), k) k, _ = mac(alg, k, append(append(v, 0x00), bx...), k)
// Step E // Step E
v, h := mac(alg, k, v, v) v, h := mac(alg, k, v, v)
// Step F // Step F
k = macReuse(h, append(append(v, 0x01), bx...), k) k = macReuse(h, append(append(v, 0x01), bx...), k)
// Step G // Step G
v, h = mac(alg, k, v, v) v, h = mac(alg, k, v, v)
// Step H // Step H
var t = make([]byte, qlen/8) var t = make([]byte, qlen/8)
for { for {
// Step H1 // Step H1
t = t[:0] t = t[:0]
// Step H2 // Step H2
for len(t) < qlen/8 { for len(t) < qlen/8 {
v = macReuse(h, v, v) v = macReuse(h, v, v)
t = append(t, v...) t = append(t, v...)
} }
// Step H3 // Step H3
secret := bits2int(t, qlen) secret := bits2int(t, qlen)
if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 && test(secret, hashInt, t) { if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 && test(secret, hashInt, t) {
return return
} }
k, _ = mac(alg, k, append(v, 0x00), k) k, _ = mac(alg, k, append(v, 0x00), k)
v, h = mac(alg, k, v, v) v, h = mac(alg, k, v, v)
} }
} }

View File

@ -1,28 +1,28 @@
package rfc6979 package rfc6979
import ( import (
"crypto/sha256" "crypto/sha256"
"encoding/hex" "encoding/hex"
"math/big" "math/big"
"testing" "testing"
) )
// https://tools.ietf.org/html/rfc6979#appendix-A.1 // https://tools.ietf.org/html/rfc6979#appendix-A.1
func TestGenerateSecret(t *testing.T) { func TestGenerateSecret(t *testing.T) {
q, _ := new(big.Int).SetString("4000000000000000000020108A2E0CC0D99F8A5EF", 16) q, _ := new(big.Int).SetString("4000000000000000000020108A2E0CC0D99F8A5EF", 16)
x, _ := new(big.Int).SetString("09A4D6792295A7F730FC3F2B49CBC0F62E862272F", 16) x, _ := new(big.Int).SetString("09A4D6792295A7F730FC3F2B49CBC0F62E862272F", 16)
hash, _ := hex.DecodeString("AF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BF") hash, _ := hex.DecodeString("AF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BF")
expected, _ := new(big.Int).SetString("23AF4074C90A02B3FE61D286D5C87F425E6BDD81B", 16) expected, _ := new(big.Int).SetString("23AF4074C90A02B3FE61D286D5C87F425E6BDD81B", 16)
var actual *big.Int var actual *big.Int
generateSecret(q, x, sha256.New, hash, func(k *big.Int, _ *big.Int, _ []byte) bool { generateSecret(q, x, sha256.New, hash, func(k *big.Int, _ *big.Int, _ []byte) bool {
actual = k actual = k
return true return true
}) })
if actual.Cmp(expected) != 0 { if actual.Cmp(expected) != 0 {
t.Errorf("Expected %x, got %x", expected, actual) t.Errorf("Expected %x, got %x", expected, actual)
} }
} }