Skip to content
Snippets Groups Projects
Commit 9caf0b14 authored by Jake Taylor's avatar Jake Taylor :lips:
Browse files

Merge branch 'ConnectionCLI' into 'release'

Implement connection CLI

See merge request !275
parents 288b0232 4a08071a
No related branches found
No related tags found
2 merge requests!510Release,!275Implement connection CLI
...@@ -31,6 +31,14 @@ import ( ...@@ -31,6 +31,14 @@ import (
const terminator = ";" const terminator = ";"
// Error constant strings. Any changes to these should go over usages of the
// affected messages in other applications (if applicable)
const (
// ErrChannelExists is a message returned in state.Request when an
// authenticated channel exists between the partner and me.
ErrChannelExists = "Authenticated channel already established with partner"
)
// Request sends a contact request from the user identity in the imported e2e // Request sends a contact request from the user identity in the imported e2e
// structure to the passed contact, as well as the passed facts (will error if // structure to the passed contact, as well as the passed facts (will error if
// they are too long). // they are too long).
...@@ -46,8 +54,7 @@ func (s *state) Request(partner contact.Contact, myfacts fact.FactList) (id.Roun ...@@ -46,8 +54,7 @@ func (s *state) Request(partner contact.Contact, myfacts fact.FactList) (id.Roun
// check that an authenticated channel does not already exist // check that an authenticated channel does not already exist
if _, err := s.e2e.GetPartner(partner.ID); err == nil || if _, err := s.e2e.GetPartner(partner.ID); err == nil ||
!strings.Contains(err.Error(), ratchet.NoPartnerErrorStr) { !strings.Contains(err.Error(), ratchet.NoPartnerErrorStr) {
return 0, errors.Errorf("Authenticated channel already " + return 0, errors.Errorf(ErrChannelExists)
"established with partner")
} }
return s.request(partner, myfacts, false) return s.request(partner, myfacts, false)
......
...@@ -24,7 +24,7 @@ import ( ...@@ -24,7 +24,7 @@ import (
// loadOrInitBackup will build a new xxdk.E2e from existing storage // loadOrInitBackup will build a new xxdk.E2e from existing storage
// or from a new storage that it will create if none already exists // or from a new storage that it will create if none already exists
func loadOrInitBackup(backupPath string, backupPass string, password []byte, storeDir string, func loadOrInitBackup(backupPath string, backupPass string, password []byte, storeDir string,
cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
jww.INFO.Printf("Using Backup sender") jww.INFO.Printf("Using Backup sender")
// create a new client if none exist // create a new client if none exist
...@@ -92,7 +92,7 @@ func loadOrInitBackup(backupPath string, backupPass string, password []byte, sto ...@@ -92,7 +92,7 @@ func loadOrInitBackup(backupPath string, backupPass string, password []byte, sto
} }
} }
messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
......
...@@ -25,7 +25,9 @@ var broadcastCmd = &cobra.Command{ ...@@ -25,7 +25,9 @@ var broadcastCmd = &cobra.Command{
Args: cobra.NoArgs, Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmixParams, e2eParams := initParams() cmixParams, e2eParams := initParams()
client := initE2e(cmixParams, e2eParams) authCbs := makeAuthCallbacks(
viper.GetBool("unsafe-channel-creation"), e2eParams)
client := initE2e(cmixParams, e2eParams, authCbs)
// Write user contact to file // Write user contact to file
user := client.GetReceptionIdentity() user := client.GetReceptionIdentity()
......
This diff is collapsed.
...@@ -11,6 +11,7 @@ package cmd ...@@ -11,6 +11,7 @@ package cmd
import ( import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/spf13/viper"
"strconv" "strconv"
"time" "time"
...@@ -32,7 +33,9 @@ var dumpRoundsCmd = &cobra.Command{ ...@@ -32,7 +33,9 @@ var dumpRoundsCmd = &cobra.Command{
roundIDs := parseRoundIDs(args) roundIDs := parseRoundIDs(args)
cmixParams, e2eParams := initParams() cmixParams, e2eParams := initParams()
client := initE2e(cmixParams, e2eParams) authCbs := makeAuthCallbacks(
viper.GetBool("unsafe-channel-creation"), e2eParams)
client := initE2e(cmixParams, e2eParams, authCbs)
err := client.StartNetworkFollower(5 * time.Second) err := client.StartNetworkFollower(5 * time.Second)
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
......
...@@ -36,7 +36,9 @@ var ftCmd = &cobra.Command{ ...@@ -36,7 +36,9 @@ var ftCmd = &cobra.Command{
Args: cobra.NoArgs, Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmixParams, e2eParams := initParams() cmixParams, e2eParams := initParams()
client := initE2e(cmixParams, e2eParams) authCbs := makeAuthCallbacks(
viper.GetBool("unsafe-channel-creation"), e2eParams)
client := initE2e(cmixParams, e2eParams, authCbs)
// Print user's reception ID and save contact file // Print user's reception ID and save contact file
user := client.GetReceptionIdentity() user := client.GetReceptionIdentity()
......
...@@ -100,6 +100,7 @@ const ( ...@@ -100,6 +100,7 @@ const (
connectionServerTimeoutFlag = "serverTimeout" connectionServerTimeoutFlag = "serverTimeout"
connectionDisconnectFlag = "disconnect" connectionDisconnectFlag = "disconnect"
connectionAuthenticatedFlag = "authenticated" connectionAuthenticatedFlag = "authenticated"
connectionEphemeralFlag = "ephemeral"
///////////////// File Transfer subcommand flags ////////////////////////// ///////////////// File Transfer subcommand flags //////////////////////////
fileSendFlag = "sendFile" fileSendFlag = "sendFile"
......
...@@ -35,7 +35,9 @@ var groupCmd = &cobra.Command{ ...@@ -35,7 +35,9 @@ var groupCmd = &cobra.Command{
Args: cobra.NoArgs, Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmixParams, e2eParams := initParams() cmixParams, e2eParams := initParams()
client := initE2e(cmixParams, e2eParams) authCbs := makeAuthCallbacks(
viper.GetBool("unsafe-channel-creation"), e2eParams)
client := initE2e(cmixParams, e2eParams, authCbs)
// Print user's reception ID // Print user's reception ID
user := client.GetReceptionIdentity() user := client.GetReceptionIdentity()
......
...@@ -71,12 +71,10 @@ func init() { ...@@ -71,12 +71,10 @@ func init() {
rootCmd.AddCommand(initCmd) rootCmd.AddCommand(initCmd)
} }
// loadOrInitMessenger will build a new xxdk.E2e from existing storage // loadOrInitCmix will build a new xxdk.Cmix from existing storage
// or from a new storage that it will create if none already exists // or from a new storage that it will create if none already exists
func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode string, func loadOrInitCmix(password []byte, storeDir, regCode string,
cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { cmixParams xxdk.CMIXParams) *xxdk.Cmix {
jww.INFO.Printf("Using normal sender")
// create a new client if none exist // create a new client if none exist
if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) { if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) {
// Initialize from scratch // Initialize from scratch
...@@ -97,6 +95,12 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st ...@@ -97,6 +95,12 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
return net
}
// loadOrInitReceptionIdentity will build a new xxdk.ReceptionIdentity from existing storage
// or from a new storage that it will create if none already exists
func loadOrInitReceptionIdentity(forceLegacy bool, net *xxdk.Cmix) xxdk.ReceptionIdentity {
// Load or initialize xxdk.ReceptionIdentity storage // Load or initialize xxdk.ReceptionIdentity storage
identity, err := xxdk.LoadReceptionIdentity(identityStorageKey, net) identity, err := xxdk.LoadReceptionIdentity(identityStorageKey, net)
if err != nil { if err != nil {
...@@ -115,8 +119,34 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st ...@@ -115,8 +119,34 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
} }
return identity
}
// loadOrInitMessenger will build a new xxdk.E2e from existing storage
// or from a new storage that it will create if none already exists
func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode string,
cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
jww.INFO.Printf("Using normal sender")
net := loadOrInitCmix(password, storeDir, regCode, cmixParams)
identity := loadOrInitReceptionIdentity(forceLegacy, net)
messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
if err != nil {
jww.FATAL.Panicf("%+v", err)
}
return messenger
}
// loadOrInitEphemeral will build a new ephemeral xxdk.E2e.
func loadOrInitEphemeral(forceLegacy bool, password []byte, storeDir, regCode string,
cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
jww.INFO.Printf("Using ephemeral sender")
net := loadOrInitCmix(password, storeDir, regCode, cmixParams)
identity := loadOrInitReceptionIdentity(forceLegacy, net)
messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) messenger, err := xxdk.LoginEphemeral(net, cbs, identity, e2eParams)
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
...@@ -126,7 +156,7 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st ...@@ -126,7 +156,7 @@ func loadOrInitMessenger(forceLegacy bool, password []byte, storeDir, regCode st
// loadOrInitVanity will build a new xxdk.E2e from existing storage // loadOrInitVanity will build a new xxdk.E2e from existing storage
// or from a new storage that it will create if none already exists // or from a new storage that it will create if none already exists
func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string, func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string,
cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
jww.INFO.Printf("Using Vanity sender") jww.INFO.Printf("Using Vanity sender")
// create a new client if none exist // create a new client if none exist
...@@ -163,7 +193,7 @@ func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string, ...@@ -163,7 +193,7 @@ func loadOrInitVanity(password []byte, storeDir, regCode, userIdPrefix string,
} }
} }
messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
......
...@@ -24,7 +24,7 @@ import ( ...@@ -24,7 +24,7 @@ import (
// loadOrInitPrecan will build a new xxdk.E2e from existing storage // loadOrInitPrecan will build a new xxdk.E2e from existing storage
// or from a new storage that it will create if none already exists // or from a new storage that it will create if none already exists
func loadOrInitPrecan(precanId uint, password []byte, storeDir string, func loadOrInitPrecan(precanId uint, password []byte, storeDir string,
cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
jww.INFO.Printf("Using Precanned sender") jww.INFO.Printf("Using Precanned sender")
// create a new client if none exist // create a new client if none exist
...@@ -60,7 +60,7 @@ func loadOrInitPrecan(precanId uint, password []byte, storeDir string, ...@@ -60,7 +60,7 @@ func loadOrInitPrecan(precanId uint, password []byte, storeDir string,
} }
} }
messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
......
...@@ -22,7 +22,7 @@ import ( ...@@ -22,7 +22,7 @@ import (
// loadOrInitProto will build a new xxdk.E2e from existing storage // loadOrInitProto will build a new xxdk.E2e from existing storage
// or from a new storage that it will create if none already exists // or from a new storage that it will create if none already exists
func loadOrInitProto(protoUserPath string, password []byte, storeDir string, func loadOrInitProto(protoUserPath string, password []byte, storeDir string,
cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams, cbs xxdk.AuthCallbacks) *xxdk.E2e {
jww.INFO.Printf("Using Proto sender") jww.INFO.Printf("Using Proto sender")
// create a new client if none exist // create a new client if none exist
...@@ -70,7 +70,7 @@ func loadOrInitProto(protoUserPath string, password []byte, storeDir string, ...@@ -70,7 +70,7 @@ func loadOrInitProto(protoUserPath string, password []byte, storeDir string,
} }
} }
messenger, err := xxdk.Login(net, authCbs, identity, e2eParams) messenger, err := xxdk.Login(net, cbs, identity, e2eParams)
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
......
...@@ -42,8 +42,6 @@ import ( ...@@ -42,8 +42,6 @@ import (
// Key used for storing xxdk.ReceptionIdentity objects // Key used for storing xxdk.ReceptionIdentity objects
const identityStorageKey = "identityStorageKey" const identityStorageKey = "identityStorageKey"
var authCbs *authCallbacks
// Execute adds all child commands to the root command and sets flags // Execute adds all child commands to the root command and sets flags
// appropriately. This is called by main.main(). It only needs to // appropriately. This is called by main.main(). It only needs to
// happen once to the rootCmd. // happen once to the rootCmd.
...@@ -71,7 +69,9 @@ var rootCmd = &cobra.Command{ ...@@ -71,7 +69,9 @@ var rootCmd = &cobra.Command{
cmixParams, e2eParams := initParams() cmixParams, e2eParams := initParams()
client := initE2e(cmixParams, e2eParams) authCbs := makeAuthCallbacks(
viper.GetBool("unsafe-channel-creation"), e2eParams)
client := initE2e(cmixParams, e2eParams, authCbs)
jww.INFO.Printf("Client Initialized...") jww.INFO.Printf("Client Initialized...")
...@@ -420,7 +420,8 @@ func initParams() (xxdk.CMIXParams, xxdk.E2EParams) { ...@@ -420,7 +420,8 @@ func initParams() (xxdk.CMIXParams, xxdk.E2EParams) {
} }
// initE2e returns a fully-formed xxdk.E2e object // initE2e returns a fully-formed xxdk.E2e object
func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams,
callbacks *authCallbacks) *xxdk.E2e {
initLog(viper.GetUint("logLevel"), viper.GetString("log")) initLog(viper.GetUint("logLevel"), viper.GetString("log"))
jww.INFO.Printf(Version()) jww.INFO.Printf(Version())
...@@ -436,22 +437,18 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e { ...@@ -436,22 +437,18 @@ func initE2e(cmixParams xxdk.CMIXParams, e2eParams xxdk.E2EParams) *xxdk.E2e {
forceLegacy := viper.GetBool(forceLegacyFlag) forceLegacy := viper.GetBool(forceLegacyFlag)
jww.DEBUG.Printf("sessionDir: %v", storeDir) jww.DEBUG.Printf("sessionDir: %v", storeDir)
// TODO: This probably shouldn't be initialized globally.
authCbs = makeAuthCallbacks(
viper.GetBool(unsafeChannelCreationFlag), e2eParams)
// Initialize the client of the proper type // Initialize the client of the proper type
var messenger *xxdk.E2e var messenger *xxdk.E2e
if precanId != 0 { if precanId != 0 {
messenger = loadOrInitPrecan(precanId, storePassword, storeDir, cmixParams, e2eParams) messenger = loadOrInitPrecan(precanId, storePassword, storeDir, cmixParams, e2eParams, callbacks)
} else if protoUserPath != "" { } else if protoUserPath != "" {
messenger = loadOrInitProto(protoUserPath, storePassword, storeDir, cmixParams, e2eParams) messenger = loadOrInitProto(protoUserPath, storePassword, storeDir, cmixParams, e2eParams, callbacks)
} else if userIdPrefix != "" { } else if userIdPrefix != "" {
messenger = loadOrInitVanity(storePassword, storeDir, regCode, userIdPrefix, cmixParams, e2eParams) messenger = loadOrInitVanity(storePassword, storeDir, regCode, userIdPrefix, cmixParams, e2eParams, callbacks)
} else if backupPath != "" { } else if backupPath != "" {
messenger = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams) messenger = loadOrInitBackup(backupPath, backupPass, storePassword, storeDir, cmixParams, e2eParams, callbacks)
} else { } else {
messenger = loadOrInitMessenger(forceLegacy, storePassword, storeDir, regCode, cmixParams, e2eParams) messenger = loadOrInitMessenger(forceLegacy, storePassword, storeDir, regCode, cmixParams, e2eParams, callbacks)
} }
// Handle protoUser output // Handle protoUser output
......
...@@ -34,7 +34,9 @@ var singleCmd = &cobra.Command{ ...@@ -34,7 +34,9 @@ var singleCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmixParams, e2eParams := initParams() cmixParams, e2eParams := initParams()
client := initE2e(cmixParams, e2eParams) authCbs := makeAuthCallbacks(
viper.GetBool("unsafe-channel-creation"), e2eParams)
client := initE2e(cmixParams, e2eParams, authCbs)
// Write user contact to file // Write user contact to file
user := client.GetReceptionIdentity() user := client.GetReceptionIdentity()
......
...@@ -35,7 +35,9 @@ var udCmd = &cobra.Command{ ...@@ -35,7 +35,9 @@ var udCmd = &cobra.Command{
Args: cobra.NoArgs, Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmixParams, e2eParams := initParams() cmixParams, e2eParams := initParams()
client := initE2e(cmixParams, e2eParams) authCbs := makeAuthCallbacks(
viper.GetBool("unsafe-channel-creation"), e2eParams)
client := initE2e(cmixParams, e2eParams, authCbs)
// get user and save contact to file // get user and save contact to file
user := client.GetReceptionIdentity() user := client.GetReceptionIdentity()
......
...@@ -71,8 +71,8 @@ func ConnectWithAuthentication(recipient contact.Contact, messenger *xxdk.E2e, ...@@ -71,8 +71,8 @@ func ConnectWithAuthentication(recipient contact.Contact, messenger *xxdk.E2e,
if err != nil { if err != nil {
return nil, err return nil, err
} }
return connectWithAuthentication(conn, timeStart, recipient, identity.Salt, privKey, return connectWithAuthentication(conn, timeStart, recipient,
messenger.GetRng(), messenger.GetCmix(), p) identity.Salt, privKey, messenger.GetRng(), messenger.GetCmix(), p)
} }
// connectWithAuthentication builds and sends an IdentityAuthentication to // connectWithAuthentication builds and sends an IdentityAuthentication to
...@@ -175,7 +175,7 @@ func connectWithAuthentication(conn Connection, timeStart time.Time, ...@@ -175,7 +175,7 @@ func connectWithAuthentication(conn Connection, timeStart time.Time,
// authenticate themselves. An established AuthenticatedConnection will // authenticate themselves. An established AuthenticatedConnection will
// be passed via the callback. // be passed via the callback.
func StartAuthenticatedServer(identity xxdk.ReceptionIdentity, func StartAuthenticatedServer(identity xxdk.ReceptionIdentity,
cb AuthenticatedCallback, net *xxdk.Cmix, p xxdk.E2EParams, authCb AuthenticatedCallback, net *xxdk.Cmix, p xxdk.E2EParams,
clParams ConnectionListParams) ( clParams ConnectionListParams) (
*ConnectionServer, error) { *ConnectionServer, error) {
...@@ -187,7 +187,7 @@ func StartAuthenticatedServer(identity xxdk.ReceptionIdentity, ...@@ -187,7 +187,7 @@ func StartAuthenticatedServer(identity xxdk.ReceptionIdentity,
// be passed along via the AuthenticatedCallback // be passed along via the AuthenticatedCallback
_, err := connection.RegisterListener( _, err := connection.RegisterListener(
catalog.ConnectionAuthenticationRequest, catalog.ConnectionAuthenticationRequest,
buildAuthConfirmationHandler(cb, connection)) buildAuthConfirmationHandler(authCb, connection))
if err != nil { if err != nil {
jww.ERROR.Printf( jww.ERROR.Printf(
"Failed to register listener on connection with %s: %+v", "Failed to register listener on connection with %s: %+v",
......
...@@ -21,21 +21,11 @@ func buildClientAuthRequest(newPartner partner.Manager, ...@@ -21,21 +21,11 @@ func buildClientAuthRequest(newPartner partner.Manager,
rng *fastRNG.StreamGenerator, rsaPrivKey *rsa.PrivateKey, rng *fastRNG.StreamGenerator, rsaPrivKey *rsa.PrivateKey,
salt []byte) ([]byte, error) { salt []byte) ([]byte, error) {
// The connection fingerprint (hashed) will be used as a nonce // Create signature
connectionFp := newPartner.ConnectionFingerprint().Bytes() connectionFp := newPartner.ConnectionFingerprint().Bytes()
opts := rsa.NewDefaultOptions()
h := opts.Hash.New()
h.Write(connectionFp)
nonce := h.Sum(nil)
// Sign the connection fingerprint
stream := rng.GetStream() stream := rng.GetStream()
defer stream.Close() defer stream.Close()
signature, err := rsa.Sign(stream, rsaPrivKey, signature, err := sign(stream, rsaPrivKey, connectionFp)
opts.Hash, nonce, opts)
if err != nil {
return nil, errors.Errorf("failed to sign nonce: %+v", err)
}
// Construct message // Construct message
pemEncodedRsaPubKey := rsa.CreatePublicKeyPem(rsaPrivKey.GetPublic()) pemEncodedRsaPubKey := rsa.CreatePublicKeyPem(rsaPrivKey.GetPublic())
...@@ -44,11 +34,12 @@ func buildClientAuthRequest(newPartner partner.Manager, ...@@ -44,11 +34,12 @@ func buildClientAuthRequest(newPartner partner.Manager,
RsaPubKey: pemEncodedRsaPubKey, RsaPubKey: pemEncodedRsaPubKey,
Salt: salt, Salt: salt,
} }
// Marshal message
payload, err := proto.Marshal(iar) payload, err := proto.Marshal(iar)
if err != nil { if err != nil {
return nil, errors.Errorf("failed to marshal identity request "+ return nil, errors.Errorf("failed to marshal identity request "+
"message: %+v", err) "message: %+v", err)
} }
return payload, nil return payload, nil
} }
package connect
import (
"github.com/pkg/errors"
"gitlab.com/xx_network/crypto/signature/rsa"
"gitlab.com/xx_network/crypto/xx"
"gitlab.com/xx_network/primitives/id"
"io"
)
// Sign creates a signature authenticating an identity for a connection.
func sign(rng io.Reader, rsaPrivKey *rsa.PrivateKey,
connectionFp []byte) ([]byte, error) {
// The connection fingerprint (hashed) will be used as a nonce
opts := rsa.NewDefaultOptions()
h := opts.Hash.New()
h.Write(connectionFp)
nonce := h.Sum(nil)
// Sign the connection fingerprint
return rsa.Sign(rng, rsaPrivKey,
opts.Hash, nonce, opts)
}
// Verify takes a signature for an authentication attempt
// and verifies the information.
func verify(partnerId *id.ID, partnerPubKey *rsa.PublicKey,
signature, connectionFp, salt []byte) error {
// Verify the partner's known ID against the information passed
// along the wire
partnerWireId, err := xx.NewID(partnerPubKey, salt, id.User)
if err != nil {
return err
}
if !partnerId.Cmp(partnerWireId) {
return errors.New("Failed confirm partner's ID over the wire")
}
// Hash the connection fingerprint
opts := rsa.NewDefaultOptions()
h := opts.Hash.New()
h.Write(connectionFp)
nonce := h.Sum(nil)
// Verify the signature
err = rsa.Verify(partnerPubKey, opts.Hash, nonce, signature, opts)
if err != nil {
return err
}
return nil
}
////////////////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the LICENSE file //
////////////////////////////////////////////////////////////////////////////////////////////
package connect
import (
"bytes"
"gitlab.com/xx_network/crypto/signature/rsa"
"gitlab.com/xx_network/crypto/xx"
"gitlab.com/xx_network/primitives/id"
"testing"
)
var expectedSig = []byte{139, 67, 63, 6, 185, 76, 60, 217, 163, 84, 251, 231,
197, 6, 33, 179, 53, 66, 88, 75, 105, 191, 16, 71, 126, 4, 16, 11, 41,
237, 34, 245, 242, 97, 44, 58, 154, 120, 58, 235, 240, 140, 223, 80, 232,
51, 94, 247, 226, 217, 79, 194, 215, 46, 187, 157, 55, 167, 180, 179, 12,
228, 205, 98, 132, 200, 146, 180, 142, 0, 230, 79, 0, 129, 39, 205, 67,
79, 252, 62, 187, 125, 130, 232, 125, 41, 99, 63, 106, 79, 234, 131, 109,
103, 189, 149, 45, 169, 227, 85, 164, 121, 103, 254, 19, 224, 236, 28, 187,
38, 240, 132, 192, 227, 145, 140, 56, 196, 91, 48, 228, 242, 123, 142, 123,
221, 159, 160}
type CountingReader struct {
count uint8
}
// Read just counts until 254 then starts over again
func (c *CountingReader) Read(b []byte) (int, error) {
for i := 0; i < len(b); i++ {
c.count = (c.count + 1) % 255
b[i] = c.count
}
return len(b), nil
}
func TestSignVerify_Consistency(t *testing.T) {
// use insecure seeded rng to reproduce key
notRand := &CountingReader{count: uint8(0)}
privKey, err := rsa.GenerateKey(notRand, 1024)
if err != nil {
t.Fatalf("SignVerify error: "+
"Could not generate key: %v", err.Error())
}
connFp := []byte("connFp")
signature, err := sign(notRand, privKey, connFp)
if err != nil {
t.Logf("Sign error: %v", err)
}
salt := make([]byte, 32)
copy(salt, "salt")
partnerId, err := xx.NewID(privKey.GetPublic(), salt, id.User)
if err != nil {
t.Fatalf("NewId error: %v", err)
}
err = verify(partnerId, privKey.GetPublic(), signature, connFp, salt)
if err != nil {
t.Fatalf("Verify error: %v", err)
}
if !bytes.Equal(signature, expectedSig) {
t.Errorf("Consistency test failed."+
"\nExpected: %v"+
"\nReceived: %v", expectedSig, signature)
}
}
...@@ -9,11 +9,9 @@ package connect ...@@ -9,11 +9,9 @@ package connect
import ( import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/client/e2e/receive"
"gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/crypto/signature/rsa"
"gitlab.com/xx_network/crypto/xx"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
) )
...@@ -41,7 +39,7 @@ type serverListener struct { ...@@ -41,7 +39,7 @@ type serverListener struct {
// buildAuthConfirmationHandler returns a serverListener object. // buildAuthConfirmationHandler returns a serverListener object.
// This will handle incoming identity authentication confirmations // This will handle incoming identity authentication confirmations
// via the serverListener.Hear method. A successful AuthenticatedConnection // via the serverListener.Hear method. A successful AuthenticatedConnection
// will be passed along via the serverListener.connectionCallback // will be passed along via the serverListener.connectionCallback.
func buildAuthConfirmationHandler(cb AuthenticatedCallback, func buildAuthConfirmationHandler(cb AuthenticatedCallback,
connection Connection) server { connection Connection) server {
return &serverListener{ return &serverListener{
...@@ -62,41 +60,19 @@ func (a serverListener) Hear(item receive.Message) { ...@@ -62,41 +60,19 @@ func (a serverListener) Hear(item receive.Message) {
return return
} }
// Process the PEM encoded public key to an rsa.PublicKey object // Get the new partner's connection fingerprint
partnerPubKey, err := rsa.LoadPublicKeyFromPem(iar.RsaPubKey)
if err != nil {
a.handleAuthConfirmationErr(err, item.Sender)
return
}
// Get the new partner
newPartner := a.conn.GetPartner() newPartner := a.conn.GetPartner()
connectionFp := newPartner.ConnectionFingerprint().Bytes()
// Verify the partner's known ID against the information passed // Process the PEM encoded public key to an rsa.PublicKey object
// along the wire partnerPubKey, err := rsa.LoadPublicKeyFromPem(iar.RsaPubKey)
partnerWireId, err := xx.NewID(partnerPubKey, iar.Salt, id.User)
if err != nil { if err != nil {
a.handleAuthConfirmationErr(err, item.Sender) a.handleAuthConfirmationErr(err, item.Sender)
return
} }
if !newPartner.PartnerId().Cmp(partnerWireId) { // Verify the signature within the message
err = errors.New("Failed confirm partner's ID over the wire") err = verify(newPartner.PartnerId(), partnerPubKey,
a.handleAuthConfirmationErr(err, item.Sender) iar.Signature, connectionFp, iar.Salt)
return
}
// The connection fingerprint (hashed) will be used as a nonce
connectionFp := newPartner.ConnectionFingerprint().Bytes()
// Hash the connection fingerprint
opts := rsa.NewDefaultOptions()
h := opts.Hash.New()
h.Write(connectionFp)
nonce := h.Sum(nil)
// Verify the signature
err = rsa.Verify(partnerPubKey, opts.Hash, nonce, iar.Signature, opts)
if err != nil { if err != nil {
a.handleAuthConfirmationErr(err, item.Sender) a.handleAuthConfirmationErr(err, item.Sender)
return return
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment