Example #1
0
// Tests whether a message can be signed, and wrapped in plain-text.
func TestMessageCleartextSignRecover(t *testing.T) {
	key, err := crypto.GenerateKey()
	if err != nil {
		t.Fatalf("failed to create crypto key: %v", err)
	}
	payload := []byte("hello world")

	msg := NewMessage(payload)
	if _, err := msg.Wrap(DefaultPoW, Options{
		From: key,
	}); err != nil {
		t.Fatalf("failed to sign message: %v", err)
	}
	if msg.Flags&signatureFlag != signatureFlag {
		t.Fatalf("signature flag mismatch: have %d, want %d", msg.Flags&signatureFlag, signatureFlag)
	}
	if bytes.Compare(msg.Payload, payload) != 0 {
		t.Fatalf("payload mismatch after signing: have 0x%x, want 0x%x", msg.Payload, payload)
	}

	pubKey := msg.Recover()
	if pubKey == nil {
		t.Fatalf("failed to recover public key")
	}
	p1 := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y)
	p2 := elliptic.Marshal(crypto.S256(), pubKey.X, pubKey.Y)
	if !bytes.Equal(p1, p2) {
		t.Fatalf("public key mismatch: have 0x%x, want 0x%x", p2, p1)
	}
}
Example #2
0
func (h *encHandshake) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) error {
	// Import the remote identity.
	h.initNonce = msg.Nonce[:]
	h.remoteID = msg.InitiatorPubkey
	rpub, err := h.remoteID.Pubkey()
	if err != nil {
		return fmt.Errorf("bad remoteID: %#v", err)
	}
	h.remotePub = ecies.ImportECDSAPublic(rpub)

	// Generate random keypair for ECDH.
	// If a private key is already set, use it instead of generating one (for testing).
	if h.randomPrivKey == nil {
		h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
		if err != nil {
			return err
		}
	}

	// Check the signature.
	token, err := h.staticSharedSecret(prv)
	if err != nil {
		return err
	}
	signedMsg := xor(token, h.initNonce)
	remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg.Signature[:])
	if err != nil {
		return err
	}
	h.remoteRandomPub, _ = importPublicKey(remoteRandomPub)
	return nil
}
Example #3
0
// makeAuthMsg creates the initiator handshake message.
func (h *encHandshake) makeAuthMsg(prv *ecdsa.PrivateKey, token []byte) (*authMsgV4, error) {
	rpub, err := h.remoteID.Pubkey()
	if err != nil {
		return nil, fmt.Errorf("bad remoteID: %v", err)
	}
	h.remotePub = ecies.ImportECDSAPublic(rpub)
	// Generate random initiator nonce.
	h.initNonce = make([]byte, shaLen)
	if _, err := rand.Read(h.initNonce); err != nil {
		return nil, err
	}
	// Generate random keypair to for ECDH.
	h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
	if err != nil {
		return nil, err
	}

	// Sign known message: static-shared-secret ^ nonce
	token, err = h.staticSharedSecret(prv)
	if err != nil {
		return nil, err
	}
	signed := xor(token, h.initNonce)
	signature, err := crypto.Sign(signed, h.randomPrivKey.ExportECDSA())
	if err != nil {
		return nil, err
	}

	msg := new(authMsgV4)
	copy(msg.Signature[:], signature)
	copy(msg.InitiatorPubkey[:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
	copy(msg.Nonce[:], h.initNonce)
	msg.Version = 4
	return msg, nil
}
Example #4
0
// Tests whether a message can be properly signed and encrypted.
func TestMessageFullCrypto(t *testing.T) {
	fromKey, err := crypto.GenerateKey()
	if err != nil {
		t.Fatalf("failed to create sender crypto key: %v", err)
	}
	toKey, err := crypto.GenerateKey()
	if err != nil {
		t.Fatalf("failed to create recipient crypto key: %v", err)
	}

	payload := []byte("hello world")
	msg := NewMessage(payload)
	envelope, err := msg.Wrap(DefaultPoW, Options{
		From: fromKey,
		To:   &toKey.PublicKey,
	})
	if err != nil {
		t.Fatalf("failed to encrypt message: %v", err)
	}
	if msg.Flags&signatureFlag != signatureFlag {
		t.Fatalf("signature flag mismatch: have %d, want %d", msg.Flags&signatureFlag, signatureFlag)
	}
	if len(msg.Signature) == 0 {
		t.Fatalf("no signature found for signed message")
	}

	out, err := envelope.Open(toKey)
	if err != nil {
		t.Fatalf("failed to open encrypted message: %v", err)
	}
	if !bytes.Equal(out.Payload, payload) {
		t.Error("payload mismatch: have 0x%x, want 0x%x", out.Payload, payload)
	}

	pubKey := out.Recover()
	if pubKey == nil {
		t.Fatalf("failed to recover public key")
	}
	p1 := elliptic.Marshal(crypto.S256(), fromKey.PublicKey.X, fromKey.PublicKey.Y)
	p2 := elliptic.Marshal(crypto.S256(), pubKey.X, pubKey.Y)
	if !bytes.Equal(p1, p2) {
		t.Fatalf("public key mismatch: have 0x%x, want 0x%x", p2, p1)
	}
}
Example #5
0
// Pubkey returns the public key represented by the node ID.
// It returns an error if the ID is not a point on the curve.
func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) {
	p := &ecdsa.PublicKey{Curve: crypto.S256(), X: new(big.Int), Y: new(big.Int)}
	half := len(id) / 2
	p.X.SetBytes(id[:half])
	p.Y.SetBytes(id[half:])
	if !p.Curve.IsOnCurve(p.X, p.Y) {
		return nil, errors.New("not a point on the S256 curve")
	}
	return p, nil
}