mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-04 13:32:52 -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
|
// get the length of the data in this certificate
|
||||||
|
// return -1 if the size of the certificate is invalid
|
||||||
func (c Certificate) Len() int {
|
func (c Certificate) Len() int {
|
||||||
|
if len(c) <= 2 {
|
||||||
|
// invalid size
|
||||||
|
return -1
|
||||||
|
}
|
||||||
return int(binary.BigEndian.Uint16(c[1:3]))
|
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) {
|
func (c Certificate) Data() (d []byte) {
|
||||||
l := c.Len()
|
l := c.Len()
|
||||||
if l > 0 {
|
if l > 0 && len(c) <= 3+l {
|
||||||
// TODO(psi): check bounds correctly?
|
|
||||||
d = c[3 : 3+l]
|
d = c[3 : 3+l]
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -42,7 +42,7 @@ var param = dsa.Parameters{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate a dsa keypair
|
// 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
|
// put our paramters in
|
||||||
priv.P = param.P
|
priv.P = param.P
|
||||||
priv.Q = param.Q
|
priv.Q = param.Q
|
||||||
@ -60,16 +60,19 @@ func createDSAPublicKey(Y *big.Int) *dsa.PublicKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createa i2p dsa private key given its public component
|
// createa i2p dsa private key given its public component
|
||||||
func createDSAPrivkey(X *big.Int) *dsa.PrivateKey {
|
func createDSAPrivkey(X *big.Int) (k *dsa.PrivateKey) {
|
||||||
Y := new(big.Int)
|
if X.Cmp(dsap) == -1 {
|
||||||
Y.Exp(dsag, X, dsap)
|
Y := new(big.Int)
|
||||||
return &dsa.PrivateKey{
|
Y.Exp(dsag, X, dsap)
|
||||||
PublicKey: dsa.PublicKey{
|
k = &dsa.PrivateKey{
|
||||||
Parameters: param,
|
PublicKey: dsa.PublicKey{
|
||||||
Y: Y,
|
Parameters: param,
|
||||||
},
|
Y: Y,
|
||||||
X: X,
|
},
|
||||||
|
X: X,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type DSAVerifier struct {
|
type DSAVerifier struct {
|
||||||
@ -128,6 +131,26 @@ func (k DSAPrivateKey) NewSigner() (s Signer, err error) {
|
|||||||
return
|
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) {
|
func (ds *DSASigner) Sign(data []byte) (sig []byte, err error) {
|
||||||
h := sha1.Sum(data)
|
h := sha1.Sum(data)
|
||||||
sig, err = ds.SignHash(h[:])
|
sig, err = ds.SignHash(h[:])
|
||||||
|
@ -1,27 +1,46 @@
|
|||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/dsa"
|
|
||||||
"crypto/rand"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDSA(t *testing.T) {
|
func TestDSA(t *testing.T) {
|
||||||
rng := rand.Reader
|
var sk DSAPrivateKey
|
||||||
kp := new(dsa.PrivateKey)
|
var pk DSAPublicKey
|
||||||
err := DSAGenerate(kp, rng)
|
var err error
|
||||||
|
sk, err = sk.Generate()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Logf("DSA Key Pair generated")
|
zeros := 0
|
||||||
} else {
|
for b, _ := range sk {
|
||||||
t.Logf("error while generating key: %s", err)
|
if b == 0 {
|
||||||
t.Fail()
|
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)
|
if err != nil {
|
||||||
_, _, err = dsa.Sign(rng, kp, h)
|
t.Logf("failed: %s", err.Error())
|
||||||
if err == nil {
|
|
||||||
t.Log("signed")
|
|
||||||
} else {
|
|
||||||
t.Logf("error signing: %s", err)
|
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,93 @@
|
|||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo pkg-config: libsodium
|
||||||
|
#include <sodium.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha512"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
type Ed25519PublicKey [32]byte
|
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 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 {
|
if err == nil {
|
||||||
dec, err := elgamalDecrypt(k, emsg, true)
|
dec, err := elgamalDecrypt(k, emsg, true)
|
||||||
if err == nil {
|
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.Logf("%q != %q", dec, msg)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ var ErrInvalidSignature = errors.New("invalid signature")
|
|||||||
type Verifier interface {
|
type Verifier interface {
|
||||||
// verify hashed data with this signing key
|
// verify hashed data with this signing key
|
||||||
// return nil on valid signature otherwise error
|
// 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 an unhashed piece of data by hashing it and calling VerifyHash
|
||||||
Verify(data, sig []byte) error
|
Verify(data, sig []byte) error
|
||||||
}
|
}
|
||||||
@ -42,6 +42,11 @@ type SigningPrivateKey interface {
|
|||||||
// create a new signer to sign data
|
// create a new signer to sign data
|
||||||
// return signer or nil and error if key format is invalid
|
// return signer or nil and error if key format is invalid
|
||||||
NewSigner() (Signer, error)
|
NewSigner() (Signer, error)
|
||||||
|
// length of this private key
|
||||||
Len() int
|
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