move crypto parts from stdi2p to crypto package

This commit is contained in:
Jeff Becker
2016-01-28 15:11:54 -05:00
parent b52e4adc04
commit 3deb15e012
12 changed files with 278 additions and 173 deletions

View File

@ -2,6 +2,8 @@ package crypto
import (
"crypto/dsa"
"crypto/sha1"
"crypto/rand"
"io"
"math/big"
)
@ -50,7 +52,7 @@ func DSAGenerate(priv *dsa.PrivateKey, rand io.Reader) error {
}
// create i2p dsa public key given its public component
func DSAPublicKey(Y *big.Int) *dsa.PublicKey {
func createDSAPublicKey(Y *big.Int) *dsa.PublicKey {
return &dsa.PublicKey{
Parameters: param,
Y: Y,
@ -58,7 +60,7 @@ func DSAPublicKey(Y *big.Int) *dsa.PublicKey {
}
// createa i2p dsa private key given its public component
func DSAPrivkey(X *big.Int) *dsa.PrivateKey {
func createDSAPrivkey(X *big.Int) *dsa.PrivateKey {
Y := new(big.Int)
Y.Exp(dsag, X, dsap)
return &dsa.PrivateKey{
@ -69,3 +71,82 @@ func DSAPrivkey(X *big.Int) *dsa.PrivateKey {
X: X,
}
}
type DSAVerifier struct {
k *dsa.PublicKey
}
type DSAPublicKey [128]byte
// create a new dsa verifier
func (k DSAPublicKey) NewVerifier() (v Verifier, err error) {
v = &DSAVerifier{
k: createDSAPublicKey(new(big.Int).SetBytes(k[:])),
}
return
}
// verify data with a dsa public key
func (v *DSAVerifier) Verify(data, sig []byte) (err error) {
h := sha1.Sum(data)
err = v.VerifyHash(h[:], sig)
return
}
// verify hash of data with a dsa public key
func (v *DSAVerifier) VerifyHash(h, sig []byte) (err error) {
if len(sig) == 40 {
r := new(big.Int).SetBytes(sig[:20])
s := new(big.Int).SetBytes(sig[20:])
if dsa.Verify(v.k, h, r, s) {
// valid signature
} else {
// invalid signature
err = ErrInvalidSignature
}
} else {
err = ErrBadSignatureSize
}
return
}
func (k DSAPublicKey) Len() int {
return len(k)
}
type DSASigner struct {
k *dsa.PrivateKey
}
type DSAPrivateKey [20]byte
// create a new dsa signer
func (k DSAPrivateKey) NewSigner() (s Signer, err error) {
s = &DSASigner{
k: createDSAPrivkey(new (big.Int).SetBytes(k[:])),
}
return
}
func (ds *DSASigner) Sign(data []byte) (sig []byte, err error) {
h := sha1.Sum(data)
sig, err = ds.SignHash(h[:])
return
}
func (ds *DSASigner) SignHash(h []byte) (sig []byte, err error) {
var r, s *big.Int
r, s, err = dsa.Sign(rand.Reader, ds.k, h)
if err == nil {
sig = make([]byte, 40)
copy(sig, r.Bytes())
copy(sig[20:], s.Bytes())
}
return
}
func (k DSAPrivateKey) Len() int {
return len(k)
}

78
lib/crypto/ecdsa.go Normal file
View File

@ -0,0 +1,78 @@
package crypto
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
)
type ECDSAVerifier struct {
k *ecdsa.PublicKey
c elliptic.Curve
h crypto.Hash
}
// verify a signature given the hash
func (v *ECDSAVerifier) VerifyHash(h, sig []byte) (err error) {
r, s := elliptic.Unmarshal(v.c, sig)
if r == nil || s == nil || ! ecdsa.Verify(v.k, h, r, s) {
err = ErrInvalidSignature
}
return
}
// verify a block of data by hashing it and comparing the hash against the signature
func (v *ECDSAVerifier) Verify(data, sig []byte) (err error) {
// sum the data and get the hash
h := v.h.New().Sum(data)[len(data):]
// verify
err = v.VerifyHash(h, sig)
return
}
func createECVerifier(c elliptic.Curve, h crypto.Hash, k []byte) (ev *ECDSAVerifier, err error) {
x, y := elliptic.Unmarshal(c, k[:])
if x == nil {
err = ErrInvalidKeyFormat
} else {
ev = &ECDSAVerifier{
c: c,
h: h,
}
ev.k = &ecdsa.PublicKey{c, x, y}
}
return
}
type ECP256PublicKey [64]byte
type ECP256PrivateKey [32]byte
func (k ECP256PublicKey) Len() int {
return len(k)
}
func (k ECP256PublicKey) NewVerifier() (Verifier, error) {
return createECVerifier(elliptic.P256(), crypto.SHA256, k[:])
}
type ECP384PublicKey [96]byte
type ECP384PrivateKey [48]byte
func (k ECP384PublicKey) Len() int {
return len(k)
}
func (k ECP384PublicKey) NewVerifier() (Verifier, error) {
return createECVerifier(elliptic.P384(), crypto.SHA384, k[:])
}
type ECP521PublicKey [132]byte
type ECP521PrivateKey [66]byte
func (k ECP521PublicKey) Len() int {
return len(k)
}
func (k ECP521PublicKey) NewVerifier() (Verifier, error) {
return createECVerifier(elliptic.P521(), crypto.SHA512, k[:])
}

5
lib/crypto/ed25519.go Normal file
View File

@ -0,0 +1,5 @@
package crypto
type Ed25519PublicKey [32]byte
type Ed25519PrivateKey [32]byte

View File

@ -1,6 +1,7 @@
package crypto
import (
"crypto/rand"
"crypto/sha256"
"crypto/subtle"
"errors"
@ -92,7 +93,6 @@ type ElgamalEncryption struct {
p, a, b1 *big.Int
}
// implements stdi2p.PublicEncryptionKey
func (elg *ElgamalEncryption) Encrypt(data []byte) (enc []byte, err error) {
return elg.EncryptPadding(data, true)
}
@ -125,7 +125,7 @@ func (elg *ElgamalEncryption) EncryptPadding(data []byte, zeroPadding bool) (enc
}
// create an elgamal public key from byte slice
func ElgamalPublicKey(data []byte) (k *elgamal.PublicKey) {
func createElgamalPublicKey(data []byte) (k *elgamal.PublicKey) {
if len(data) == 256 {
k = &elgamal.PublicKey{
G: elgg,
@ -137,7 +137,7 @@ func ElgamalPublicKey(data []byte) (k *elgamal.PublicKey) {
}
// create an elgamal private key from byte slice
func ElgamalPrivateKey(data []byte) (k *elgamal.PrivateKey) {
func createElgamalPrivateKey(data []byte) (k *elgamal.PrivateKey) {
if len(data) == 256 {
x := new(big.Int).SetBytes(data)
y := new(big.Int).Exp(elgg, x, elgp)
@ -154,7 +154,7 @@ func ElgamalPrivateKey(data []byte) (k *elgamal.PrivateKey) {
}
// create a new elgamal encryption session
func NewElgamalEncryption(pub *elgamal.PublicKey, rand io.Reader) (enc *ElgamalEncryption, err error) {
func createElgamalEncryption(pub *elgamal.PublicKey, rand io.Reader) (enc *ElgamalEncryption, err error) {
kbytes := make([]byte, 256)
k := new(big.Int)
for err == nil {
@ -174,3 +174,17 @@ func NewElgamalEncryption(pub *elgamal.PublicKey, rand io.Reader) (enc *ElgamalE
}
return
}
type ElgPublicKey [256]byte
type ElgPrivateKey [256]byte
func (elg ElgPublicKey) Len() int {
return len(elg)
}
func (elg ElgPublicKey) NewEncrypter() (enc Encrypter, err error) {
k := createElgamalPublicKey(elg[:])
enc, err = createElgamalEncryption(k, rand.Reader)
return
}

View File

@ -16,8 +16,8 @@ func TestElg(t *testing.T) {
msg := make([]byte, 222)
_, err := io.ReadFull(rand.Reader, msg)
if err == nil {
pub := ElgamalPublicKey(k.Y.Bytes())
enc, err := NewElgamalEncryption(pub, rand.Reader)
pub := createElgamalPublicKey(k.Y.Bytes())
enc, err := createElgamalEncryption(pub, rand.Reader)
if err == nil {
emsg, err := enc.Encrypt(msg)
if err == nil {

16
lib/crypto/encrypt.go Normal file
View File

@ -0,0 +1,16 @@
package crypto
type Encrypter interface {
// encrypt a block of data
// return encrypted block or nil and error if an error happened
Encrypt(data []byte) (enc []byte, err error)
}
type PublicEncryptionKey interface {
// create a new encrypter to encrypt data to this public key
NewEncrypter() (Encrypter, error)
// length of this public key in bytes
Len() int
}

12
lib/crypto/rsa.go Normal file
View File

@ -0,0 +1,12 @@
package crypto
type RSA2048PublicKey [256]byte
type RSA2048PrivateKey [512]byte
type RSA3072PublicKey [384]byte
type RSA3072PrivateKey [786]byte
type RSA4096PublicKey [512]byte
type RSA4096PrivateKey [1024]byte

49
lib/crypto/sign.go Normal file
View File

@ -0,0 +1,49 @@
package crypto
import (
"errors"
)
var ErrBadSignatureSize = errors.New("bad signature size")
var ErrInvalidKeyFormat = errors.New("invalid key format")
var ErrInvalidSignature = errors.New("invalid signature")
// type for verifying signatures
type Verifier interface {
// verify hashed data with this signing key
// return nil on valid signature otherwise error
VerifyHash(data, sig []byte) error
// verify an unhashed piece of data by hashing it and calling VerifyHash
Verify(data, sig []byte) error
}
// key for verifying data
type SigningPublicKey interface {
// create new Verifier to verify the validity of signatures
// return verifier or nil and error if key format is invalid
NewVerifier() (Verifier, error)
// get the size of this public key
Len() int
}
// type for signing data
type Signer interface {
// sign data with our private key by calling SignHash after hashing the data we are given
// return signature or nil signature and error if an error happened
Sign(data []byte) (sig []byte, err error)
// sign hash of data with our private key
// return signature or nil signature and error if an error happened
SignHash(h []byte) (sig []byte, err error)
}
// key for signing data
type SigningPrivateKey interface {
// create a new signer to sign data
// return signer or nil and error if key format is invalid
NewSigner() (Signer, error)
Len() int
}

View File

@ -2,6 +2,7 @@ package stdi2p
import (
"encoding/binary"
"github.com/bounce-chat/go-i2p/lib/crypto"
)
const (
@ -63,28 +64,29 @@ func (c KeyCert) Data() []byte {
}
// get the signing public key from this key cert
func (c KeyCert) SigningPublicKey() (k SigningPublicKey) {
func (c KeyCert) SigningPublicKey() (k crypto.SigningPublicKey) {
data := c.Data()
ktype := binary.BigEndian.Uint16(data[:2])
// set data to be the key data now
data = data[4:]
// determine the key type
if ktype == KEYCERT_SIGN_DSA_SHA1 {
var pk DSAPublicKey
var pk crypto.DSAPublicKey
copy(pk[:], data[:pk.Len()])
k = pk
} else if ktype == KEYCERT_SIGN_P256 {
var pk ECP256PublicKey
var pk crypto.ECP256PublicKey
copy(pk[:], data[:pk.Len()])
k = pk
} else if ktype == KEYCERT_SIGN_P384 {
var pk ECP384PublicKey
var pk crypto.ECP384PublicKey
copy(pk[:], data[:pk.Len()])
k = pk
} else if ktype == KEYCERT_SIGN_P521 {
var pk ECP521PublicKey
var pk crypto.ECP521PublicKey
copy(pk[:], data[:pk.Len()])
k = pk
}
// TODO: rsa/eddsa
return
}

View File

@ -1,15 +1,19 @@
package stdi2p
import (
"github.com/bounce-chat/go-i2p/lib/crypto"
)
// a network endpoint inside i2p
// effectively a public key blob
type Destination []byte
// obtain public elgamal key
func (dest Destination) PublicKey() (k PublicEncryptionKey) {
func (dest Destination) PublicKey() (k crypto.PublicEncryptionKey) {
cert := dest.Certificate()
if cert.Type() == CERT_KEY {
} else {
var ek ElgPublicKey
var ek crypto.ElgPublicKey
copy(ek[:], dest[:256])
k = ek
}
@ -23,13 +27,13 @@ func (dest Destination) Certificate() Certificate {
// gets this destination's signing key
// if there is a keycert in this destination the signing key in there is used
func (dest Destination) SigningPublicKey() (k SigningPublicKey) {
func (dest Destination) SigningPublicKey() (k crypto.SigningPublicKey) {
cert := dest.Certificate()
if cert.Type() == CERT_KEY {
// we have a key certificate
k = KeyCert(cert).SigningPublicKey()
} else {
var pk DSAPublicKey
var pk crypto.DSAPublicKey
copy(pk[:], dest[256:256+128])
k = pk
}

View File

@ -1,39 +0,0 @@
package stdi2p
import (
"crypto/rand"
"github.com/bounce-chat/go-i2p/lib/crypto"
)
// AES session key
type SessionKey [32]byte
// key used for encrypting via public key cryptography
type PublicEncryptionKey interface {
// encrypt data to this public key
// return encrypted data or nil and error
Encrypt(data []byte) ([]byte, error)
}
// public encryption key
type ElgPublicKey [256]byte
// generate a new encrypter session
func (k ElgPublicKey) NewEncrypter() (enc PublicEncryptionKey, err error) {
enc, err = crypto.NewElgamalEncryption(crypto.ElgamalPublicKey(k[:]), rand.Reader)
return
}
func (k ElgPublicKey) Encrypt(data []byte) (enc []byte, err error) {
var ek PublicEncryptionKey
// TODO(psi): do we really want to generate a new encryption session every time?
ek, err = k.NewEncrypter()
if err == nil {
enc, err = ek.Encrypt(data)
}
ek = nil
return
}
// private encryption key
type ElgPrivateKey [256]byte

View File

@ -1,118 +1 @@
package stdi2p
import (
"crypto/dsa"
"crypto/ecdsa"
"crypto/elliptic"
"errors"
"github.com/bounce-chat/go-i2p/lib/crypto"
"math/big"
)
var ErrBadSignatureSize = errors.New("bad signature size")
var ErrInvalidKeyFormat = errors.New("invalid key format")
var ErrInvalidSignature = errors.New("invalid signature")
// key for verifying data
type SigningPublicKey interface {
// verify hashed data with this signing key
// return nil on valid signature otherwise error
Verify(data, sig []byte) error
// get the size of this public key
Len() int
}
// key for signing data
type SigningPrivateKey interface {
// sign data with our private key
// return signature or nil signature and error if an error happened
Sign(data []byte) (sig []byte, err error)
}
type DSAPublicKey [128]byte
type DSAPrivateKey [20]byte
// verify data with a dsa public key
func (dpk DSAPublicKey) Verify(data, sig []byte) (err error) {
if len(sig) == 40 {
k := crypto.DSAPublicKey(new(big.Int).SetBytes(dpk[:]))
r := new(big.Int).SetBytes(sig[:20])
s := new(big.Int).SetBytes(sig[20:])
if dsa.Verify(k, data, r, s) {
// valid signature
} else {
// invalid signature
err = ErrInvalidSignature
}
} else {
err = ErrBadSignatureSize
}
return
}
func (k DSAPublicKey) Len() int {
return len(k)
}
func ecVerify(c elliptic.Curve, k, data, sig []byte) (err error) {
x, y := elliptic.Unmarshal(c, k[:])
if x == nil {
err = ErrInvalidKeyFormat
} else {
pk := &ecdsa.PublicKey{c, x, y}
r, s := elliptic.Unmarshal(c, sig)
if r == nil || s == nil || ! ecdsa.Verify(pk, data, r, s) {
err = ErrInvalidSignature
}
}
return
}
type ECP256PublicKey [64]byte
type ECP256PrivateKey [32]byte
func (k ECP256PublicKey) Len() int {
return len(k)
}
func (k ECP256PublicKey) Verify(data, sig []byte) (err error) {
err = ecVerify(elliptic.P256(), k[:], data, sig)
return
}
type ECP384PublicKey [96]byte
type ECP384PrivateKey [48]byte
func (k ECP384PublicKey) Len() int {
return len(k)
}
func (k ECP384PublicKey) Verify(data, sig []byte) (err error) {
err = ecVerify(elliptic.P384(), k[:], data, sig)
return
}
type ECP521PublicKey [132]byte
type ECP521PrivateKey [66]byte
func (k ECP521PublicKey) Len() int {
return len(k)
}
func (k ECP521PublicKey) Verify(data, sig []byte) (err error) {
err = ecVerify(elliptic.P521(), k[:], data, sig)
return
}
type RSA2048PublicKey [256]byte
type RSA2048PrivateKey [512]byte
type RSA3072PublicKey [384]byte
type RSA3072PrivateKey [786]byte
type RSA4096PublicKey [512]byte
type RSA4096PrivateKey [1024]byte
type Ed25519PublicKey [32]byte
type Ed25519PrivateKey [32]byte