aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelig <viktor.tron@gmail.com>2015-01-19 12:53:48 +0800
committerFelix Lange <fjl@twurst.com>2015-02-06 07:00:35 +0800
commit489d956283390b701473edd4a597afea2c426d41 (patch)
tree92ec206e6a1cb0c6eedbacdcdc0acafae60b396d
parent076c382a7486ebf58f33e1e0df49e92dc877ea19 (diff)
downloadgo-tangerine-489d956283390b701473edd4a597afea2c426d41.tar
go-tangerine-489d956283390b701473edd4a597afea2c426d41.tar.gz
go-tangerine-489d956283390b701473edd4a597afea2c426d41.tar.bz2
go-tangerine-489d956283390b701473edd4a597afea2c426d41.tar.lz
go-tangerine-489d956283390b701473edd4a597afea2c426d41.tar.xz
go-tangerine-489d956283390b701473edd4a597afea2c426d41.tar.zst
go-tangerine-489d956283390b701473edd4a597afea2c426d41.zip
completed the test. FAIL now. it crashes at diffie-hellman. ECIES -> secp256k1-go panics
-rw-r--r--p2p/crypto.go45
-rw-r--r--p2p/crypto_test.go55
2 files changed, 57 insertions, 43 deletions
diff --git a/p2p/crypto.go b/p2p/crypto.go
index 10c82d3a1..37c6e1fc9 100644
--- a/p2p/crypto.go
+++ b/p2p/crypto.go
@@ -53,10 +53,24 @@ func newCryptoId(id ClientIdentity) (self *cryptoId, err error) {
return
}
-// initAuth is called by peer if it initiated the connection
-func (self *cryptoId) initAuth(remotePubKeyDER, sessionToken []byte) (auth []byte, initNonce []byte, remotePubKey *ecdsa.PublicKey, err error) {
+/* startHandshake is called by peer if it initiated the connection.
+ By protocol spec, the party who initiates the connection (initiator) will send an 'auth' packet
+New: authInitiator -> E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
+ authRecipient -> E(remote-pubk, ecdhe-random-pubk || nonce || 0x0)
+
+Known: authInitiator = E(remote-pubk, S(ecdhe-random, token^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x1)
+ authRecipient = E(remote-pubk, ecdhe-random-pubk || nonce || 0x1) // token found
+ authRecipient = E(remote-pubk, ecdhe-random-pubk || nonce || 0x0) // token not found
+
+The caller provides the public key of the peer as conjuctured from lookup based on IP:port, given as user input or proven by signatures. The caller must have access to persistant information about the peers, and pass the previous session token as an argument to cryptoId.
+
+The handshake is the process by which the peers establish their connection for a session.
+
+*/
+
+func (self *cryptoId) startHandshake(remotePubKeyDER, sessionToken []byte) (auth []byte, initNonce []byte, randomPrvKey *ecdsa.PrivateKey, randomPubKey *ecdsa.PublicKey, err error) {
// session init, common to both parties
- remotePubKey = crypto.ToECDSAPub(remotePubKeyDER)
+ remotePubKey := crypto.ToECDSAPub(remotePubKeyDER)
if remotePubKey == nil {
err = fmt.Errorf("invalid remote public key")
return
@@ -70,6 +84,7 @@ func (self *cryptoId) initAuth(remotePubKeyDER, sessionToken []byte) (auth []byt
if sessionToken, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remotePubKey), sskLen, sskLen); err != nil {
return
}
+ // this will not stay here ;)
fmt.Printf("secret generated: %v %x", len(sessionToken), sessionToken)
// tokenFlag = 0x00 // redundant
} else {
@@ -93,15 +108,14 @@ func (self *cryptoId) initAuth(remotePubKeyDER, sessionToken []byte) (auth []byt
var sharedSecret = Xor(sessionToken, initNonce)
// generate random keypair to use for signing
- var ecdsaRandomPrvKey *ecdsa.PrivateKey
- if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
+ if randomPrvKey, err = crypto.GenerateKey(); err != nil {
return
}
// sign shared secret (message known to both parties): shared-secret
var signature []byte
// signature = sign(ecdhe-random, shared-secret)
// uses secp256k1.Sign
- if signature, err = crypto.Sign(sharedSecret, ecdsaRandomPrvKey); err != nil {
+ if signature, err = crypto.Sign(sharedSecret, randomPrvKey); err != nil {
return
}
fmt.Printf("signature generated: %v %x", len(signature), signature)
@@ -110,7 +124,7 @@ func (self *cryptoId) initAuth(remotePubKeyDER, sessionToken []byte) (auth []byt
// signed-shared-secret || H(ecdhe-random-pubk) || pubk || nonce || 0x0
copy(msg, signature) // copy signed-shared-secret
// H(ecdhe-random-pubk)
- copy(msg[sigLen:sigLen+keyLen], crypto.Sha3(crypto.FromECDSAPub(&ecdsaRandomPrvKey.PublicKey)))
+ copy(msg[sigLen:sigLen+keyLen], crypto.Sha3(crypto.FromECDSAPub(&randomPrvKey.PublicKey)))
// pubkey copied to the correct segment.
copy(msg[sigLen+keyLen:sigLen+2*keyLen], self.pubKeyDER)
// nonce is already in the slice
@@ -131,7 +145,7 @@ func (self *cryptoId) initAuth(remotePubKeyDER, sessionToken []byte) (auth []byt
}
// verifyAuth is called by peer if it accepted (but not initiated) the connection
-func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.PublicKey) (authResp []byte, respNonce []byte, initNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, err error) {
+func (self *cryptoId) respondToHandshake(auth, sessionToken []byte, remotePubKey *ecdsa.PublicKey) (authResp []byte, respNonce []byte, initNonce []byte, randomPrvKey *ecdsa.PrivateKey, err error) {
var msg []byte
fmt.Printf("encrypted message received: %v %x\n used pubkey: %x\n", len(auth), auth, crypto.FromECDSAPub(self.pubKey))
// they prove that msg is meant for me,
@@ -167,7 +181,7 @@ func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.
return
}
// convert to ECDSA standard
- remoteRandomPubKey = crypto.ToECDSAPub(remoteRandomPubKeyDER)
+ remoteRandomPubKey := crypto.ToECDSAPub(remoteRandomPubKeyDER)
if remoteRandomPubKey == nil {
err = fmt.Errorf("invalid remote public key")
return
@@ -181,13 +195,12 @@ func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.
return
}
// generate random keypair for session
- var ecdsaRandomPrvKey *ecdsa.PrivateKey
- if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
+ if randomPrvKey, err = crypto.GenerateKey(); err != nil {
return
}
// responder auth message
// E(remote-pubk, ecdhe-random-pubk || nonce || 0x0)
- copy(resp[:keyLen], crypto.FromECDSAPub(&ecdsaRandomPrvKey.PublicKey))
+ copy(resp[:keyLen], crypto.FromECDSAPub(&randomPrvKey.PublicKey))
// nonce is already in the slice
resp[resLen-1] = tokenFlag
@@ -200,7 +213,7 @@ func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.
return
}
-func (self *cryptoId) verifyAuthResp(auth []byte) (respNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, tokenFlag bool, err error) {
+func (self *cryptoId) completeHandshake(auth []byte) (respNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, tokenFlag bool, err error) {
var msg []byte
// they prove that msg is meant for me,
// I prove I possess private key if i can read it
@@ -221,12 +234,12 @@ func (self *cryptoId) verifyAuthResp(auth []byte) (respNonce []byte, remoteRando
return
}
-func (self *cryptoId) newSession(initNonce, respNonce, auth []byte, remoteRandomPubKey *ecdsa.PublicKey) (sessionToken []byte, rw *secretRW, err error) {
+func (self *cryptoId) newSession(initNonce, respNonce, auth []byte, privKey *ecdsa.PrivateKey, remoteRandomPubKey *ecdsa.PublicKey) (sessionToken []byte, rw *secretRW, err error) {
// 3) Now we can trust ecdhe-random-pubk to derive new keys
//ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk)
var dhSharedSecret []byte
- dhSharedSecret, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remoteRandomPubKey), sskLen, sskLen)
- if err != nil {
+ pubKey := ecies.ImportECDSAPublic(remoteRandomPubKey)
+ if dhSharedSecret, err = ecies.ImportECDSA(privKey).GenerateShared(pubKey, sskLen, sskLen); err != nil {
return
}
// shared-secret = crypto.Sha3(ecdhe-shared-secret || crypto.Sha3(nonce || initiator-nonce))
diff --git a/p2p/crypto_test.go b/p2p/crypto_test.go
index 1785b5c45..cfb2d19d1 100644
--- a/p2p/crypto_test.go
+++ b/p2p/crypto_test.go
@@ -1,7 +1,7 @@
package p2p
import (
- // "bytes"
+ "bytes"
"fmt"
"testing"
@@ -24,31 +24,32 @@ func TestCryptoHandshake(t *testing.T) {
return
}
- auth, initNonce, _, _ := initiator.initAuth(responder.pubKeyDER, sessionToken)
-
- response, remoteRespNonce, remoteInitNonce, remoteRandomPubKey, _ := responder.verifyAuth(auth, sessionToken, pubInit)
-
- respNonce, randomPubKey, _, _ := initiator.verifyAuthResp(response)
-
- fmt.Printf("%x\n%x\n%x\n%x\n%x\n%x\n%x\n%x\n", auth, initNonce, response, remoteRespNonce, remoteInitNonce, remoteRandomPubKey, respNonce, randomPubKey)
- initSessionToken, initSecretRW, _ := initiator.newSession(initNonce, respNonce, auth, randomPubKey)
- // respSessionToken, respSecretRW, _ := responder.newSession(remoteInitNonce, remoteRespNonce, auth, remoteRandomPubKey)
-
- // if !bytes.Equal(initSessionToken, respSessionToken) {
- // t.Errorf("session tokens do not match")
- // }
- // // aesSecret, macSecret, egressMac, ingressMac
- // if !bytes.Equal(initSecretRW.aesSecret, respSecretRW.aesSecret) {
- // t.Errorf("AES secrets do not match")
- // }
- // if !bytes.Equal(initSecretRW.macSecret, respSecretRW.macSecret) {
- // t.Errorf("macSecrets do not match")
- // }
- // if !bytes.Equal(initSecretRW.egressMac, respSecretRW.egressMac) {
- // t.Errorf("egressMacs do not match")
- // }
- // if !bytes.Equal(initSecretRW.ingressMac, respSecretRW.ingressMac) {
- // t.Errorf("ingressMacs do not match")
- // }
+ auth, initNonce, randomPrvKey, randomPubKey, _ := initiator.initAuth(responder.pubKeyDER, sessionToken)
+
+ response, remoteRespNonce, remoteInitNonce, remoteRandomPrivKey, _ := responder.verifyAuth(auth, sessionToken, pubInit)
+
+ respNonce, remoteRandomPubKey, _, _ := initiator.verifyAuthResp(response)
+
+ initSessionToken, initSecretRW, _ := initiator.newSession(initNonce, respNonce, auth, randomPrvKey, remoteRandomPubKey)
+ respSessionToken, respSecretRW, _ := responder.newSession(remoteInitNonce, remoteRespNonce, auth, remoteRandomPrivKey, randomPubKey)
+
+ fmt.Printf("%x\n%x\n%x\n%x\n%x\n%x\n%x\n%x\n%x\n%x\n", auth, initNonce, response, remoteRespNonce, remoteInitNonce, remoteRandomPubKey, respNonce, randomPubKey, initSessionToken, initSecretRW)
+
+ if !bytes.Equal(initSessionToken, respSessionToken) {
+ t.Errorf("session tokens do not match")
+ }
+ // aesSecret, macSecret, egressMac, ingressMac
+ if !bytes.Equal(initSecretRW.aesSecret, respSecretRW.aesSecret) {
+ t.Errorf("AES secrets do not match")
+ }
+ if !bytes.Equal(initSecretRW.macSecret, respSecretRW.macSecret) {
+ t.Errorf("macSecrets do not match")
+ }
+ if !bytes.Equal(initSecretRW.egressMac, respSecretRW.egressMac) {
+ t.Errorf("egressMacs do not match")
+ }
+ if !bytes.Equal(initSecretRW.ingressMac, respSecretRW.ingressMac) {
+ t.Errorf("ingressMacs do not match")
+ }
}