Replace extra25519
the build was successful
Details
the build was successful
Details
This commit is contained in:
parent
8af47de107
commit
7ef301c8b5
|
@ -56,7 +56,12 @@ func (ea *AuthApp) Init(connection tapir.Connection) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the triple-diffie-hellman exchange.
|
// Perform the triple-diffie-hellman exchange.
|
||||||
key := primitives.Perform3DH(connection.ID(), &ephemeralIdentity, remoteAuthMessage.LongTermPublicKey, remoteAuthMessage.EphemeralPublicKey, connection.IsOutbound())
|
key, err := primitives.Perform3DH(connection.ID(), &ephemeralIdentity, remoteAuthMessage.LongTermPublicKey, remoteAuthMessage.EphemeralPublicKey, connection.IsOutbound())
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed Auth Challenge %v", err)
|
||||||
|
connection.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
connection.SetEncryptionKey(key)
|
connection.SetEncryptionKey(key)
|
||||||
|
|
||||||
// We just successfully unmarshaled both of these, so we can safely ignore the err return from these functions.
|
// We just successfully unmarshaled both of these, so we can safely ignore the err return from these functions.
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -3,16 +3,14 @@ module cwtch.im/tapir
|
||||||
require (
|
require (
|
||||||
git.openprivacy.ca/openprivacy/connectivity v1.1.0
|
git.openprivacy.ca/openprivacy/connectivity v1.1.0
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.0
|
git.openprivacy.ca/openprivacy/log v1.0.0
|
||||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412
|
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/gtank/merlin v0.1.1
|
github.com/gtank/merlin v0.1.1
|
||||||
github.com/gtank/ristretto255 v0.1.2
|
github.com/gtank/ristretto255 v0.1.2
|
||||||
github.com/kr/pretty v0.2.0 // indirect
|
github.com/kr/pretty v0.2.0 // indirect
|
||||||
github.com/stretchr/testify v1.4.0 // indirect
|
github.com/stretchr/testify v1.4.0 // indirect
|
||||||
go.etcd.io/bbolt v1.3.3
|
go.etcd.io/bbolt v1.3.4
|
||||||
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a
|
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||||
)
|
)
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -2,8 +2,6 @@ git.openprivacy.ca/openprivacy/connectivity v1.1.0 h1:9PEeKuPdoIRYeA62BUkBW2BfK4
|
||||||
git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
|
git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
|
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
|
git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
|
||||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
|
|
||||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
|
|
||||||
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw=
|
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw=
|
||||||
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -26,8 +24,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a h1:aczoJ0HPNE92XKa7DrIzkNN6esOKO2TBwiiYoKcINhA=
|
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a h1:aczoJ0HPNE92XKa7DrIzkNN6esOKO2TBwiiYoKcINhA=
|
||||||
|
|
|
@ -20,7 +20,7 @@ type BaseOnionService struct {
|
||||||
id *primitives.Identity
|
id *primitives.Identity
|
||||||
privateKey ed25519.PrivateKey
|
privateKey ed25519.PrivateKey
|
||||||
ls connectivity.ListenService
|
ls connectivity.ListenService
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes a BaseOnionService with a given private key and identity
|
// Init initializes a BaseOnionService with a given private key and identity
|
||||||
|
|
|
@ -14,11 +14,15 @@ import (
|
||||||
// Alice Ephemeral <-> Bob Ephemeral
|
// Alice Ephemeral <-> Bob Ephemeral
|
||||||
//
|
//
|
||||||
// Through this, a unique session key is derived. The exchange is offline-deniable (in the context of Tapir and Onion Service)
|
// Through this, a unique session key is derived. The exchange is offline-deniable (in the context of Tapir and Onion Service)
|
||||||
func Perform3DH(longtermIdentity *Identity, ephemeralIdentity *Identity, remoteLongTermPublicKey ed25519.PublicKey, remoteEphemeralPublicKey ed25519.PublicKey, outbound bool) [32]byte {
|
func Perform3DH(longtermIdentity *Identity, ephemeralIdentity *Identity, remoteLongTermPublicKey ed25519.PublicKey, remoteEphemeralPublicKey ed25519.PublicKey, outbound bool) ([32]byte, error) {
|
||||||
// 3DH Handshake
|
// 3DH Handshake
|
||||||
l2e := longtermIdentity.EDH(remoteEphemeralPublicKey)
|
l2e, err1 := longtermIdentity.EDH(remoteEphemeralPublicKey)
|
||||||
e2l := ephemeralIdentity.EDH(remoteLongTermPublicKey)
|
e2l, err2 := ephemeralIdentity.EDH(remoteLongTermPublicKey)
|
||||||
e2e := ephemeralIdentity.EDH(remoteEphemeralPublicKey)
|
e2e, err3 := ephemeralIdentity.EDH(remoteEphemeralPublicKey)
|
||||||
|
|
||||||
|
if err1 != nil || err2 != nil || err3 != nil {
|
||||||
|
return [32]byte{}, err1
|
||||||
|
}
|
||||||
|
|
||||||
// We need to define an order for the result concatenation so that both sides derive the same key.
|
// We need to define an order for the result concatenation so that both sides derive the same key.
|
||||||
var result [96]byte
|
var result [96]byte
|
||||||
|
@ -31,5 +35,5 @@ func Perform3DH(longtermIdentity *Identity, ephemeralIdentity *Identity, remoteL
|
||||||
copy(result[32:64], l2e)
|
copy(result[32:64], l2e)
|
||||||
copy(result[64:96], e2e)
|
copy(result[64:96], e2e)
|
||||||
}
|
}
|
||||||
return sha3.Sum256(result[:])
|
return sha3.Sum256(result[:]), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,9 @@ func (i *Identity) PublicKey() ed25519.PublicKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// EDH performs a diffie-hellman operation on this identities private key with the given public key.
|
// EDH performs a diffie-hellman operation on this identities private key with the given public key.
|
||||||
func (i *Identity) EDH(key ed25519.PublicKey) []byte {
|
func (i *Identity) EDH(key ed25519.PublicKey) ([]byte, error) {
|
||||||
secret := utils.EDH(*i.edpk, key)
|
secret, err := utils.EDH(*i.edpk, key)
|
||||||
return secret[:]
|
return secret[:], err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hostname provides the onion address associated with this Identity.
|
// Hostname provides the onion address associated with this Identity.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package primitives
|
package primitives
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,9 +10,28 @@ func TestIdentity_EDH(t *testing.T) {
|
||||||
id1, _ := InitializeEphemeralIdentity()
|
id1, _ := InitializeEphemeralIdentity()
|
||||||
id2, _ := InitializeEphemeralIdentity()
|
id2, _ := InitializeEphemeralIdentity()
|
||||||
|
|
||||||
k1 := id1.EDH(id2.PublicKey())
|
k1, err1 := id1.EDH(id2.PublicKey())
|
||||||
k2 := id2.EDH(id1.PublicKey())
|
k2, err2 := id2.EDH(id1.PublicKey())
|
||||||
|
|
||||||
t.Logf("k1: %x\nk2: %x\n", k1, k2)
|
if err1 == nil && err2 == nil && subtle.ConstantTimeCompare(k1, k2) == 1 {
|
||||||
|
t.Logf("k1: %x\nk2: %x\n", k1, k2)
|
||||||
|
} else {
|
||||||
|
t.Fatalf("The derived keys should be identical")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkEDH(b *testing.B) {
|
||||||
|
id1, _ := InitializeEphemeralIdentity()
|
||||||
|
id2, _ := InitializeEphemeralIdentity()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
k1, err1 := id1.EDH(id2.PublicKey())
|
||||||
|
k2, err2 := id2.EDH(id1.PublicKey())
|
||||||
|
if err1 == nil && err2 == nil && subtle.ConstantTimeCompare(k1, k2) == 1 {
|
||||||
|
//b.Logf("k1: %x\nk2: %x\n", k1, k2)
|
||||||
|
} else {
|
||||||
|
b.Fatalf("The derived keys should be identical")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +1,95 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/agl/ed25519/extra25519"
|
"crypto/sha512"
|
||||||
"golang.org/x/crypto/curve25519"
|
"golang.org/x/crypto/curve25519"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EDH implements diffie hellman using curve25519 keys derived from ed25519 keys
|
// EDH implements diffie hellman using curve25519 keys derived from ed25519 keys
|
||||||
// NOTE: This uses a 3rd party library extra25519 as the key conversion is not in the core golang lib
|
func EDH(privateKey ed25519.PrivateKey, remotePublicKey ed25519.PublicKey) ([]byte, error) {
|
||||||
// as such this definitely needs further review.
|
|
||||||
func EDH(privateKey ed25519.PrivateKey, remotePublicKey ed25519.PublicKey) [32]byte {
|
|
||||||
var privKeyBytes [64]byte
|
var privKeyBytes [64]byte
|
||||||
var remotePubKeyBytes [32]byte
|
var remotePubKeyBytes [32]byte
|
||||||
copy(privKeyBytes[:], privateKey[:])
|
copy(privKeyBytes[:], privateKey[:])
|
||||||
copy(remotePubKeyBytes[:], remotePublicKey[:])
|
copy(remotePubKeyBytes[:], remotePublicKey[:])
|
||||||
var secret, curve25519priv, curve25519pub [32]byte
|
var curve25519priv [32]byte
|
||||||
extra25519.PrivateKeyToCurve25519(&curve25519priv, &privKeyBytes)
|
|
||||||
extra25519.PublicKeyToCurve25519(&curve25519pub, &remotePubKeyBytes)
|
PrivateKeyToCurve25519(&curve25519priv, &privKeyBytes)
|
||||||
curve25519.ScalarMult(&secret, &curve25519priv, &curve25519pub)
|
curve25519pub := ed25519PublicKeyToCurve25519(remotePublicKey)
|
||||||
return secret
|
secret, err := curve25519.X25519(curve25519priv[:], curve25519pub[:])
|
||||||
|
return secret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/FiloSottile/age/blob/master/internal/age/ssh.go#L174
|
||||||
|
// Copyright 2019 Google LLC
|
||||||
|
//
|
||||||
|
//Redistribution and use in source and binary forms, with or without
|
||||||
|
//modification, are permitted provided that the following conditions are
|
||||||
|
//met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
//notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
//copyright notice, this list of conditions and the following disclaimer
|
||||||
|
//in the documentation and/or other materials provided with the
|
||||||
|
//distribution.
|
||||||
|
// * Neither the name of Google LLC nor the names of its
|
||||||
|
//contributors may be used to endorse or promote products derived from
|
||||||
|
//this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
//A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
//OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
//LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
//DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
//THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
//OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
var curve25519P, _ = new(big.Int).SetString("57896044618658097711785492504343953926634992332820282019728792003956564819949", 10)
|
||||||
|
|
||||||
|
func ed25519PublicKeyToCurve25519(pk ed25519.PublicKey) []byte {
|
||||||
|
// ed25519.PublicKey is a little endian representation of the y-coordinate,
|
||||||
|
// with the most significant bit set based on the sign of the x-coordinate.
|
||||||
|
bigEndianY := make([]byte, ed25519.PublicKeySize)
|
||||||
|
for i, b := range pk {
|
||||||
|
bigEndianY[ed25519.PublicKeySize-i-1] = b
|
||||||
|
}
|
||||||
|
bigEndianY[0] &= 0b0111_1111
|
||||||
|
|
||||||
|
// The Montgomery u-coordinate is derived through the bilinear map
|
||||||
|
//
|
||||||
|
// u = (1 + y) / (1 - y)
|
||||||
|
//
|
||||||
|
// See https://blog.filippo.io/using-ed25519-keys-for-encryption.
|
||||||
|
y := new(big.Int).SetBytes(bigEndianY)
|
||||||
|
denom := big.NewInt(1)
|
||||||
|
denom.ModInverse(denom.Sub(denom, y), curve25519P) // 1 / (1 - y)
|
||||||
|
u := y.Mul(y.Add(y, big.NewInt(1)), denom)
|
||||||
|
u.Mod(u, curve25519P)
|
||||||
|
|
||||||
|
out := make([]byte, curve25519.PointSize)
|
||||||
|
uBytes := u.Bytes()
|
||||||
|
for i, b := range uBytes {
|
||||||
|
out[len(uBytes)-i-1] = b
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrivateKeyToCurve25519 converts an ed25519 private key into a corresponding
|
||||||
|
// curve25519 private key
|
||||||
|
func PrivateKeyToCurve25519(curve25519Private *[32]byte, privateKey *[64]byte) {
|
||||||
|
h := sha512.New()
|
||||||
|
h.Write(privateKey[:32])
|
||||||
|
digest := h.Sum(nil)
|
||||||
|
|
||||||
|
digest[0] &= 248
|
||||||
|
digest[31] &= 127
|
||||||
|
digest[31] |= 64
|
||||||
|
|
||||||
|
copy(curve25519Private[:], digest)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue