fix crash

- add session token check and fallback to shared secret in responder call too
- use explicit length for the types of new messages
- fix typo resp[resLen-1] = tokenFlag
This commit is contained in:
zelig 2015-01-19 00:55:24 +00:00 committed by Felix Lange
parent b855f671a5
commit 714b955d6e
1 changed files with 29 additions and 22 deletions

View File

@ -17,7 +17,7 @@ var (
sigLen int = 65 // elliptic S256 sigLen int = 65 // elliptic S256
keyLen int = 32 // ECDSA keyLen int = 32 // ECDSA
msgLen int = sigLen + 3*keyLen + 1 // 162 msgLen int = sigLen + 3*keyLen + 1 // 162
resLen int = 65 resLen int = 65 //
) )
// aesSecret, macSecret, egressMac, ingress // aesSecret, macSecret, egressMac, ingress
@ -133,7 +133,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, sharedSecret []byte, remotePubKey *ecdsa.PublicKey) (authResp []byte, respNonce []byte, initNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, err error) { func (self *cryptoId) verifyAuth(auth, sessionToken []byte, remotePubKey *ecdsa.PublicKey) (authResp []byte, respNonce []byte, initNonce []byte, remoteRandomPubKey *ecdsa.PublicKey, 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,
@ -141,50 +141,57 @@ func (self *cryptoId) verifyAuth(auth, sharedSecret []byte, remotePubKey *ecdsa.
if msg, err = crypto.Decrypt(self.prvKey, auth); err != nil { if msg, err = crypto.Decrypt(self.prvKey, auth); err != nil {
return return
} }
fmt.Printf("\nplaintext message retrieved: %v %x\n", len(msg), msg)
// var remoteNonce []byte = msg[msgLen-skLen-1 : msgLen-1] var tokenFlag byte
if sessionToken == nil {
// no session token found means we need to generate shared secret.
// ecies shared secret is used as initial session token for new peers
// generate shared key from prv and remote pubkey
if sessionToken, err = ecies.ImportECDSA(self.prvKey).GenerateShared(ecies.ImportECDSAPublic(remotePubKey), sskLen, sskLen); err != nil {
return
}
fmt.Printf("secret generated: %v %x", len(sessionToken), sessionToken)
// tokenFlag = 0x00 // redundant
} else {
// for known peers, we use stored token from the previous session
tokenFlag = 0x01
}
// the initiator nonce is read off the end of the message
initNonce = msg[msgLen-keyLen-1 : msgLen-1] initNonce = msg[msgLen-keyLen-1 : msgLen-1]
// I prove that i own prv key (to derive shared secret, and read nonce off encrypted msg) and that I own shared secret // I prove that i own prv key (to derive shared secret, and read nonce off encrypted msg) and that I own shared secret
// they prove they own the private key belonging to ecdhe-random-pubk // they prove they own the private key belonging to ecdhe-random-pubk
var signedMsg = Xor(sharedSecret, initNonce) // we can now reconstruct the signed message and recover the peers pubkey
var signedMsg = Xor(sessionToken, initNonce)
var remoteRandomPubKeyDER []byte var remoteRandomPubKeyDER []byte
if remoteRandomPubKeyDER, err = secp256k1.RecoverPubkey(signedMsg, msg[:sigLen]); err != nil { if remoteRandomPubKeyDER, err = secp256k1.RecoverPubkey(signedMsg, msg[:sigLen]); err != nil {
return return
} }
// 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
} }
var resp = make([]byte, 2*keyLen+1) // now we find ourselves a long task too, fill it random
// generate sskLen long nonce var resp = make([]byte, resLen)
respNonce = msg[msgLen-keyLen-1 : msgLen-1] // generate keyLen long nonce
respNonce = msg[resLen-keyLen-1 : msgLen-1]
if _, err = rand.Read(respNonce); err != nil { if _, err = rand.Read(respNonce); err != nil {
return return
} }
// generate random keypair // generate random keypair for session
var ecdsaRandomPrvKey *ecdsa.PrivateKey var ecdsaRandomPrvKey *ecdsa.PrivateKey
if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil { if ecdsaRandomPrvKey, err = crypto.GenerateKey(); err != nil {
return return
} }
// var ecdsaRandomPubKey *ecdsa.PublicKey // responder auth message
// ecdsaRandomPubKey= &ecdsaRandomPrvKey.PublicKey
// 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(&ecdsaRandomPrvKey.PublicKey))
// pubkey copied to the correct segment.
copy(resp[keyLen:2*keyLen], self.pubKeyDER)
// nonce is already in the slice // nonce is already in the slice
// stick tokenFlag byte to the end resp[resLen-1] = tokenFlag
var tokenFlag byte
if sharedSecret == nil {
} else {
// for known peers, we use stored token from the previous session
tokenFlag = 0x01
}
resp[resLen] = tokenFlag
// encrypt using remote-pubk // encrypt using remote-pubk
// auth = eciesEncrypt(remote-pubk, msg) // auth = eciesEncrypt(remote-pubk, msg)