mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-17 13:54:33 -04:00
move crypto parts from stdi2p to crypto package
This commit is contained in:
@ -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
78
lib/crypto/ecdsa.go
Normal 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
5
lib/crypto/ed25519.go
Normal file
@ -0,0 +1,5 @@
|
||||
package crypto
|
||||
|
||||
|
||||
type Ed25519PublicKey [32]byte
|
||||
type Ed25519PrivateKey [32]byte
|
@ -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
|
||||
}
|
||||
|
@ -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
16
lib/crypto/encrypt.go
Normal 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
12
lib/crypto/rsa.go
Normal 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
49
lib/crypto/sign.go
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
|
Reference in New Issue
Block a user