Browse Source

New crypto refactoring.

master
Bernd Fix 10 months ago
parent
commit
1f48a47d78
13 changed files with 181 additions and 147 deletions
  1. +1
    -0
      .gitignore
  2. +3
    -0
      doc/crypto/gcrypt.txt
  3. +1
    -1
      src/cmd/vanityid/main.go
  4. +10
    -10
      src/gnunet/core/peer.go
  5. +0
    -7
      src/gnunet/crypto/ecdhe.go
  6. +0
    -99
      src/gnunet/crypto/eddsa.go
  7. +7
    -0
      src/gnunet/crypto/key_exchange.go
  8. +100
    -0
      src/gnunet/crypto/keys.go
  9. +9
    -7
      src/gnunet/crypto/keys_test.go
  10. +22
    -1
      src/gnunet/crypto/signature.go
  11. +17
    -18
      src/gnunet/message/msg_core.go
  12. +5
    -4
      src/gnunet/message/msg_transport.go
  13. +6
    -0
      src/gnunet/util/rnd.go

+ 1
- 0
.gitignore View File

@@ -76,3 +76,4 @@ local.properties
/work/
/rt/
/docker/
/scratch/

+ 3
- 0
doc/crypto/gcrypt.txt View File

@@ -0,0 +1,3 @@

https://wiki.gnupg.org/ECC
https://gnupg.org/documentation/manuals/gcrypt.pdf (p.46)

+ 1
- 1
src/cmd/vanityid/main.go View File

