예제 #1
0
// ECDH computes a Diffie-Hellman (DH) key exchange over the elliptic curve (EC)
// curve25519. If ownPublicKey is given it is used to check for the key
// reflection attack. Otherwise it is derived from privateKey.
func ECDH(privateKey, peersPublicKey, ownPublicKey *[32]byte) (*[32]byte, error) {
	var (
		sharedKey [32]byte
		pubKey    []byte
	)
	// check mandatory key length
	if privateKey == nil {
		return nil, log.Error("cipher: curve25519.ECDH(): privateKey == nil")
	}
	if peersPublicKey == nil {
		return nil, log.Error("cipher: curve25519.ECDH(): peersPublicKey == nil")
	}
	// check for key reflection attack
	if ownPublicKey != nil {
		pubKey = ownPublicKey[:]
	} else {
		var publicKey [32]byte
		curve25519.ScalarBaseMult(&publicKey, privateKey)
		pubKey = publicKey[:]
	}
	if bytes.Equal(pubKey, peersPublicKey[:]) {
		return nil, log.Errorf("cipher: curve25519.ECDH(): publicKey == peersPublicKey")
	}
	// perform Diffie-Hellman key exchange
	curve25519.ScalarMult(&sharedKey, privateKey, peersPublicKey)
	return &sharedKey, nil
}
예제 #2
0
파일: auth.go 프로젝트: carriercomm/repbin
// Verify an answer. secret is the own secret key, testKey is the public key to test ownership on
func Verify(answer *[AnswerSize]byte, secret *[PrivateKeySize]byte, testKey *[PublicKeySize]byte) bool {
	var sharedSecret [PublicKeySize]byte
	var timeb [8]byte
	var inChallenge [ChallengeSize]byte
	var hashIn [AnswerSize]byte
	var inHash [PrivateKeySize]byte
	t1, t2 := false, false

	copy(inChallenge[:], answer[:ChallengeSize]) // Copy full challenge
	copy(timeb[:], inChallenge[:8])              // First 8 byte of challenge are time
	copy(inHash[:], answer[ChallengeSize:])      // Copy hash
	tempPriv, _, outChallenge := genTempKey(timeb, secret)
	if *outChallenge == inChallenge {
		t1 = true
	}
	curve25519.ScalarMult(&sharedSecret, tempPriv, testKey)
	copy(hashIn[0:ChallengeSize], outChallenge[:])
	copy(hashIn[ChallengeSize:], sharedSecret[:])
	outHash := sha256.Sum256(hashIn[:])
	if inHash == outHash {
		t2 = true
	}
	if t1 && t2 {
		return true
	}
	return false
}
예제 #3
0
func (r *Ratchet) EncryptFirst(out, msg []byte, theirRatchetPublic *[32]byte) []byte {
	r.saved = make(map[[32]byte]map[uint32]savedKey)
	r.ratchet = true
	r.randBytes(r.ourRatchetPrivate[:])
	copy(r.theirRatchetPublic[:], theirRatchetPublic[:])
	copy(r.theirAuthPublic[:], theirRatchetPublic[:])

	var sharedKey [32]byte
	curve25519.ScalarMult(&sharedKey, &r.ourRatchetPrivate, &r.theirRatchetPublic)
	h := hmac.New(sha256.New, sharedKey[:])
	deriveKey(&r.rootKey, rootKeyLabel, h)
	deriveKey(&r.recvHeaderKey, headerKeyLabel, h)
	deriveKey(&r.nextSendHeaderKey, sendHeaderKeyLabel, h)
	deriveKey(&r.nextRecvHeaderKey, nextRecvHeaderKeyLabel, h)
	deriveKey(&r.recvChainKey, chainKeyLabel, h)

	var ourRatchetPublic [32]byte
	curve25519.ScalarBaseMult(&ourRatchetPublic, &r.ourRatchetPrivate)
	tag_idx := len(out)
	out = append(out, make([]byte, authSize)...)
	out = append(out, ourRatchetPublic[:]...)
	out = r.encrypt(out, msg)
	r.FillAuth(out[tag_idx:][:authSize], out[tag_idx+authSize:], theirRatchetPublic)
	return out
}
예제 #4
0
파일: panda.go 프로젝트: carriercomm/pond
func (kx *KeyExchange) exchange1() error {
	reply, err := kx.meetingPlace.Exchange(kx.Log, kx.meeting1[:], kx.message1[:], kx.ShutdownChan)
	if err != nil {
		return err
	}

	var peerDHPublic, encryptedPeerDHPublic [32]byte
	if len(reply) < len(encryptedPeerDHPublic) {
		return errors.New("panda: meeting point reply too small")
	}

	copy(encryptedPeerDHPublic[:], reply)
	rijndael.NewCipher(&kx.key).Decrypt(&peerDHPublic, &encryptedPeerDHPublic)

	curve25519.ScalarMult(&kx.sharedKey, &kx.dhPrivate, &peerDHPublic)

	paddedLen := kx.meetingPlace.Padding()
	padded := make([]byte, paddedLen-24 /* nonce */ -secretbox.Overhead)
	binary.LittleEndian.PutUint32(padded, uint32(len(kx.kxBytes)))
	copy(padded[4:], kx.kxBytes)
	if _, err := io.ReadFull(kx.rand, padded[4+len(kx.kxBytes):]); err != nil {
		return err
	}

	var nonce [24]byte
	if _, err := io.ReadFull(kx.rand, nonce[:]); err != nil {
		return err
	}

	kx.message2 = make([]byte, paddedLen)
	copy(kx.message2, nonce[:])
	secretbox.Seal(kx.message2[24:24], padded, &nonce, &kx.sharedKey)

	return nil
}
예제 #5
0
파일: addr.go 프로젝트: JonathanLogan/mute
// GetMixData decrypts the private portion of a nymaddress.
func (ad *Address) GetMixData(keysLookup KeyFunc) (*AddressPrivate, error) {
	pubkey := new([KeySize]byte)
	copy(pubkey[:], ad.MixPubKey)
	privkey := keysLookup(pubkey)
	if privkey == nil {
		return nil, ErrNoKey
	}
	sharedSecret := new([KeySize]byte)
	addrKey := new([KeySize]byte)
	copy(addrKey[:], ad.AddressKey)
	curve25519.ScalarMult(sharedSecret, privkey, addrKey)
	cr, err := lioness.New(sharedSecret[:]) // saves some bytes and is safe against tagging
	if err != nil {
		return nil, err
	}
	privmarshal, err := cr.Decrypt(ad.PrivateData)
	if err != nil {
		return nil, err
	}
	ap := new(AddressPrivate)
	_, err = asn1.Unmarshal(privmarshal, ap)
	if err != nil {
		return nil, err
	}
	return ap, nil
}
예제 #6
0
func (c *Conn) handshakeClient(handshakeHash hash.Hash, ephemeralPrivate *[32]byte) error {
	var ephemeralIdentityShared [32]byte
	curve25519.ScalarMult(&ephemeralIdentityShared, ephemeralPrivate, &c.Peer)

	digest := handshakeHash.Sum(nil)
	h := hmac.New(sha256.New, ephemeralIdentityShared[:])
	h.Write(serverProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	digestReceived := make([]byte, len(digest)+secretbox.Overhead)
	n, err := c.read(digestReceived)
	if err != nil {
		return err
	}
	if n != len(digest) {
		return shortMessageError
	}
	digestReceived = digestReceived[:n]

	if subtle.ConstantTimeCompare(digest, digestReceived) != 1 {
		return errors.New("transport: server identity incorrect")
	}

	var identityShared [32]byte
	curve25519.ScalarMult(&identityShared, &c.identity, &c.Peer)

	handshakeHash.Write(digest)
	digest = handshakeHash.Sum(digest[:0])

	h = hmac.New(sha256.New, identityShared[:])
	h.Write(clientProofMagic)
	h.Write(digest)

	finalMessage := make([]byte, 32+sha256.Size)
	copy(finalMessage, c.identityPublic[:])
	h.Sum(finalMessage[32:32])

	if _, err := c.write(finalMessage); err != nil {
		return err
	}

	return nil
}
예제 #7
0
func (e *curve25519ECDH) GenerateSharedSecret(privKey crypto.PrivateKey, pubKey crypto.PublicKey) ([]byte, error) {
	var priv, pub, secret *[32]byte

	priv = privKey.(*[32]byte)
	pub = pubKey.(*[32]byte)
	secret = new([32]byte)

	curve25519.ScalarMult(secret, priv, pub)
	return secret[:], nil
}
예제 #8
0
파일: curve25519.go 프로젝트: lewdon/quic
// ComputeSharedKey computes and returns the shared key based on the local private key and the remote public key.
func (this *c255) ComputeSharedKey(remotePublicKey []byte) (error, []byte) {
	var remote [32]byte
	if len(remotePublicKey) != 32 {
		return errors.New("ECDH : invalid Curve25519 KeyExchange"), nil
	}
	sharedKey := new([32]byte)
	copy(remote[:], remotePublicKey)
	curve25519.ScalarMult(sharedKey, &this.privateKey, &remote)
	return nil, sharedKey[:]
}
예제 #9
0
func (c *Conn) handshakeServer(handshakeHash hash.Hash, theirEphemeralPublic *[32]byte) error {
	var ephemeralIdentityShared [32]byte
	curve25519.ScalarMult(&ephemeralIdentityShared, &c.identity, theirEphemeralPublic)

	digest := handshakeHash.Sum(nil)
	h := hmac.New(sha256.New, ephemeralIdentityShared[:])
	h.Write(serverProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	if _, err := c.write(digest); err != nil {
		return err
	}

	handshakeHash.Write(digest)
	digest = handshakeHash.Sum(digest[:0])

	finalMessage := make([]byte, 32+sha256.Size+secretbox.Overhead)
	n, err := c.read(finalMessage)
	if err != nil {
		return err
	}
	if n != 32+sha256.Size {
		return shortMessageError
	}
	finalMessage = finalMessage[:n]

	copy(c.Peer[:], finalMessage[:32])
	var identityShared [32]byte
	curve25519.ScalarMult(&identityShared, &c.identity, &c.Peer)

	h = hmac.New(sha256.New, identityShared[:])
	h.Write(clientProofMagic)
	h.Write(digest)
	digest = h.Sum(digest[:0])

	if subtle.ConstantTimeCompare(digest, finalMessage[32:]) != 1 {
		return errors.New("transport: bad proof from client")
	}

	return nil
}
예제 #10
0
파일: ntor.go 프로젝트: manawenuz/obfs4
// ClientHandshake does the client side of a ntor handshake and returnes
// status, KEY_SEED, and AUTH.  If status is not true or AUTH does not match
// the value recieved from the server, the handshake MUST be aborted.
func ClientHandshake(clientKeypair *Keypair, serverPublic *PublicKey, idPublic *PublicKey, id *NodeID) (ok bool, keySeed *KeySeed, auth *Auth) {
	var notOk int
	var secretInput bytes.Buffer

	// Client side uses EXP(Y,x) | EXP(B,x)
	var exp [SharedSecretLength]byte
	curve25519.ScalarMult(&exp, clientKeypair.private.Bytes(),
		serverPublic.Bytes())
	notOk |= constantTimeIsZero(exp[:])
	secretInput.Write(exp[:])

	curve25519.ScalarMult(&exp, clientKeypair.private.Bytes(),
		idPublic.Bytes())
	notOk |= constantTimeIsZero(exp[:])
	secretInput.Write(exp[:])

	keySeed, auth = ntorCommon(secretInput, id, idPublic,
		clientKeypair.public, serverPublic)
	return notOk == 0, keySeed, auth
}
예제 #11
0
func FillAuthWith(ourAuthPrivate *[32]byte) func([]byte, []byte, *[32]byte) {
	return func(tag, data []byte, theirAuthPublic *[32]byte) {
		var sharedAuthKey [32]byte
		curve25519.ScalarMult(&sharedAuthKey, ourAuthPrivate, theirAuthPublic)

		var ourAuthPublic [32]byte
		curve25519.ScalarBaseMult(&ourAuthPublic, ourAuthPrivate)

		h := hmac.New(sha256.New, sharedAuthKey[:])
		h.Write(data)
		copy(tag, h.Sum(nil))
	}
}
예제 #12
0
파일: auth.go 프로젝트: carriercomm/repbin
// Answer an authentication challenge. Secret is the private key belonging to the public key to be tested
func Answer(challenge *[ChallengeSize]byte, secret *[PrivateKeySize]byte) *[AnswerSize]byte {
	// return challenge|hash(challenge,DH(Secret,challenge.Pub))
	var sharedSecret [PublicKeySize]byte
	var tempPub [PublicKeySize]byte
	var hashIn, answer [AnswerSize]byte
	copy(hashIn[0:ChallengeSize], challenge[:])
	copy(tempPub[:], challenge[8:])
	curve25519.ScalarMult(&sharedSecret, secret, &tempPub)
	copy(hashIn[ChallengeSize:], sharedSecret[:])
	mHash := sha256.Sum256(hashIn[:])
	copy(answer[:ChallengeSize], challenge[:])
	copy(answer[ChallengeSize:], mHash[:])
	return &answer
}
예제 #13
0
파일: ratchet.go 프로젝트: carriercomm/pond
// Encrypt acts like append() but appends an encrypted version of msg to out.
func (r *Ratchet) Encrypt(out, msg []byte) []byte {
	if r.ratchet {
		r.randBytes(r.sendRatchetPrivate[:])
		copy(r.sendHeaderKey[:], r.nextSendHeaderKey[:])

		var sharedKey, keyMaterial [32]byte
		curve25519.ScalarMult(&sharedKey, &r.sendRatchetPrivate, &r.recvRatchetPublic)
		sha := sha256.New()
		sha.Write(rootKeyUpdateLabel)
		sha.Write(r.rootKey[:])
		sha.Write(sharedKey[:])

		if r.v2 {
			sha.Sum(keyMaterial[:0])
			h := hmac.New(sha256.New, keyMaterial[:])
			deriveKey(&r.rootKey, rootKeyLabel, h)
			deriveKey(&r.nextSendHeaderKey, sendHeaderKeyLabel, h)
			deriveKey(&r.sendChainKey, chainKeyLabel, h)
		} else {
			sha.Sum(r.rootKey[:0])
			h := hmac.New(sha256.New, r.rootKey[:])
			deriveKey(&r.nextSendHeaderKey, sendHeaderKeyLabel, h)
			deriveKey(&r.sendChainKey, chainKeyLabel, h)
		}
		r.prevSendCount, r.sendCount = r.sendCount, 0
		r.ratchet = false
	}

	h := hmac.New(sha256.New, r.sendChainKey[:])
	var messageKey [32]byte
	deriveKey(&messageKey, messageKeyLabel, h)
	deriveKey(&r.sendChainKey, chainKeyStepLabel, h)

	var sendRatchetPublic [32]byte
	curve25519.ScalarBaseMult(&sendRatchetPublic, &r.sendRatchetPrivate)
	var header [headerSize]byte
	var headerNonce, messageNonce [24]byte
	r.randBytes(headerNonce[:])
	r.randBytes(messageNonce[:])

	binary.LittleEndian.PutUint32(header[0:4], r.sendCount)
	binary.LittleEndian.PutUint32(header[4:8], r.prevSendCount)
	copy(header[8:], sendRatchetPublic[:])
	copy(header[nonceInHeaderOffset:], messageNonce[:])
	out = append(out, headerNonce[:]...)
	out = secretbox.Seal(out, header[:], &headerNonce, &r.sendHeaderKey)
	r.sendCount++
	return secretbox.Seal(out, msg, &messageNonce, &messageKey)
}
예제 #14
0
func computeSharedSecretWithPasswordHash(privateKey *[32]byte, herPublicKey *[32]byte, passwordHash *[32]byte) [32]byte {

	// TODO: check this, is this right way to check for empty [32]byte?

	var computedKey [32]byte
	curve25519.ScalarMult(&computedKey, privateKey, herPublicKey)

	buff := make([]byte, 64)
	copy(buff[:32], computedKey[:])
	copy(buff[32:64], passwordHash[:])

	secret := sha256.Sum256(buff)

	return secret
}
예제 #15
0
func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
	var kp curve25519KeyPair
	if err := kp.generate(rand); err != nil {
		return nil, err
	}
	if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil {
		return nil, err
	}

	packet, err := c.readPacket()
	if err != nil {
		return nil, err
	}

	var reply kexECDHReplyMsg
	if err = Unmarshal(packet, &reply); err != nil {
		return nil, err
	}
	if len(reply.EphemeralPubKey) != 32 {
		return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
	}

	var servPub, secret [32]byte
	copy(servPub[:], reply.EphemeralPubKey)
	curve25519.ScalarMult(&secret, &kp.priv, &servPub)
	if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
		return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
	}

	h := crypto.SHA256.New()
	magics.write(h)
	writeString(h, reply.HostKey)
	writeString(h, kp.pub[:])
	writeString(h, reply.EphemeralPubKey)

	kInt := new(big.Int).SetBytes(secret[:])
	K := make([]byte, intLength(kInt))
	marshalInt(K, kInt)
	h.Write(K)

	return &kexResult{
		H:         h.Sum(nil),
		K:         K,
		HostKey:   reply.HostKey,
		Signature: reply.Signature,
		Hash:      crypto.SHA256,
	}, nil
}
예제 #16
0
파일: curve25519.go 프로젝트: enceve/crypto
func (c ecdh25519) ComputeSecret(private PrivateKey, peersPublic PublicKey) (secret []byte) {
	if len(private) != 32 {
		panic("ecdh: private key is not 32 byte")
	}
	if len(peersPublic) != 32 {
		panic("ecdh: peers public key is not 32 byte")
	}

	var sec, pri, pub [32]byte
	copy(pri[:], private)
	copy(pub[:], peersPublic)

	curve25519.ScalarMult(&sec, &pri, &pub)

	secret = sec[:]
	return
}
예제 #17
0
// CalculateSharedSecret calculates a shared secret from the given parameters. If myPrivateKey is nil, it will
// return only nils. If Nonce is nil, a nonce will be created
func CalculateSharedSecret(peerPublicKey, myPrivateKey, nonceIn *[KeySize]byte) (secret, nonceOut *[KeySize]byte) {
	var err error
	if myPrivateKey == nil || peerPublicKey == nil {
		return nil, nil
	}
	if nonceIn == nil {
		nonceOut, err = genNonce()
		if err != nil {
			return nil, nil
		}
	} else {
		nonceOut = nonceIn
	}
	secretOne := new([KeySize]byte)
	curve25519.ScalarMult(secretOne, myPrivateKey, peerPublicKey)
	return ExpandSecret(nonceOut[:], secretOne[:]), nonceOut
}
예제 #18
0
func (r *Ratchet) DecryptFirst(ciphertext []byte, ourRatchetPrivate *[32]byte) ([]byte, error) {
	r.saved = make(map[[32]byte]map[uint32]savedKey)
	if len(ciphertext) < OverheadFirst {
		return nil, errors.New("first message too short")
	}
	copy(r.ourRatchetPrivate[:], ourRatchetPrivate[:])
	copy(r.ourAuthPrivate[:], ourRatchetPrivate[:])

	tag := ciphertext[:authSize]
	var sharedKey [32]byte
	copy(r.theirRatchetPublic[:], ciphertext[authSize:][:handshakePreHeaderSize])
	curve25519.ScalarMult(&sharedKey, &r.ourRatchetPrivate, &r.theirRatchetPublic)
	h := hmac.New(sha256.New, sharedKey[:])
	deriveKey(&r.rootKey, rootKeyLabel, h)
	deriveKey(&r.sendHeaderKey, headerKeyLabel, h)
	deriveKey(&r.nextRecvHeaderKey, sendHeaderKeyLabel, h)
	deriveKey(&r.nextSendHeaderKey, nextRecvHeaderKeyLabel, h)
	deriveKey(&r.sendChainKey, chainKeyLabel, h)

	return r.decryptAndCheckAuth(tag, ciphertext[authSize:], ciphertext[authSize+handshakePreHeaderSize:])
}
예제 #19
0
파일: addr.go 프로젝트: JonathanLogan/mute
// GetPrivate gets the shared secret from a header.
func (tmp AddressTemplate) GetPrivate(header, MailboxAddress []byte) (nym, secret []byte, err error) {
	rh := new(RelayHeader)
	_, err = asn1.Unmarshal(header, rh)
	if err != nil {
		return nil, nil, err
	}
	symkey := tmp.genSymKey(rh.Nonce, rh.ReceiverPubKey, MailboxAddress)
	HMACHead := calcHmac(symkey, rh.Nonce, rh.ReceiverPubKey, rh.EncNym)
	if !hmac.Equal(rh.HMACHead, HMACHead) {
		return nil, nil, ErrHMAC
	}
	nym = decryptNym(symkey, rh.EncNym)
	recPub, recPriv := tmp.genDetermKeys(rh.Nonce, nym)
	if !bytes.Equal(recPub[:], rh.ReceiverPubKey) {
		return nil, nil, ErrBadKey
	}
	sharedSecret := new([KeySize]byte)
	senderPubKey := new([KeySize]byte)
	copy(senderPubKey[:], rh.SenderKey)
	curve25519.ScalarMult(sharedSecret, recPriv, senderPubKey)
	return nym, sharedSecret[:], nil
}
예제 #20
0
파일: addr.go 프로젝트: JonathanLogan/mute
// GetHeader returns the header for a relay message and a secret for encryption.
func (ap AddressPrivate) GetHeader() (header, secret []byte, err error) {
	pubkey, privkey, err := genKeyRandom()
	if err != nil {
		return nil, nil, err
	}
	rh := RelayHeader{
		SenderKey:      pubkey[:],
		Nonce:          ap.Nonce,
		ReceiverPubKey: ap.ReceiverPubKey,
		EncNym:         ap.EncNym,
		HMACHead:       ap.HMACHead,
	}
	d, err := asn1.Marshal(rh)
	if err != nil {
		return nil, nil, err
	}
	sharedSecret := new([KeySize]byte)
	receiverPubKey := new([KeySize]byte)
	copy(receiverPubKey[:], ap.ReceiverPubKey)
	curve25519.ScalarMult(sharedSecret, privkey, receiverPubKey)
	return d, sharedSecret[:], nil
}
예제 #21
0
func CheckAuthWith(prt ProfileRatchet) func([]byte, []byte, []byte, *[32]byte) error {
	return func(tag, data, msg []byte, ourAuthPrivate *[32]byte) error {
		var sharedAuthKey [32]byte
		message := new(proto.Message)
		unpadMsg := proto.Unpad(msg)
		err := message.Unmarshal(unpadMsg)
		if err != nil {
			return err
		}

		profile, err := prt(message.Dename, message.DenameLookup)
		if err != nil {
			return err
		}

		chatProfileBytes, err := client.GetProfileField(profile, PROFILE_FIELD_ID)
		if err != nil {
			return err
		}

		chatProfile := new(proto.Profile)
		if err := chatProfile.Unmarshal(chatProfileBytes); err != nil {
			return err
		}

		theirAuthPublic := (*[32]byte)(&chatProfile.MessageAuthKey)

		curve25519.ScalarMult(&sharedAuthKey, ourAuthPrivate, theirAuthPublic)
		h := hmac.New(sha256.New, sharedAuthKey[:])

		h.Write(data)
		if subtle.ConstantTimeCompare(tag, h.Sum(nil)[:len(tag)]) == 0 {
			return errors.New("Authentication failed: failed to reproduce envelope auth tag using the current auth pubkey from dename")
		}
		return nil
	}
}
예제 #22
0
func (c *Conn) Handshake() error {
	var ephemeralPrivate, ephemeralPublic, ephemeralShared [32]byte
	if _, err := io.ReadFull(rand.Reader, ephemeralPrivate[:]); err != nil {
		return err
	}
	curve25519.ScalarBaseMult(&ephemeralPublic, &ephemeralPrivate)

	if _, err := c.write(ephemeralPublic[:]); err != nil {
		return err
	}

	var theirEphemeralPublic [32]byte
	if n, err := c.read(theirEphemeralPublic[:]); err != nil || n != len(theirEphemeralPublic) {
		if err == nil {
			err = shortMessageError
		}
		return err
	}

	handshakeHash := sha256.New()
	if c.isServer {
		handshakeHash.Write(theirEphemeralPublic[:])
		handshakeHash.Write(ephemeralPublic[:])
	} else {
		handshakeHash.Write(ephemeralPublic[:])
		handshakeHash.Write(theirEphemeralPublic[:])
	}

	curve25519.ScalarMult(&ephemeralShared, &ephemeralPrivate, &theirEphemeralPublic)
	c.setupKeys(&ephemeralShared)

	if c.isServer {
		return c.handshakeServer(handshakeHash, &theirEphemeralPublic)
	}
	return c.handshakeClient(handshakeHash, &ephemeralPrivate)
}
예제 #23
0
func dhKeyGen(priv, pub *[32]byte) *[32]byte {
	key := new([32]byte)
	curve25519.ScalarMult(key, priv, pub)
	hashed := blake2b.Sum256(key[:])
	return &hashed
}
예제 #24
0
파일: ratchet.go 프로젝트: carriercomm/pond
// CompleteKeyExchange takes a KeyExchange message from the other party and
// establishes the ratchet.
func (r *Ratchet) CompleteKeyExchange(kx *pond.KeyExchange, isV2 bool) error {
	if r.kxPrivate0 == nil {
		return errors.New("ratchet: handshake already complete")
	}

	var public0 [32]byte
	curve25519.ScalarBaseMult(&public0, r.kxPrivate0)

	if len(kx.Dh) != len(public0) {
		return errors.New("ratchet: peer's key exchange is invalid")
	}
	if len(kx.Dh1) != len(public0) {
		return errors.New("ratchet: peer using old-form key exchange")
	}

	var amAlice bool
	switch bytes.Compare(public0[:], kx.Dh) {
	case -1:
		amAlice = true
	case 1:
		amAlice = false
	case 0:
		return errors.New("ratchet: peer echoed our own DH values back")
	}

	var theirDH [32]byte
	copy(theirDH[:], kx.Dh)

	keyMaterial := make([]byte, 0, 32*5)
	var sharedKey [32]byte
	curve25519.ScalarMult(&sharedKey, r.kxPrivate0, &theirDH)
	keyMaterial = append(keyMaterial, sharedKey[:]...)

	if amAlice {
		curve25519.ScalarMult(&sharedKey, r.MyIdentityPrivate, &theirDH)
		keyMaterial = append(keyMaterial, sharedKey[:]...)
		curve25519.ScalarMult(&sharedKey, r.kxPrivate0, r.TheirIdentityPublic)
		keyMaterial = append(keyMaterial, sharedKey[:]...)
		if !isV2 {
			keyMaterial = append(keyMaterial, r.MySigningPublic[:]...)
			keyMaterial = append(keyMaterial, r.TheirSigningPublic[:]...)
		}
	} else {
		curve25519.ScalarMult(&sharedKey, r.kxPrivate0, r.TheirIdentityPublic)
		keyMaterial = append(keyMaterial, sharedKey[:]...)
		curve25519.ScalarMult(&sharedKey, r.MyIdentityPrivate, &theirDH)
		keyMaterial = append(keyMaterial, sharedKey[:]...)
		if !isV2 {
			keyMaterial = append(keyMaterial, r.TheirSigningPublic[:]...)
			keyMaterial = append(keyMaterial, r.MySigningPublic[:]...)
		}
	}

	h := hmac.New(sha256.New, keyMaterial)
	deriveKey(&r.rootKey, rootKeyLabel, h)
	if amAlice {
		deriveKey(&r.recvHeaderKey, headerKeyLabel, h)
		deriveKey(&r.nextSendHeaderKey, sendHeaderKeyLabel, h)
		deriveKey(&r.nextRecvHeaderKey, nextRecvHeaderKeyLabel, h)
		deriveKey(&r.recvChainKey, chainKeyLabel, h)
		copy(r.recvRatchetPublic[:], kx.Dh1)
	} else {
		deriveKey(&r.sendHeaderKey, headerKeyLabel, h)
		deriveKey(&r.nextRecvHeaderKey, sendHeaderKeyLabel, h)
		deriveKey(&r.nextSendHeaderKey, nextRecvHeaderKeyLabel, h)
		deriveKey(&r.sendChainKey, chainKeyLabel, h)
		copy(r.sendRatchetPrivate[:], r.kxPrivate1[:])
	}

	r.ratchet = amAlice
	r.kxPrivate0 = nil
	r.kxPrivate1 = nil
	r.v2 = isV2

	return nil
}
예제 #25
0
파일: curve25519.go 프로젝트: smitterson/hc
// SharedSecret returns a Curve25519 shared secret derived from privateKey and otherPublicKey.
func SharedSecret(privateKey, otherPublicKey [keySize]byte) [keySize]byte {
	var k [keySize]byte
	curve25519.ScalarMult(&k, &privateKey, &otherPublicKey)

	return k
}
예제 #26
0
func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
	packet, err := c.readPacket()
	if err != nil {
		return
	}
	var kexInit kexECDHInitMsg
	if err = Unmarshal(packet, &kexInit); err != nil {
		return
	}

	if len(kexInit.ClientPubKey) != 32 {
		return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
	}

	var kp curve25519KeyPair
	if err := kp.generate(rand); err != nil {
		return nil, err
	}

	var clientPub, secret [32]byte
	copy(clientPub[:], kexInit.ClientPubKey)
	curve25519.ScalarMult(&secret, &kp.priv, &clientPub)
	if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
		return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
	}

	hostKeyBytes := priv.PublicKey().Marshal()

	h := crypto.SHA256.New()
	magics.write(h)
	writeString(h, hostKeyBytes)
	writeString(h, kexInit.ClientPubKey)
	writeString(h, kp.pub[:])

	kInt := new(big.Int).SetBytes(secret[:])
	K := make([]byte, intLength(kInt))
	marshalInt(K, kInt)
	h.Write(K)

	H := h.Sum(nil)

	sig, err := signAndMarshal(priv, rand, H)
	if err != nil {
		return nil, err
	}

	reply := kexECDHReplyMsg{
		EphemeralPubKey: kp.pub[:],
		HostKey:         hostKeyBytes,
		Signature:       sig,
	}
	if err := c.writePacket(Marshal(&reply)); err != nil {
		return nil, err
	}
	return &kexResult{
		H:         H,
		K:         K,
		HostKey:   hostKeyBytes,
		Signature: sig,
		Hash:      crypto.SHA256,
	}, nil
}
예제 #27
0
파일: ratchet.go 프로젝트: carriercomm/pond
func (r *Ratchet) Decrypt(ciphertext []byte) ([]byte, error) {
	msg, err := r.trySavedKeys(ciphertext)
	if err != nil || msg != nil {
		return msg, err
	}

	sealedHeader := ciphertext[:sealedHeaderSize]
	sealedMessage := ciphertext[sealedHeaderSize:]
	var nonce [24]byte
	copy(nonce[:], sealedHeader)
	sealedHeader = sealedHeader[len(nonce):]

	header, ok := secretbox.Open(nil, sealedHeader, &nonce, &r.recvHeaderKey)
	ok = ok && !isZeroKey(&r.recvHeaderKey)
	if ok {
		if len(header) != headerSize {
			return nil, errors.New("ratchet: incorrect header size")
		}
		messageNum := binary.LittleEndian.Uint32(header[:4])
		provisionalChainKey, messageKey, savedKeys, err := r.saveKeys(&r.recvHeaderKey, &r.recvChainKey, messageNum, r.recvCount)
		if err != nil {
			return nil, err
		}

		copy(nonce[:], header[nonceInHeaderOffset:])
		msg, ok := secretbox.Open(nil, sealedMessage, &nonce, &messageKey)
		if !ok {
			return nil, errors.New("ratchet: corrupt message")
		}

		copy(r.recvChainKey[:], provisionalChainKey[:])
		r.mergeSavedKeys(savedKeys)
		r.recvCount = messageNum + 1
		return msg, nil
	}

	header, ok = secretbox.Open(nil, sealedHeader, &nonce, &r.nextRecvHeaderKey)
	if !ok {
		return nil, errors.New("ratchet: cannot decrypt")
	}
	if len(header) != headerSize {
		return nil, errors.New("ratchet: incorrect header size")
	}

	if r.ratchet {
		return nil, errors.New("ratchet: received message encrypted to next header key without ratchet flag set")
	}

	messageNum := binary.LittleEndian.Uint32(header[:4])
	prevMessageCount := binary.LittleEndian.Uint32(header[4:8])

	_, _, oldSavedKeys, err := r.saveKeys(&r.recvHeaderKey, &r.recvChainKey, prevMessageCount, r.recvCount)
	if err != nil {
		return nil, err
	}

	var dhPublic, sharedKey, rootKey, chainKey, keyMaterial [32]byte
	copy(dhPublic[:], header[8:])

	curve25519.ScalarMult(&sharedKey, &r.sendRatchetPrivate, &dhPublic)

	sha := sha256.New()
	sha.Write(rootKeyUpdateLabel)
	sha.Write(r.rootKey[:])
	sha.Write(sharedKey[:])

	var rootKeyHMAC hash.Hash

	if r.v2 {
		sha.Sum(keyMaterial[:0])
		rootKeyHMAC = hmac.New(sha256.New, keyMaterial[:])
		deriveKey(&rootKey, rootKeyLabel, rootKeyHMAC)
	} else {
		sha.Sum(rootKey[:0])
		rootKeyHMAC = hmac.New(sha256.New, rootKey[:])
	}
	deriveKey(&chainKey, chainKeyLabel, rootKeyHMAC)

	provisionalChainKey, messageKey, savedKeys, err := r.saveKeys(&r.nextRecvHeaderKey, &chainKey, messageNum, 0)
	if err != nil {
		return nil, err
	}

	copy(nonce[:], header[nonceInHeaderOffset:])
	msg, ok = secretbox.Open(nil, sealedMessage, &nonce, &messageKey)
	if !ok {
		return nil, errors.New("ratchet: corrupt message")
	}

	copy(r.rootKey[:], rootKey[:])
	copy(r.recvChainKey[:], provisionalChainKey[:])
	copy(r.recvHeaderKey[:], r.nextRecvHeaderKey[:])
	deriveKey(&r.nextRecvHeaderKey, sendHeaderKeyLabel, rootKeyHMAC)
	for i := range r.sendRatchetPrivate {
		r.sendRatchetPrivate[i] = 0
	}
	copy(r.recvRatchetPublic[:], dhPublic[:])

	r.recvCount = messageNum + 1
	r.mergeSavedKeys(oldSavedKeys)
	r.mergeSavedKeys(savedKeys)
	r.ratchet = true

	return msg, nil
}
예제 #28
0
파일: create.go 프로젝트: nemesisqp/gotor
func (c *OnionConnection) handleCreateNTOR(circID CircuitID, data []byte, newHandshake bool) ActionableError {
	if len(data) < 84 {
		return RefuseCircuit(errors.New("didn't get enough data"), DESTROY_REASON_PROTOCOL)
	}

	_, alreadyThere := c.circuits[circID]
	if alreadyThere {
		return CloseConnection(errors.New("nope"))
	}

	fingerprint := data[0:20]
	myFingerprint := c.usedTLSCtx.Fingerprint
	for i, v := range fingerprint {
		if v != myFingerprint[i] {
			Log(LOG_INFO, "FP mismatch %s != %s", myFingerprint, fingerprint)
			return RefuseCircuit(errors.New("that's not me"), DESTROY_REASON_PROTOCOL)
		}
	}

	var key_X [32]byte
	copy(key_X[:], data[52:84])

	mExpand := []byte("ntor-curve25519-sha256-1:key_expand")
	tKey := []byte("ntor-curve25519-sha256-1:key_extract")
	tMac := []byte("ntor-curve25519-sha256-1:mac")
	tVerify := []byte("ntor-curve25519-sha256-1:verify")

	var key_y [32]byte
	CRandBytes(key_y[:])
	key_y[0] &= 248
	key_y[31] &= 127
	key_y[31] |= 64
	var key_Y [32]byte
	curve25519.ScalarBaseMult(&key_Y, &key_y)

	var buffer bytes.Buffer

	var tmpHolder [32]byte
	curve25519.ScalarMult(&tmpHolder, &key_y, &key_X)
	buffer.Write(tmpHolder[:])

	curve25519.ScalarMult(&tmpHolder, &c.parentOR.ntorPrivate, &key_X)
	buffer.Write(tmpHolder[:])

	buffer.Write(fingerprint)
	buffer.Write(c.parentOR.ntorPublic[:])
	buffer.Write(key_X[:])
	buffer.Write(key_Y[:])
	buffer.Write([]byte("ntor-curve25519-sha256-1"))

	secretInput := buffer.Bytes()
	kdf := KDFHKDF(72, secretInput, tKey, mExpand)

	hhmac := hmac.New(sha256.New, tVerify)
	hhmac.Write(secretInput)
	verify := hhmac.Sum(nil)

	buffer.Reset()
	buffer.Write(verify)
	buffer.Write(fingerprint)
	buffer.Write(c.parentOR.ntorPublic[:])
	buffer.Write(key_Y[:])
	buffer.Write(key_X[:])
	buffer.Write([]byte("ntor-curve25519-sha256-1Server"))
	authInput := buffer.Bytes()

	hhmac = hmac.New(sha256.New, tMac)
	hhmac.Write(authInput)
	auth := hhmac.Sum(nil)

	// XXX check for infinity

	cmd := CMD_CREATED2
	if !newHandshake {
		cmd = CMD_CREATED
	}
	writeCell := NewCell(c.negotiatedVersion, circID, cmd, nil)
	writeCellBuf := writeCell.Data()
	if newHandshake {
		writeCellBuf[0] = 0
		writeCellBuf[1] = 64
		copy(writeCellBuf[2:34], key_Y[:])
		copy(writeCellBuf[34:], auth)
	} else {
		copy(writeCellBuf[0:32], key_Y[:])
		copy(writeCellBuf[32:], auth)
	}

	circ := NewCircuit(circID, kdf[0:20], kdf[20:40], kdf[40:56], kdf[56:72])
	c.circuits[circID] = circ

	c.writeQueue <- writeCell.Bytes()

	return nil
}
예제 #29
0
파일: keys.go 프로젝트: carriercomm/repbin
func scalarMult(dst, in, base *Curve25519Key) {
	curve25519.ScalarMult((*[Curve25519KeySize]byte)(dst), (*[Curve25519KeySize]byte)(in), (*[Curve25519KeySize]byte)(base))
}
예제 #30
0
파일: box.go 프로젝트: Rudloff/platform
// Precompute calculates the shared key between peersPublicKey and privateKey
// and writes it to sharedKey. The shared key can be used with
// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing
// when using the same pair of keys repeatedly.
func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) {
	curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey)
	salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma)
}