* rework dsa test

* add initial ed25519 (not done)

* fix common.Certificate compile error

* add more functions to crypto.SigningPrivateKey interface, not everyone implements them yet
This commit is contained in:
Jeff Becker
2016-01-29 08:36:04 -05:00
parent 6fcab3b7dd
commit 5d043d79e7
7 changed files with 182 additions and 31 deletions

View File

@ -38,15 +38,19 @@ func (c Certificate) Type() byte {
}
// get the length of the data in this certificate
// return -1 if the size of the certificate is invalid
func (c Certificate) Len() int {
if len(c) <= 2 {
// invalid size
return -1
}
return int(binary.BigEndian.Uint16(c[1:3]))
}
// get the data for this certificate or null if non exists
// get the data for this certificate or null if none exists
func (c Certificate) Data() (d []byte) {
l := c.Len()
if l > 0 {
// TODO(psi): check bounds correctly?
if l > 0 && len(c) <= 3+l {
d = c[3 : 3+l]
}
return

View File

@ -42,7 +42,7 @@ var param = dsa.Parameters{
}
// generate a dsa keypair
func DSAGenerate(priv *dsa.PrivateKey, rand io.Reader) error {
func generateDSA(priv *dsa.PrivateKey, rand io.Reader) error {
// put our paramters in
priv.P = param.P
priv.Q = param.Q
@ -60,16 +60,19 @@ func createDSAPublicKey(Y *big.Int) *dsa.PublicKey {
}
// createa i2p dsa private key given its public component
func createDSAPrivkey(X *big.Int) *dsa.PrivateKey {
Y := new(big.Int)
Y.Exp(dsag, X, dsap)
return &dsa.PrivateKey{
PublicKey: dsa.PublicKey{
Parameters: param,
Y: Y,
},
X: X,
func createDSAPrivkey(X *big.Int) (k *dsa.PrivateKey) {
if X.Cmp(dsap) == -1 {
Y := new(big.Int)
Y.Exp(dsag, X, dsap)
k = &dsa.PrivateKey{
PublicKey: dsa.PublicKey{
Parameters: param,
Y: Y,
},
X: X,
}
}
return
}
type DSAVerifier struct {
@ -128,6 +131,26 @@ func (k DSAPrivateKey) NewSigner() (s Signer, err error) {
return
}
func (k DSAPrivateKey) Public() (pk DSAPublicKey, err error) {
p := createDSAPrivkey(new(big.Int).SetBytes(k[:]))
if p == nil {
err = ErrInvalidKeyFormat
} else {
copy(pk[:], p.Y.Bytes())
}
return
}
func (k DSAPrivateKey) Generate() (s DSAPrivateKey, err error) {
dk := new(dsa.PrivateKey)
err = generateDSA(dk, rand.Reader)
if err == nil {
copy(k[:], dk.X.Bytes())
s = k
}
return
}
func (ds *DSASigner) Sign(data []byte) (sig []byte, err error) {
h := sha1.Sum(data)
sig, err = ds.SignHash(h[:])

View File

@ -1,27 +1,46 @@
package crypto
import (
"crypto/dsa"
"crypto/rand"
"testing"
)
func TestDSA(t *testing.T) {
rng := rand.Reader
kp := new(dsa.PrivateKey)
err := DSAGenerate(kp, rng)
var sk DSAPrivateKey
var pk DSAPublicKey
var err error
sk, err = sk.Generate()
if err == nil {
t.Logf("DSA Key Pair generated")
} else {
t.Logf("error while generating key: %s", err)
t.Fail()
zeros := 0
for b, _ := range sk {
if b == 0 {
zeros ++
}
}
if zeros == len(sk) {
t.Logf("key generation yielded all zeros")
t.Fail()
}
pk, err = sk.Public()
if err == nil {
data := make([]byte, 512)
var sig []byte
var signer Signer
signer, err = sk.NewSigner()
if err == nil {
sig, err = signer.Sign(data)
if err == nil {
t.Logf("sig=%q", sig)
var verify Verifier
verify, err = pk.NewVerifier()
if err == nil {
err = verify.Verify(data, sig)
}
}
}
}
}
h := make([]byte, 20)
_, _, err = dsa.Sign(rng, kp, h)
if err == nil {
t.Log("signed")
} else {
t.Logf("error signing: %s", err)
if err != nil {
t.Logf("failed: %s", err.Error())
t.Fail()
}
}

View File

@ -1,4 +1,93 @@
package crypto
/*
#cgo pkg-config: libsodium
#include <sodium.h>
#include <stdint.h>
*/
import "C"
import (
"crypto/sha512"
"errors"
"fmt"
)
type Ed25519PublicKey [32]byte
type Ed25519Verifier struct {
k [32]C.uchar
}
func (k Ed25519PublicKey) NewVerifier() (v Verifier, err error) {
ev := new(Ed25519Verifier)
for i, b := range k {
ev.k[i] = C.uchar(b)
}
v = ev
return
}
func (v *Ed25519Verifier) VerifyHash(h, sig []byte) (err error) {
if len(sig) == C.crypto_sign_BYTES {
// valid size of sig
// copy signature and hash
var csig, ch [32]C.uchar
for i, b := range h {
ch[i] = C.uchar(b)
}
for i, b := range sig {
csig[i] = C.uchar(b)
}
// verify
if C.crypto_sign_verify_detached(&csig[0], &ch[0], C.ulonglong(32), &v.k[0]) == 0 {
// valid signature
} else {
// bad signature
err = ErrInvalidSignature
}
} else {
// bad size of sig
err = ErrBadSignatureSize
}
return
}
func (v *Ed25519Verifier) Verify(data, sig []byte) (err error) {
h := sha512.Sum512(data)
err = v.VerifyHash(h[:], sig)
return
}
type Ed25519PrivateKey [32]byte
type Ed25519Signer struct {
k [32]C.uchar
}
func (s *Ed25519Signer) Sign(data []byte) (sig []byte, err error) {
h := sha512.Sum512(data)
sig, err = s.SignHash(h[:])
return
}
func (s *Ed25519Signer) SignHash(h []byte) (sig []byte, err error) {
var ch [32]C.uchar
for i, b := range h {
ch[i] = C.uchar(b)
}
var csig [32]C.uchar
var smlen_p C.ulonglong
res := C.crypto_sign_detached(&csig[0], &smlen_p, &ch[0], C.ulonglong(32), &s.k[0])
if res == 0 {
// success signing
sig = make([]byte, 32)
for i, b := range csig {
sig[i] = byte(b)
}
} else {
// failed signing
err = errors.New(fmt.Sprintf("failed to sign: crypto_sign_detached exit code %d", int(res)))
}
return
}

View File

@ -0,0 +1,9 @@
package crypto
import (
"testing"
)
func TestEd25519(t *testing.T) {
}

View File

@ -22,7 +22,9 @@ func TestElg(t *testing.T) {
if err == nil {
dec, err := elgamalDecrypt(k, emsg, true)
if err == nil {
if !bytes.Equal(dec, msg) {
if bytes.Equal(dec, msg) {
t.Logf("%q == %q", dec, msg)
} else {
t.Logf("%q != %q", dec, msg)
t.Fail()
}

View File

@ -12,7 +12,7 @@ var ErrInvalidSignature = errors.New("invalid signature")
type Verifier interface {
// verify hashed data with this signing key
// return nil on valid signature otherwise error
VerifyHash(data, sig []byte) error
VerifyHash(h, sig []byte) error
// verify an unhashed piece of data by hashing it and calling VerifyHash
Verify(data, sig []byte) error
}
@ -42,6 +42,11 @@ type SigningPrivateKey interface {
// create a new signer to sign data
// return signer or nil and error if key format is invalid
NewSigner() (Signer, error)
// length of this private key
Len() int
// get public key or return nil and error if invalid key data in private key
Public() (SigningPublicKey, error)
// generate a new private key, put it into itself
// returns itself or nil and error if an error occurs
Generate() (SigningPrivateKey, error)
}