This adds SealAnonymous and OpenAnonymous functions that implement the libsodium "sealed box" functionality. Fixes golang/go#35346 Change-Id: I22455f1b83595ec8a68d1861e635bd6cb0573f44 GitHub-Last-Rev: 7d334cf861942ec63ad613b7f28fb6dd7a1f9992 GitHub-Pull-Request: golang/crypto#107 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/205241 Reviewed-by: Filippo Valsorda <filippo@golang.org> Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
182 lines
5.2 KiB
Go
182 lines
5.2 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package box
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"testing"
|
|
|
|
"golang.org/x/crypto/curve25519"
|
|
)
|
|
|
|
func TestSealOpen(t *testing.T) {
|
|
publicKey1, privateKey1, _ := GenerateKey(rand.Reader)
|
|
publicKey2, privateKey2, _ := GenerateKey(rand.Reader)
|
|
|
|
if *privateKey1 == *privateKey2 {
|
|
t.Fatalf("private keys are equal!")
|
|
}
|
|
if *publicKey1 == *publicKey2 {
|
|
t.Fatalf("public keys are equal!")
|
|
}
|
|
message := []byte("test message")
|
|
var nonce [24]byte
|
|
|
|
box := Seal(nil, message, &nonce, publicKey1, privateKey2)
|
|
opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
|
|
if !ok {
|
|
t.Fatalf("failed to open box")
|
|
}
|
|
|
|
if !bytes.Equal(opened, message) {
|
|
t.Fatalf("got %x, want %x", opened, message)
|
|
}
|
|
|
|
for i := range box {
|
|
box[i] ^= 0x40
|
|
_, ok := Open(nil, box, &nonce, publicKey2, privateKey1)
|
|
if ok {
|
|
t.Fatalf("opened box with byte %d corrupted", i)
|
|
}
|
|
box[i] ^= 0x40
|
|
}
|
|
}
|
|
|
|
func TestBox(t *testing.T) {
|
|
var privateKey1, privateKey2 [32]byte
|
|
for i := range privateKey1[:] {
|
|
privateKey1[i] = 1
|
|
}
|
|
for i := range privateKey2[:] {
|
|
privateKey2[i] = 2
|
|
}
|
|
|
|
var publicKey1 [32]byte
|
|
curve25519.ScalarBaseMult(&publicKey1, &privateKey1)
|
|
var message [64]byte
|
|
for i := range message[:] {
|
|
message[i] = 3
|
|
}
|
|
|
|
var nonce [24]byte
|
|
for i := range nonce[:] {
|
|
nonce[i] = 4
|
|
}
|
|
|
|
box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2)
|
|
|
|
// expected was generated using the C implementation of NaCl.
|
|
expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc")
|
|
|
|
if !bytes.Equal(box, expected) {
|
|
t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
|
|
}
|
|
}
|
|
|
|
func TestSealOpenAnonymous(t *testing.T) {
|
|
publicKey, privateKey, _ := GenerateKey(rand.Reader)
|
|
message := []byte("test message")
|
|
|
|
box, err := SealAnonymous(nil, message, publicKey, nil)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error sealing %v", err)
|
|
}
|
|
opened, ok := OpenAnonymous(nil, box, publicKey, privateKey)
|
|
if !ok {
|
|
t.Fatalf("failed to open box")
|
|
}
|
|
|
|
if !bytes.Equal(opened, message) {
|
|
t.Fatalf("got %x, want %x", opened, message)
|
|
}
|
|
|
|
for i := range box {
|
|
box[i] ^= 0x40
|
|
_, ok := OpenAnonymous(nil, box, publicKey, privateKey)
|
|
if ok {
|
|
t.Fatalf("opened box with byte %d corrupted", i)
|
|
}
|
|
box[i] ^= 0x40
|
|
}
|
|
|
|
// allocates new slice if out isn't long enough
|
|
out := []byte("hello")
|
|
orig := append([]byte(nil), out...)
|
|
box, err = SealAnonymous(out, message, publicKey, nil)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error sealing %v", err)
|
|
}
|
|
if !bytes.Equal(out, orig) {
|
|
t.Fatal("expected out to be unchanged")
|
|
}
|
|
if !bytes.HasPrefix(box, orig) {
|
|
t.Fatal("expected out to be coppied to returned slice")
|
|
}
|
|
_, ok = OpenAnonymous(nil, box[len(out):], publicKey, privateKey)
|
|
if !ok {
|
|
t.Fatalf("failed to open box")
|
|
}
|
|
|
|
// uses provided slice if it's long enough
|
|
out = append(make([]byte, 0, 1000), []byte("hello")...)
|
|
orig = append([]byte(nil), out...)
|
|
box, err = SealAnonymous(out, message, publicKey, nil)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error sealing %v", err)
|
|
}
|
|
if !bytes.Equal(out, orig) {
|
|
t.Fatal("expected out to be unchanged")
|
|
}
|
|
if &out[0] != &box[0] {
|
|
t.Fatal("expected box to point to out")
|
|
}
|
|
_, ok = OpenAnonymous(nil, box[len(out):], publicKey, privateKey)
|
|
if !ok {
|
|
t.Fatalf("failed to open box")
|
|
}
|
|
}
|
|
|
|
func TestSealedBox(t *testing.T) {
|
|
var privateKey [32]byte
|
|
for i := range privateKey[:] {
|
|
privateKey[i] = 1
|
|
}
|
|
|
|
var publicKey [32]byte
|
|
curve25519.ScalarBaseMult(&publicKey, &privateKey)
|
|
var message [64]byte
|
|
for i := range message[:] {
|
|
message[i] = 3
|
|
}
|
|
|
|
fakeRand := bytes.NewReader([]byte{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5})
|
|
box, err := SealAnonymous(nil, message[:], &publicKey, fakeRand)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error sealing %v", err)
|
|
}
|
|
|
|
// expected was generated using the C implementation of libsodium with a
|
|
// random implementation that always returns 5.
|
|
// https://gist.github.com/mastahyeti/942ec3f175448d68fed25018adbce5a7
|
|
expected, _ := hex.DecodeString("50a61409b1ddd0325e9b16b700e719e9772c07000b1bd7786e907c653d20495d2af1697137a53b1b1dfc9befc49b6eeb38f86be720e155eb2be61976d2efb34d67ecd44a6ad634625eb9c288bfc883431a84ab0f5557dfe673aa6f74c19f033e648a947358cfcc606397fa1747d5219a")
|
|
|
|
if !bytes.Equal(box, expected) {
|
|
t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected)
|
|
}
|
|
|
|
// box was generated using the C implementation of libsodium.
|
|
// https://gist.github.com/mastahyeti/942ec3f175448d68fed25018adbce5a7
|
|
box, _ = hex.DecodeString("3462e0640728247a6f581e3812850d6edc3dcad1ea5d8184c072f62fb65cb357e27ffa8b76f41656bc66a0882c4d359568410665746d27462a700f01e314f382edd7aae9064879b0f8ba7b88866f88f5e4fbd7649c850541877f9f33ebd25d46d9cbcce09b69a9ba07f0eb1d105d4264")
|
|
result, ok := OpenAnonymous(nil, box, &publicKey, &privateKey)
|
|
if !ok {
|
|
t.Fatalf("failed to open box")
|
|
}
|
|
if !bytes.Equal(result, message[:]) {
|
|
t.Fatalf("message didn't match, got\n%x\n, expected\n%x", result, message[:])
|
|
}
|
|
}
|