mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-04 05:26:51 -04:00
* 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:
@ -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
|
||||
|
@ -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 {
|
||||
func createDSAPrivkey(X *big.Int) (k *dsa.PrivateKey) {
|
||||
if X.Cmp(dsap) == -1 {
|
||||
Y := new(big.Int)
|
||||
Y.Exp(dsag, X, dsap)
|
||||
return &dsa.PrivateKey{
|
||||
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[:])
|
||||
|
@ -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)
|
||||
zeros := 0
|
||||
for b, _ := range sk {
|
||||
if b == 0 {
|
||||
zeros ++
|
||||
}
|
||||
}
|
||||
if zeros == len(sk) {
|
||||
t.Logf("key generation yielded all zeros")
|
||||
t.Fail()
|
||||
}
|
||||
h := make([]byte, 20)
|
||||
_, _, err = dsa.Sign(rng, kp, h)
|
||||
pk, err = sk.Public()
|
||||
if err == nil {
|
||||
t.Log("signed")
|
||||
} else {
|
||||
t.Logf("error signing: %s", err)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
t.Logf("failed: %s", err.Error())
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
9
lib/crypto/ed25519_test.go
Normal file
9
lib/crypto/ed25519_test.go
Normal file
@ -0,0 +1,9 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEd25519(t *testing.T) {
|
||||
|
||||
}
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Reference in New Issue
Block a user