Skip to content

Commit

Permalink
Add golang and params.h changes from old main
Browse files Browse the repository at this point in the history
  • Loading branch information
david415 committed May 9, 2024
1 parent 7ec789a commit 23797ff
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 0 deletions.
12 changes: 12 additions & 0 deletions go.mod
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
)
19 changes: 19 additions & 0 deletions go.sum
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=
141 changes: 141 additions & 0 deletions ref/binding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package sphincsplus

//#cgo linux LDFLAGS: "-L./ -L/usr/lib/x86_64-linux-gnu/ -lcrypto"
//#include "api.h"
import "C"
import (
"fmt"
"unsafe"

"github.com/katzenpost/hpqc/util"

"github.com/katzenpost/sphincsplus/ref/params"
)

var (
_ = params.A

// 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

// 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())
)

// Name returns the string naming of the current
// Sphincs+ that this binding is being used with.
func Name() string {
return "Sphincs+shake-256f"
}

// 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
}

// Reset overwrites the key with zeros.
func (p *PublicKey) Reset() {
util.ExplicitBzero(p.publicKey)
}

// 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
}

// Reset overwrites the key with zeros.
func (p *PrivateKey) Reset() {
util.ExplicitBzero(p.privateKey)
}

// 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
}
65 changes: 65 additions & 0 deletions ref/binding_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
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("PrivateKeySize %d", PrivateKeySize)
t.Logf("PublicKeySize %d", PublicKeySize)
t.Logf("SignatureSize %d", SignatureSize)
}
17 changes: 17 additions & 0 deletions ref/explicitBzero.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: (C) 2017 Yawning Angel.
// SPDX-License-Identifier: AGPL-3.0-only

package sphincsplus

import "runtime"

// ExplicitBzero explicitly clears out the buffer b, by filling it with 0x00
// bytes.
//
//go:noinline
func ExplicitBzero(b []byte) {
for i := range b {
b[i] = 0
}
runtime.KeepAlive(b)
}
1 change: 1 addition & 0 deletions ref/params.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#define str(s) #s
#define xstr(s) str(s)
#define PARAMS sphincs-shake-256f

#include xstr(params/params-PARAMS.h)

3 changes: 3 additions & 0 deletions ref/params/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package params

const A = 1
39 changes: 39 additions & 0 deletions ref/vector_test.go

Large diffs are not rendered by default.

0 comments on commit 23797ff

Please sign in to comment.