completed the test. FAIL now. it crashes at diffie-hellman. ECIES -> secp256k1-go panics

This commit is contained in:
zelig 2015-01-19 04:53:48 +00:00 committed by Felix Lange
parent 076c382a74
commit 489d956283
2 changed files with 53 additions and 39 deletions

View File

@ -53,10 +53,24 @@ func newCryptoId(id ClientIdentity) (self *cryptoId, err error) {
return return
} }
// initAuth is called by peer if it initiated the connection /* startHandshake 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) { 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 // session init, common to both parties
remotePubKey = crypto.ToECDSAPub(remotePubKeyDER) remotePubKey := crypto.ToECDSAPub(remotePubKeyDER)
if remotePubKey == nil { if remotePubKey == nil {
err = fmt.Errorf("invalid remote public key") err = fmt.Errorf("invalid remote public key")
return 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 { if sessionToken, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remotePubKey), sskLen, sskLen); err != nil {
return return
} }
// this will not stay here ;)
fmt.Printf("secret generated: %v %x", len(sessionToken), sessionToken) fmt.Printf("secret generated: %v %x", len(sessionToken), sessionToken)
// tokenFlag = 0x00 // redundant // tokenFlag = 0x00 // redundant
} else { } else {
@ -93,15 +108,14 @@ func (self *cryptoId) initAuth(remotePubKeyDER, sessionToken []byte) (auth []byt
var sharedSecret = Xor(sessionToken, initNonce) var sharedSecret = Xor(sessionToken, initNonce)
// generate random keypair to use for signing // generate random keypair to use for signing
var ecdsaRandomPrvKey *ecdsa.PrivateKey if randomPrvKey, err = crypto.GenerateKey(); err != nil {
if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
return return
} }
// sign shared secret (message known to both parties): shared-secret // sign shared secret (message known to both parties): shared-secret
var signature []byte var signature []byte
// signature = sign(ecdhe-random, shared-secret) // signature = sign(ecdhe-random, shared-secret)
// uses secp256k1.Sign // uses secp256k1.Sign
if signature, err = crypto.Sign(sharedSecret, ecdsaRandomPrvKey); err != nil { if signature, err = crypto.Sign(sharedSecret, randomPrvKey); err != nil {
return return
} }
fmt.Printf("signature generated: %v %x", len(signature), signature) 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 // signed-shared-secret || H(ecdhe-random-pubk) || pubk || nonce || 0x0
copy(msg, signature) // copy signed-shared-secret copy(msg, signature) // copy signed-shared-secret
// H(ecdhe-random-pubk) // 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. // pubkey copied to the correct segment.
copy(msg[sigLen+keyLen:sigLen+2*keyLen], self.pubKeyDER) copy(msg[sigLen+keyLen:sigLen+2*keyLen], self.pubKeyDER)
// nonce is already in the slice // 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 // 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 var msg []byte
fmt.Printf("encrypted message received: %v %x\n used pubkey: %x\n", len(auth), auth, crypto.FromECDSAPub(self.pubKey)) 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, // they prove that msg is meant for me,
@ -167,7 +181,7 @@ func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.
return return
} }
// convert to ECDSA standard // convert to ECDSA standard
remoteRandomPubKey = crypto.ToECDSAPub(remoteRandomPubKeyDER) remoteRandomPubKey := crypto.ToECDSAPub(remoteRandomPubKeyDER)
if remoteRandomPubKey == nil { if remoteRandomPubKey == nil {
err = fmt.Errorf("invalid remote public key") err = fmt.Errorf("invalid remote public key")
return return
@ -181,13 +195,12 @@ func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.
return return
} }
// generate random keypair for session // generate random keypair for session
var ecdsaRandomPrvKey *ecdsa.PrivateKey if randomPrvKey, err = crypto.GenerateKey(); err != nil {
if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
return return
} }
// responder auth message // responder auth message
// E(remote-pubk, ecdhe-random-pubk || nonce || 0x0) // 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 // nonce is already in the slice
resp[resLen-1] = tokenFlag resp[resLen-1] = tokenFlag
@ -200,7 +213,7 @@ func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.
return 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 var msg []byte
// they prove that msg is meant for me, // they prove that msg is meant for me,
// I prove I possess private key if i can read it // 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 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 // 3) Now we can trust ecdhe-random-pubk to derive new keys
//ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk) //ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk)
var dhSharedSecret []byte var dhSharedSecret []byte
dhSharedSecret, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remoteRandomPubKey), sskLen, sskLen) pubKey := ecies.ImportECDSAPublic(remoteRandomPubKey)
if err != nil { if dhSharedSecret, err = ecies.ImportECDSA(privKey).GenerateShared(pubKey, sskLen, sskLen); err != nil {
return return
} }
// shared-secret = crypto.Sha3(ecdhe-shared-secret || crypto.Sha3(nonce || initiator-nonce)) // shared-secret = crypto.Sha3(ecdhe-shared-secret || crypto.Sha3(nonce || initiator-nonce))

