-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This updates the Golang bindings originally written by David Stainton for the Katzenpost Mixnet fork and uses the latest SPHINCS+ reference implementation. This branch enhances the bindings to parameterize building, and to perform comprehensive testing for all parameter sets on GNU/Linux, MacOS, and Windows.
- Loading branch information
Showing
67 changed files
with
1,235 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
name: Windows Msys2 64bit (msvcrt,ucrt) gcc golang build and test | ||
|
||
on: [push] | ||
|
||
jobs: | ||
windows-build-and-test-golang: | ||
runs-on: ${{ matrix.os }} | ||
strategy: | ||
matrix: | ||
OS: ["windows-2019", "windows-2022"] | ||
CC: ["gcc"] | ||
ENVIRONMENT: ["UCRT64", "MINGW64"] # https://www.msys2.org/docs/environments/ | ||
go-version: ["1.22.x"] | ||
hash: | ||
- sha2 | ||
- shake | ||
- haraka | ||
size: | ||
- 128 | ||
- 192 | ||
- 256 | ||
option: | ||
- s | ||
- f | ||
thash: | ||
- simple | ||
- robust | ||
fail-fast: false | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Set up Msys2 | ||
uses: msys2/setup-msys2@v2 | ||
with: | ||
msystem: ${{ matrix.ENVIRONMENT }} | ||
install: >- | ||
base-devel | ||
mingw-w64-x86_64-toolchain | ||
mingw-w64-x86_64-pkg-config | ||
mingw-w64-x86_64-gcc | ||
mingw-w64-ucrt-x86_64-gcc | ||
mingw-w64-x86_64-go | ||
mingw-w64-ucrt-x86_64-go | ||
make | ||
git | ||
gcc | ||
- name: Setup Go ${{ matrix.go-version }} | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
|
||
- name: Gather runtime environment | ||
shell: msys2 {0} | ||
run: | | ||
echo ${{ matrix.ENVIRONMENT }} | ||
uname -a | ||
bash --version | ||
${{ matrix.CC }} -v | ||
go version | ||
- name: Build golang | ||
shell: msys2 {0} | ||
run: | | ||
export CGO_ENABLE=1 | ||
export CGO_CFLAGS="-D HASH=${{ matrix.hash }} -D THASH=${{ matrix.thash }} -D PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }}" | ||
go build --tags=sphincs_${{ matrix.hash }}_${{ matrix.size }}${{ matrix.option }} -v ./... | ||
- name: Golang test | ||
shell: msys2 {0} | ||
run: | | ||
export CGO_ENABLE=1 | ||
export CGO_CFLAGS="-D HASH=${{ matrix.hash }} -D THASH=${{ matrix.thash }} -D PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }}" | ||
go test --tags=sphincs_${{ matrix.hash }}_${{ matrix.size }}${{ matrix.option }} -v ./... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
name: Tests golang bindings for ref implementation | ||
|
||
on: | ||
- push | ||
- pull_request | ||
|
||
jobs: | ||
build: | ||
runs-on: ${{ matrix.OS }} | ||
strategy: | ||
matrix: | ||
hash: | ||
- sha2 | ||
- shake | ||
- haraka | ||
size: | ||
- 128 | ||
- 192 | ||
- 256 | ||
option: | ||
- s | ||
- f | ||
thash: | ||
- simple | ||
- robust | ||
OS: ["ubuntu-latest", "macos-latest"] | ||
go-version: ["1.20"] | ||
#go-version: ["1.22.x"] | ||
# later: go-version: ["1.19", "1.20", "1.21.x", "1.22.x"] | ||
fail-fast: false | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Setup Go ${{ matrix.go-version }} | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
|
||
- name: Run go test | ||
run: | | ||
export CGO_ENABLE=1 | ||
export CGO_CFLAGS=" -D HASH=${{ matrix.hash }} -D THASH=${{ matrix.thash }} -D PARAMS=sphincs-${{ matrix.hash }}-${{ matrix.size }}${{ matrix.option }}" | ||
go test --tags=sphincs_${{ matrix.hash }}_${{ matrix.size }}${{ matrix.option }} -v ./... | ||
# vim: set ft=yaml ts=2 sw=2 et : |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module github.com/katzenpost/sphincsplus | ||
|
||
go 1.20 | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/katzenpost/hpqc v0.0.0-20240114190904-bc8bcfcca4ee // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
github.com/stretchr/objx v0.5.0 // indirect | ||
github.com/stretchr/testify v1.8.4 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/katzenpost/hpqc v0.0.0-20240114190904-bc8bcfcca4ee h1:MiBBJNXAJkgv7asTOzrL0lbsL+UIFaFlm13boWz4Fxs= | ||
github.com/katzenpost/hpqc v0.0.0-20240114190904-bc8bcfcca4ee/go.mod h1:i2+fQVPYzpv+WoZcN0KQqjQLEc/AgzRYwAFjYC/LiHg= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= | ||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
PARAMS = sphincs-haraka-128f | ||
PARAMS ?= sphincs-haraka-128f | ||
THASH = robust | ||
|
||
CC=/usr/bin/gcc | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// +build PQCgenKAT_sign | ||
|
||
// | ||
// PQCgenKAT_sign.c | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
//go:build cgo && ((linux && amd64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && (sphincs_haraka_128f || sphincs_haraka_128s || sphincs_haraka_192f || sphincs_haraka_192s || sphincs_haraka_256f || sphincs_haraka_256s || sphincs_sha2_128f || sphincs_sha2_128s || sphincs_sha2_192f || sphincs_sha2_192s || sphincs_sha2_256f || sphincs_sha2_256s || sphincs_shake_128f || sphincs_shake_128s || sphincs_shake_192f || sphincs_shake_192s || sphincs_shake_256f || sphincs_shake_256s) | ||
|
||
package sphincsplus | ||
|
||
//#cgo amd64 LDFLAGS: -L./ | ||
//#cgo amd64 CFLAGS: -O3 -std=c99 -D CGO=1 | ||
//#cgo darwin/amd64 LDFLAGS: -L./ | ||
//#cgo darwin/amd64 CFLAGS: -O3 -std=c99 -D CGO=1 | ||
//#cgo linux/amd64 LDFLAGS: -L./ -L/usr/lib/x86_64-linux-gnu/ | ||
//#cgo linux/amd64 CFLAGS: -O3 -std=c99 -D CGO=1 | ||
//#include "api.h" | ||
import "C" | ||
import ( | ||
"fmt" | ||
"unsafe" | ||
|
||
"github.com/katzenpost/sphincsplus/ref/params" | ||
) | ||
|
||
var ( | ||
|
||
// PublicKeySize is the size in bytes of the public key. | ||
PublicKeySize int = C.CRYPTO_PUBLICKEYBYTES | ||
|
||
// PrivateKeySize is the size in bytes of the private key. | ||
PrivateKeySize int = C.CRYPTO_SECRETKEYBYTES | ||
|
||
// SignatureSize is the size in bytes of the signature. | ||
SignatureSize int = C.CRYPTO_BYTES | ||
|
||
// SignatureName is the parameterized signature system name | ||
|
||
// Name returns the string naming of the current | ||
// Sphincs+ that this binding is being used with. | ||
SignatureName = params.Name() | ||
|
||
// ErrPublicKeySize indicates the raw data is not the correct size for a public key. | ||
ErrPublicKeySize error = fmt.Errorf("%s: raw public key data size is wrong", Name()) | ||
|
||
// ErrPrivateKeySize indicates the raw data is not the correct size for a private key. | ||
ErrPrivateKeySize error = fmt.Errorf("%s: raw private key data size is wrong", Name()) | ||
) | ||
|
||
func SchemeName() string { | ||
return SignatureName | ||
} | ||
|
||
// NewKeypair generates a new Sphincs+ keypair. | ||
func NewKeypair() (*PrivateKey, *PublicKey) { | ||
privKey := &PrivateKey{ | ||
privateKey: make([]byte, C.CRYPTO_SECRETKEYBYTES), | ||
} | ||
pubKey := &PublicKey{ | ||
publicKey: make([]byte, C.CRYPTO_PUBLICKEYBYTES), | ||
} | ||
C.crypto_sign_keypair((*C.uchar)(unsafe.Pointer(&pubKey.publicKey[0])), | ||
(*C.uchar)(unsafe.Pointer(&privKey.privateKey[0]))) | ||
return privKey, pubKey | ||
} | ||
|
||
// PublicKey is a public Sphincs+ key. | ||
type PublicKey struct { | ||
publicKey []byte | ||
} | ||
|
||
// Verify checks whether the given signature is valid. | ||
func (p *PublicKey) Verify(signature, message []byte) bool { | ||
ret := C.crypto_sign_verify((*C.uchar)(unsafe.Pointer(&signature[0])), | ||
C.size_t(len(signature)), | ||
(*C.uchar)(unsafe.Pointer(&message[0])), | ||
C.size_t(len(message)), | ||
(*C.uchar)(unsafe.Pointer(&p.publicKey[0]))) | ||
if ret == 0 { | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
// Bytes returns the PublicKey as a byte slice. | ||
func (p *PublicKey) Bytes() []byte { | ||
return p.publicKey | ||
} | ||
|
||
// FromBytes loads a PublicKey from the given byte slice. | ||
func (p *PublicKey) FromBytes(data []byte) error { | ||
if len(data) != PublicKeySize { | ||
return ErrPublicKeySize | ||
} | ||
|
||
p.publicKey = data | ||
return nil | ||
} | ||
|
||
// Verify checks whether the given signature is valid. | ||
/* | ||
func (p *PublicKey) Verify(signature, message []byte) bool { | ||
ret := C.crypto_sign_verify((*C.uchar)(unsafe.Pointer(&signature[0])), | ||
C.ulong(len(signature)), | ||
(*C.uchar)(unsafe.Pointer(&message[0])), | ||
C.ulong(len(message)), | ||
(*C.uchar)(unsafe.Pointer(&p.publicKey[0]))) | ||
if ret == 0 { | ||
return true | ||
} | ||
return false | ||
} | ||
*/ | ||
|
||
// PrivateKey is a private Sphincs+ key. | ||
type PrivateKey struct { | ||
privateKey []byte | ||
} | ||
|
||
// Sign signs the given message and returns the signature. | ||
func (p *PrivateKey) Sign(message []byte) []byte { | ||
signature := make([]byte, C.CRYPTO_BYTES) | ||
sigLen := C.size_t(C.CRYPTO_BYTES) | ||
C.crypto_sign_signature((*C.uchar)(unsafe.Pointer(&signature[0])), | ||
&sigLen, | ||
(*C.uchar)(unsafe.Pointer(&message[0])), | ||
(C.size_t)(len(message)), | ||
(*C.uchar)(unsafe.Pointer(&p.privateKey[0]))) | ||
return signature | ||
} | ||
|
||
// Bytes returns the PrivateKey as a byte slice. | ||
func (p *PrivateKey) Bytes() []byte { | ||
return p.privateKey | ||
} | ||
|
||
// FromBytes loads a PrivateKey from the given byte slice. | ||
func (p *PrivateKey) FromBytes(data []byte) error { | ||
if len(data) != PrivateKeySize { | ||
return ErrPrivateKeySize | ||
} | ||
|
||
p.privateKey = data | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
//go:build ((linux && amd64) || (darwin && amd64) || (darwin && arm64) || (windows && amd64)) && (sphincs_haraka_128f || sphincs_haraka_128s || sphincs_haraka_192f || sphincs_haraka_192s || sphincs_haraka_256f || sphincs_haraka_256s || sphincs_sha2_128f || sphincs_sha2_128s || sphincs_sha2_192f || sphincs_sha2_192s || sphincs_sha2_256f || sphincs_sha2_256s || sphincs_shake_128f || sphincs_shake_128s || sphincs_shake_192f || sphincs_shake_192s || sphincs_shake_256f || sphincs_shake_256s) | ||
|
||
package sphincsplus | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestSignVerify(t *testing.T) { | ||
t.Parallel() | ||
privKey1, pubKey1 := NewKeypair() | ||
message := []byte("i am a message") | ||
sig1 := privKey1.Sign(message) | ||
require.True(t, pubKey1.Verify(sig1, message)) | ||
|
||
privKey2, pubKey2 := NewKeypair() | ||
require.False(t, pubKey2.Verify(sig1, message)) | ||
|
||
sig2 := privKey2.Sign(message) | ||
require.True(t, pubKey2.Verify(sig2, message)) | ||
require.False(t, pubKey1.Verify(sig2, message)) | ||
|
||
// non-determinism | ||
sig3 := privKey1.Sign(message) | ||
require.NotEqual(t, sig1, sig3) | ||
} | ||
|
||
func TestSerialization(t *testing.T) { | ||
t.Parallel() | ||
privKey1, pubKey1 := NewKeypair() | ||
message := []byte("i am a message") | ||
sig := privKey1.Sign(message) | ||
require.True(t, pubKey1.Verify(sig, message)) | ||
|
||
pubKeyBytes1 := pubKey1.Bytes() | ||
pubKey2 := &PublicKey{} | ||
err := pubKey2.FromBytes(pubKeyBytes1) | ||
require.NoError(t, err) | ||
require.True(t, pubKey2.Verify(sig, message)) | ||
require.False(t, pubKey2.Verify(sig, message[:len(message)-3])) | ||
|
||
privKeyBytes2 := privKey1.Bytes() | ||
privKey2 := &PrivateKey{} | ||
err = privKey2.FromBytes(privKeyBytes2) | ||
require.NoError(t, err) | ||
sig2 := privKey2.Sign(message) | ||
require.True(t, pubKey1.Verify(sig2, message)) | ||
require.True(t, pubKey2.Verify(sig2, message)) | ||
} | ||
|
||
func TestSizes(t *testing.T) { | ||
t.Parallel() | ||
privKey, pubKey := NewKeypair() | ||
message := []byte("i am a message") | ||
sig := privKey.Sign(message) | ||
require.True(t, pubKey.Verify(sig, message)) | ||
|
||
require.Equal(t, PrivateKeySize, len(privKey.Bytes())) | ||
require.Equal(t, PublicKeySize, len(pubKey.Bytes())) | ||
require.Equal(t, SignatureSize, len(sig)) | ||
|
||
t.Logf("SPHINCS+ scheme parameters: %s", SchemeName()) | ||
t.Logf("PrivateKeySize %d", PrivateKeySize) | ||
t.Logf("PublicKeySize %d", PublicKeySize) | ||
t.Logf("SignatureSize %d", SignatureSize) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.