@@ -25,7 +25,7 @@ func main() {
if err != nil || n != 32 {
panic(err)
}
prv := crypto.EdDSAPrivateKeyFromSeed(seed)
prv := crypto.PrivateKeyFromSeed(seed)
pub := prv.Public().Bytes()
id := util.EncodeBinaryToString(pub)
for _, p := range prefixes {


+ 10
- 10
src/gnunet/core/peer.go View File

@@ -19,18 +19,18 @@ type Peer interface {
*/

type Peer struct {
pub *crypto.EdDSAPublicKey
pub *crypto.PublicKey
idString string
addrList []*util.Address
prv *crypto.EdDSAPrivateKey // long-term signing key
ephPrv *crypto.EdDSAPrivateKey // ephemeral signing key
prv *crypto.PrivateKey // long-term signing key
ephPrv *crypto.PrivateKey // ephemeral signing key
ephMsg *message.EphemeralKeyMsg // ephemeral signing key message
}

func NewPeer(data []byte, local bool) (p *Peer, err error) {
p = new(Peer)
if local {
p.prv = crypto.EdDSAPrivateKeyFromSeed(data)
p.prv = crypto.PrivateKeyFromSeed(data)
p.pub = p.prv.Public()
p.ephPrv, p.ephMsg, err = message.NewEphemeralKey(p.pub.Bytes(), p.prv)
if err != nil {
@@ -38,7 +38,7 @@ func NewPeer(data []byte, local bool) (p *Peer, err error) {
}
} else {
p.prv = nil
p.pub = crypto.NewEdDSAPublicKey(data)
p.pub = crypto.NewPublicKey(data)
}
p.idString = util.EncodeBinaryToString(p.pub.Bytes())
p.addrList = make([]*util.Address, 0)
@@ -53,15 +53,15 @@ func (p *Peer) SetEphKeyMsg(msg *message.EphemeralKeyMsg) {
p.ephMsg = msg
}

func (p *Peer) EphPrvKey() *crypto.EdDSAPrivateKey {
func (p *Peer) EphPrvKey() *crypto.PrivateKey {
return p.ephPrv
}

func (p *Peer) PrvKey() *crypto.EdDSAPrivateKey {
func (p *Peer) PrvKey() *crypto.PrivateKey {
return p.prv
}

func (p *Peer) PubKey() *crypto.EdDSAPublicKey {
func (p *Peer) PubKey() *crypto.PublicKey {
return p.pub
}

@@ -81,13 +81,13 @@ func (p *Peer) AddAddress(a *util.Address) {
p.addrList = append(p.addrList, a)
}

func (p *Peer) Sign(msg []byte) ([]byte, error) {
func (p *Peer) Sign(msg []byte) (*crypto.Signature, error) {
if p.prv == nil {
return nil, fmt.Errorf("No private key")
}
return p.prv.Sign(msg)
}

func (p *Peer) Verify(msg, sig []byte) bool {
func (p *Peer) Verify(msg []byte, sig *crypto.Signature) bool {
return p.pub.Verify(msg, sig)
}

+ 0
- 7
src/gnunet/crypto/ecdhe.go View File

@@ -1,7 +0,0 @@
package crypto

import ()

func SharedSecret(prv *EdDSAPrivateKey, pub *EdDSAPublicKey) ([]byte, error) {
return nil, nil
}

+ 0
- 99
src/gnunet/crypto/eddsa.go View File

@@ -1,99 +0,0 @@
package crypto

import (
"crypto"
"crypto/rand"
"crypto/sha512"
"errors"

"gnunet/util"

"gnunet/crypto/ed25519"
)

// Error codes
var (
ErrInvalidEdDSAPrivateKeyData = errors.New("Invalid Ed25519 private key data")
)

//----------------------------------------------------------------------
// Public key
//----------------------------------------------------------------------

// EdDSAPublicKey is a Ed25519 public key.
type EdDSAPublicKey struct {
key ed25519.PublicKey
}

// NewEdDSAPublicKey sets the binary representation of a public key.
// The value is not checked for validity!
func NewEdDSAPublicKey(data []byte) *EdDSAPublicKey {
return &EdDSAPublicKey{
key: util.Clone(data),
}
}

// Bytes returns the binary representation of a public key.
func (pub *EdDSAPublicKey) Bytes() []byte {
return []byte(pub.key)
}

// Verify checks a signature of a data block.
func (pub *EdDSAPublicKey) Verify(data, sig []byte) bool {
h := sha512.New()
h.Write(data)
hv := h.Sum(nil)
return ed25519.Verify(pub.key, hv, sig)
}

//----------------------------------------------------------------------
// Private Key
//----------------------------------------------------------------------

// EdDSAPrivateKey is a Ed25519 private key.
type EdDSAPrivateKey struct {
key ed25519.PrivateKey // private key data (seed||public_key)
d []byte // HACK! "real" private key
}

// EdDSAPrivateKeyFromSeed returns a private key for a given seed.
func EdDSAPrivateKeyFromSeed(seed []byte) *EdDSAPrivateKey {
k := &EdDSAPrivateKey{
key: ed25519.NewKeyFromSeed(seed),
}
// HACK! Save the "real" private key 'd' for later use
md := sha512.Sum512(seed)
k.d = util.Reverse(md[:32])
k.d[0] = (k.d[0] & 0x3f) | 0x40
k.d[31] &= 0xf8
return k
}

// D returns the "real" private key (HACK!)
func (prv *EdDSAPrivateKey) D() []byte {
return util.Clone(prv.d)
}

// Public returns the public key for a private key.
func (prv *EdDSAPrivateKey) Public() *EdDSAPublicKey {
return &EdDSAPublicKey{
key: util.Clone(prv.key[ed25519.PublicKeySize:]),
}
}

// Sign creates a signature for a data block.
func (prv *EdDSAPrivateKey) Sign(data []byte) ([]byte, error) {
h := sha512.New()
h.Write(data)
hv := h.Sum(nil)
return prv.key.Sign(rand.Reader, hv, crypto.Hash(0))
}

// NewPeerKeypair creates a new Ed25519 key pair.
func EdDSAKeypair() (*EdDSAPublicKey, *EdDSAPrivateKey, error) {
pub, prv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, nil, err
}
return &EdDSAPublicKey{key: pub}, &EdDSAPrivateKey{key: prv}, nil
}

+ 7
- 0
src/gnunet/crypto/key_exchange.go View File

@@ -0,0 +1,7 @@
package crypto

import ()

func SharedSecret(prv *PrivateKey, pub *PublicKey) ([]byte, error) {
return nil, nil
}

+ 100
- 0
src/gnunet/crypto/keys.go View File

@@ -0,0 +1,100 @@
package crypto

import (
"crypto"
"crypto/rand"
"crypto/sha512"
"fmt"
"math/big"

"gnunet/crypto/ed25519"
"gnunet/util"
)

// Error codes
var (
ErrInvalidPrivateKeyData = fmt.Errorf("Invalid private key data")
)

//----------------------------------------------------------------------
// Public key
//----------------------------------------------------------------------

// PublicKey is a Ed25519 public key.
type PublicKey struct {
key ed25519.PublicKey
}

// NewPublicKey sets the binary representation of a public key.
// The value is not checked for validity!
func NewPublicKey(data []byte) *PublicKey {
if l := len(data); l != ed25519.PublicKeySize {
panic(fmt.Sprintf("NewPublicKey: invalid key size (%d)", l))
}
return &PublicKey{
key: util.Clone(data),
}
}

// Bytes returns the binary representation of a public key.
func (pub *PublicKey) Bytes() []byte {
return []byte(pub.key)
}

// Verify checks a signature of a message.
func (pub *PublicKey) Verify(msg []byte, sig *Signature) bool {
hv := sha512.Sum512(msg)
return ed25519.Verify(pub.key, hv[:], sig.Bytes())
}

//----------------------------------------------------------------------
// Private Key
//----------------------------------------------------------------------

// PrivateKey is a Ed25519 private key.
type PrivateKey struct {
key ed25519.PrivateKey // private key data (seed||public_key)
d *big.Int // HACK! "real" private key
}

// PrivateKeyFromSeed returns a private key for a given seed.
func PrivateKeyFromSeed(seed []byte) *PrivateKey {
k := &PrivateKey{
key: ed25519.NewKeyFromSeed(seed),
}
// HACK! Save the "real" private key 'd' for later use
md := sha512.Sum512(seed)
d := util.Reverse(md[:32])
d[0] = (d[0] & 0x3f) | 0x40
d[31] &= 0xf8
k.d = new(big.Int).SetBytes(d)
return k
}

// D returns the "real" private key (HACK!)
func (prv *PrivateKey) D() *big.Int {
return prv.d
}

// Public returns the public key for a private key.
func (prv *PrivateKey) Public() *PublicKey {
return &PublicKey{
key: util.Clone(prv.key[ed25519.PublicKeySize:]),
}
}

// Sign creates a signature for a message.
func (prv *PrivateKey) Sign(msg []byte) (*Signature, error) {
hv := sha512.Sum512(msg)
sig, err := prv.key.Sign(rand.Reader, hv[:], crypto.Hash(0))
return NewSignatureFromBytes(sig), err
}

// NewKeypair creates a new Ed25519 key pair.
func NewKeypair() (*PublicKey, *PrivateKey, error) {
pub, prv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, nil, err
}
return &PublicKey{key: pub}, &PrivateKey{key: prv}, nil
}

src/gnunet/crypto/eddsa_test.go → src/gnunet/crypto/keys_test.go View File

@@ -73,13 +73,13 @@ var (
},
*/
}
prv *EdDSAPrivateKey
pub *EdDSAPublicKey
prv *PrivateKey
pub *PublicKey
)

func TestEdDSAPrvKey(t *testing.T) {
func TestPrvKey(t *testing.T) {

prv = EdDSAPrivateKeyFromSeed(seed)
prv = PrivateKeyFromSeed(seed)
if testing.Verbose() {
prvB := prv.key[:32]
fmt.Printf("PRIVATE = %s\n", hex.EncodeToString(prvB))
@@ -100,16 +100,18 @@ func TestEdDSAPrvKey(t *testing.T) {
}
}

func TestEdDSASign(t *testing.T) {
func TestSign(t *testing.T) {
for i := range data {
sigT, err := prv.Sign(data[i])
if err != nil {
t.Fatal(err)
}
sigX := sigT.Bytes()
if testing.Verbose() {
fmt.Printf("SIG(%d)=%s\n", i, hex.EncodeToString(sigT))
fmt.Printf("SIG(%d)=%s\n", i, hex.EncodeToString(sigX))
}
if bytes.Compare(sigT, sig[i]) != 0 {
if bytes.Compare(sigX, sig[i]) != 0 {
t.Logf("SIG! = %s\n", hex.EncodeToString(sig[i]))
t.Fatal(fmt.Sprintf("Signature mismatch (%d)", i))
}


+ 22
- 1
src/gnunet/crypto/signature.go View File

@@ -1,6 +1,8 @@
package crypto

import ()
import (
"gnunet/util"
)

// Signature purpose constants
const (
@@ -34,3 +36,22 @@ const (
SIG_GNUID_TICKET // GNUid Ticket.
SIG_CREDENTIAL // GNUnet credential.
)

//----------------------------------------------------------------------
// Signature
//----------------------------------------------------------------------

type Signature struct {
// internal
data []byte
}

func NewSignatureFromBytes(data []byte) *Signature {
return &Signature{
data: util.Clone(data),
}
}

func (s *Signature) Bytes() []byte {
return s.data[:]
}

+ 17
- 18
src/gnunet/message/msg_core.go View File

@@ -27,20 +27,19 @@ type EphemeralKeyMsg struct {
}

func NewEphemeralKeyMsg() *EphemeralKeyMsg {
b := &EphKeyBlock{
SignSize: 88,
SigPurpose: crypto.SIG_ECC_KEY,
CreateTime: util.GetAbsoluteTimeNow(),
ExpireTime: util.GetAbsoluteTimeOffset(12 * time.Hour),
EphemeralKey: make([]byte, 32),
PeerID: make([]byte, 32),
}
return &EphemeralKeyMsg{
MsgSize: 160,
MsgType: CORE_EPHEMERAL_KEY,
SenderStatus: 1,
Signature: make([]byte, 64),
SignedBlock: b,
SignedBlock: &EphKeyBlock{
SignSize: 88,
SigPurpose: crypto.SIG_ECC_KEY,
CreateTime: util.GetAbsoluteTimeNow(),
ExpireTime: util.GetAbsoluteTimeOffset(12 * time.Hour),
EphemeralKey: make([]byte, 32),
PeerID: make([]byte, 32),
},
}
}

@@ -52,25 +51,25 @@ func (m *EphemeralKeyMsg) String() string {
m.SenderStatus)
}

func (m *EphemeralKeyMsg) Public() *crypto.EdDSAPublicKey {
return crypto.NewEdDSAPublicKey(m.SignedBlock.PeerID)
func (m *EphemeralKeyMsg) Public() *crypto.PublicKey {
return crypto.NewPublicKey(m.SignedBlock.PeerID)
}

func (m *EphemeralKeyMsg) Verify(pub *crypto.EdDSAPublicKey) bool {
func (m *EphemeralKeyMsg) Verify(pub *crypto.PublicKey) bool {
data, err := Marshal(m.SignedBlock)
if err != nil {
fmt.Printf("Verify: %s\n", err)
return false
}
return pub.Verify(data, m.Signature)
sig := crypto.NewSignatureFromBytes(m.Signature)
return pub.Verify(data, sig)
}

func NewEphemeralKey(peerId []byte, ltPrv *crypto.EdDSAPrivateKey) (*crypto.EdDSAPrivateKey, *EphemeralKeyMsg, error) {
func NewEphemeralKey(peerId []byte, ltPrv *crypto.PrivateKey) (*crypto.PrivateKey, *EphemeralKeyMsg, error) {
msg := NewEphemeralKeyMsg()
copy(msg.SignedBlock.PeerID, peerId)
seed := make([]byte, 32)
util.RndArray(seed)
prv := crypto.EdDSAPrivateKeyFromSeed(seed)
seed := util.NewRndArray(32)
prv := crypto.PrivateKeyFromSeed(seed)
copy(msg.SignedBlock.EphemeralKey, prv.Public().Bytes())

data, err := Marshal(msg.SignedBlock)
@@ -81,7 +80,7 @@ func NewEphemeralKey(peerId []byte, ltPrv *crypto.EdDSAPrivateKey) (*crypto.EdDS
if err != nil {
return nil, nil, err
}
msg.Signature = sig
copy(msg.Signature, sig.Bytes())

return prv, msg, nil
}

+ 5
- 4
src/gnunet/message/msg_transport.go View File

@@ -105,7 +105,7 @@ func (m *TransportPongMsg) String() string {
return fmt.Sprintf("TransportPongMsg{<unkown>,%d}", m.Challenge)
}

func (m *TransportPongMsg) Sign(prv *crypto.EdDSAPrivateKey) error {
func (m *TransportPongMsg) Sign(prv *crypto.PrivateKey) error {
data, err := Marshal(m.SignedBlock)
if err != nil {
fmt.Printf("Sign: %s\n", err)
@@ -116,17 +116,18 @@ func (m *TransportPongMsg) Sign(prv *crypto.EdDSAPrivateKey) error {
fmt.Printf("Sign: %s\n", err)
return err
}
m.Signature = sig
copy(m.Signature, sig.Bytes())
return nil
}

func (m *TransportPongMsg) Verify(pub *crypto.EdDSAPublicKey) bool {
func (m *TransportPongMsg) Verify(pub *crypto.PublicKey) bool {
data, err := Marshal(m.SignedBlock)
if err != nil {
fmt.Printf("Verify: %s\n", err)
return false
}
return pub.Verify(data, m.Signature)
sig := crypto.NewSignatureFromBytes(m.Signature)
return pub.Verify(data, sig)
}

//----------------------------------------------------------------------


+ 6
- 0
src/gnunet/util/rnd.go View File

@@ -10,6 +10,12 @@ func RndArray(b []byte) {
rand.Read(b)
}

func NewRndArray(size int) []byte {
b := make([]byte, size)
rand.Read(b)
return b
}

func RndUInt64() uint64 {
b := make([]byte, 8)
RndArray(b)


Loading…
Cancel
Save