View File

@ -1,7 +1,7 @@
package p2p package p2p
import ( import (
// "bytes" "bytes"
"fmt" "fmt"
"testing" "testing"
@ -24,31 +24,32 @@ func TestCryptoHandshake(t *testing.T) {
return return
} }
auth, initNonce, _, _ := initiator.initAuth(responder.pubKeyDER, sessionToken) auth, initNonce, randomPrvKey, randomPubKey, _ := initiator.initAuth(responder.pubKeyDER, sessionToken)
response, remoteRespNonce, remoteInitNonce, remoteRandomPubKey, _ := responder.verifyAuth(auth, sessionToken, pubInit) response, remoteRespNonce, remoteInitNonce, remoteRandomPrivKey, _ := responder.verifyAuth(auth, sessionToken, pubInit)
respNonce, randomPubKey, _, _ := initiator.verifyAuthResp(response) respNonce, remoteRandomPubKey, _, _ := 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, randomPrvKey, remoteRandomPubKey)
initSessionToken, initSecretRW, _ := initiator.newSession(initNonce, respNonce, auth, randomPubKey) respSessionToken, respSecretRW, _ := responder.newSession(remoteInitNonce, remoteRespNonce, auth, remoteRandomPrivKey, randomPubKey)
// respSessionToken, respSecretRW, _ := responder.newSession(remoteInitNonce, remoteRespNonce, auth, remoteRandomPubKey)
// if !bytes.Equal(initSessionToken, respSessionToken) { 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)
// t.Errorf("session tokens do not match")
// } if !bytes.Equal(initSessionToken, respSessionToken) {
// // aesSecret, macSecret, egressMac, ingressMac t.Errorf("session tokens do not match")
// if !bytes.Equal(initSecretRW.aesSecret, respSecretRW.aesSecret) { }
// t.Errorf("AES secrets do not match") // aesSecret, macSecret, egressMac, ingressMac
// } if !bytes.Equal(initSecretRW.aesSecret, respSecretRW.aesSecret) {
// if !bytes.Equal(initSecretRW.macSecret, respSecretRW.macSecret) { t.Errorf("AES secrets do not match")
// t.Errorf("macSecrets do not match") }
// } if !bytes.Equal(initSecretRW.macSecret, respSecretRW.macSecret) {
// if !bytes.Equal(initSecretRW.egressMac, respSecretRW.egressMac) { t.Errorf("macSecrets do not match")
// t.Errorf("egressMacs do not match") }
// } if !bytes.Equal(initSecretRW.egressMac, respSecretRW.egressMac) {
// if !bytes.Equal(initSecretRW.ingressMac, respSecretRW.ingressMac) { t.Errorf("egressMacs do not match")
// t.Errorf("ingressMacs do not match") }
// } if !bytes.Equal(initSecretRW.ingressMac, respSecretRW.ingressMac) {
t.Errorf("ingressMacs do not match")
}
} }