2018-10-18 17:10:29 +09:00
|
|
|
// sign_test.go -- Test harness for sign
|
|
|
|
//
|
|
|
|
// (c) 2016 Sudhi Herle <sudhi@herle.net>
|
|
|
|
//
|
|
|
|
// Licensing Terms: GPLv2
|
|
|
|
//
|
|
|
|
// If you need a commercial license for this work, please contact
|
|
|
|
// the author.
|
|
|
|
//
|
|
|
|
// This software does not come with any express or implied
|
|
|
|
// warranty; it is provided "as is". No claim is made to its
|
|
|
|
// suitability for any purpose.
|
|
|
|
|
|
|
|
package sign
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Return a temp dir in a temp-dir
|
|
|
|
func tempdir(t *testing.T) string {
|
|
|
|
assert := newAsserter(t)
|
|
|
|
|
|
|
|
var b [10]byte
|
|
|
|
|
|
|
|
dn := os.TempDir()
|
2020-03-23 10:44:40 -07:00
|
|
|
randRead(b[:])
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
tmp := path.Join(dn, fmt.Sprintf("%x", b[:]))
|
|
|
|
err := os.MkdirAll(tmp, 0755)
|
|
|
|
assert(err == nil, fmt.Sprintf("mkdir -p %s: %s", tmp, err))
|
|
|
|
|
|
|
|
//t.Logf("Tempdir is %s", tmp)
|
|
|
|
return tmp
|
|
|
|
}
|
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
var fixedPw = []byte("abc")
|
|
|
|
var badPw = []byte("def")
|
|
|
|
var nilPw []byte
|
|
|
|
|
2019-11-07 11:57:01 +01:00
|
|
|
// return a hardcoded password
|
|
|
|
func hardcodedPw() ([]byte, error) {
|
2022-04-29 21:36:39 +05:30
|
|
|
return fixedPw, nil
|
2019-11-07 11:57:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func wrongPw() ([]byte, error) {
|
2022-04-29 21:36:39 +05:30
|
|
|
return badPw, nil
|
2019-11-07 11:57:01 +01:00
|
|
|
}
|
2020-01-08 09:17:54 -08:00
|
|
|
func emptyPw() ([]byte, error) {
|
2022-04-29 21:36:39 +05:30
|
|
|
return nilPw, nil
|
2019-11-07 11:57:01 +01:00
|
|
|
}
|
|
|
|
|
2018-10-18 17:10:29 +09:00
|
|
|
// Return true if file exists, false otherwise
|
|
|
|
func fileExists(fn string) bool {
|
|
|
|
st, err := os.Stat(fn)
|
|
|
|
if err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if st.Mode().IsRegular() {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
const badsk string = `
|
|
|
|
esk: q8AP3/6C5F0zB8CLiuJsidx2gJYmrnyOmuoazEbKL5Uh+Jn/Zgw85fTbYfhjcbt48CJejBzsgPYRYR7wWECFRA==
|
|
|
|
salt: uIdTQZotfnkaLkth9jsHvoQKMWdNZuE7dgVNADrRoeY=
|
|
|
|
algo: scrypt-sha256
|
|
|
|
verify: AOFLLC6h29+mvstWtMU1/zZFwHLBMMiI4mlW9DHpYdM=
|
|
|
|
Z: 65536
|
|
|
|
r: 8
|
|
|
|
p: 1
|
|
|
|
`
|
|
|
|
|
|
|
|
// #1. Create new key pair, and read them back.
|
2020-01-08 09:17:54 -08:00
|
|
|
func TestSignSimple(t *testing.T) {
|
2018-10-18 17:10:29 +09:00
|
|
|
assert := newAsserter(t)
|
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
sk, err := NewPrivateKey()
|
|
|
|
assert(err == nil, "NewPrivateKey() fail")
|
2018-10-18 17:10:29 +09:00
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
pk := sk.PublicKey()
|
2018-10-18 17:10:29 +09:00
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
dn := t.TempDir()
|
|
|
|
bn := fmt.Sprintf("%s/t0", dn)
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
pkf := fmt.Sprintf("%s.pub", bn)
|
|
|
|
skf := fmt.Sprintf("%s.key", bn)
|
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
err = pk.Serialize(pkf, "", true)
|
|
|
|
assert(err == nil, "can't serialize pk %s", pkf)
|
|
|
|
|
|
|
|
// try to overwrite
|
|
|
|
err = pk.Serialize(pkf, "", false)
|
|
|
|
assert(err != nil, "pk %s overwritten!", pkf)
|
|
|
|
|
|
|
|
err = sk.Serialize(skf, "", true, fixedPw)
|
|
|
|
assert(err == nil, "can't serialize sk %s", skf)
|
|
|
|
|
|
|
|
err = sk.Serialize(skf, "", false, nilPw)
|
|
|
|
assert(err != nil, "sk %s overwritten!", skf)
|
|
|
|
|
2018-10-18 17:10:29 +09:00
|
|
|
// We must find these two files
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(fileExists(pkf), "missing pkf %s", pkf)
|
|
|
|
assert(fileExists(skf), "missing skf %s", skf)
|
2018-10-18 17:10:29 +09:00
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
npk, err := ReadPublicKey(pkf)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(err == nil, "ReadPK() fail")
|
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
// send the public key as private key
|
|
|
|
nsk, err := ReadPrivateKey(pkf, emptyPw)
|
2019-11-07 11:57:01 +01:00
|
|
|
assert(err != nil, "bad SK ReadSK fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
nsk, err = ReadPrivateKey(skf, emptyPw)
|
|
|
|
assert(err != nil, "ReadSK() worked with empty pw")
|
2018-10-18 17:10:29 +09:00
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
nsk, err = ReadPrivateKey(skf, wrongPw)
|
|
|
|
assert(err != nil, "ReadSK() worked with wrong pw")
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
badf := fmt.Sprintf("%s/badf.key", dn)
|
|
|
|
err = ioutil.WriteFile(badf, []byte(badsk), 0600)
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "can't write badsk: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
nsk, err = ReadPrivateKey(badf, hardcodedPw)
|
|
|
|
assert(err != nil, "decoded bad SK")
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
// Finally, with correct password it should work.
|
2022-04-29 21:36:39 +05:30
|
|
|
nsk, err = ReadPrivateKey(skf, hardcodedPw)
|
|
|
|
assert(err == nil, "ReadSK() correct pw fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
// And, deserialized keys should be identical
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(byteEq(pk.Pk, npk.Pk), "pkbytes unequal")
|
|
|
|
assert(byteEq(sk.Sk, nsk.Sk), "skbytes unequal")
|
2018-10-18 17:10:29 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
// #2. Create new key pair, sign a rand buffer and verify
|
2020-01-08 09:17:54 -08:00
|
|
|
func TestSignRandBuf(t *testing.T) {
|
2018-10-18 17:10:29 +09:00
|
|
|
assert := newAsserter(t)
|
2022-04-29 21:36:39 +05:30
|
|
|
|
|
|
|
sk, err := NewPrivateKey()
|
|
|
|
assert(err == nil, "NewPrivateKey() fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
var ck [64]byte // simulates sha512 sum
|
|
|
|
|
2020-03-23 10:44:40 -07:00
|
|
|
randRead(ck[:])
|
2018-10-18 17:10:29 +09:00
|
|
|
|
2022-04-29 21:36:39 +05:30
|
|
|
pk := sk.PublicKey()
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
ss, err := sk.SignMessage(ck[:], "")
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "sk.sign fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(ss != nil, "sig is null")
|
|
|
|
|
|
|
|
// verify sig
|
|
|
|
assert(ss.IsPKMatch(pk), "pk match fail")
|
|
|
|
|
|
|
|
// Corrupt the pkhash and see
|
2020-03-23 10:44:40 -07:00
|
|
|
randRead(ss.pkhash)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(!ss.IsPKMatch(pk), "corrupt pk match fail")
|
|
|
|
|
|
|
|
// Incorrect checksum == should fail verification
|
2020-03-23 10:44:40 -07:00
|
|
|
ok := pk.VerifyMessage(ck[:16], ss)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(!ok, "bad ck verify fail")
|
|
|
|
|
|
|
|
// proper checksum == should work
|
2020-03-23 10:44:40 -07:00
|
|
|
ok = pk.VerifyMessage(ck[:], ss)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(ok, "verify fail")
|
|
|
|
|
|
|
|
// Now sign a file
|
2022-04-29 21:36:39 +05:30
|
|
|
dn := t.TempDir()
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
var buf [8192]byte
|
|
|
|
|
|
|
|
zf := fmt.Sprintf("%s/file.dat", dn)
|
|
|
|
fd, err := os.OpenFile(zf, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "file.dat creat file: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
for i := 0; i < 8; i++ {
|
2020-03-23 10:44:40 -07:00
|
|
|
randRead(buf[:])
|
2018-10-18 17:10:29 +09:00
|
|
|
n, err := fd.Write(buf[:])
|
|
|
|
assert(err == nil, fmt.Sprintf("file.dat write fail: %s", err))
|
|
|
|
assert(n == 8192, fmt.Sprintf("file.dat i/o fail: exp 8192 saw %v", n))
|
|
|
|
}
|
|
|
|
fd.Sync()
|
|
|
|
fd.Close()
|
|
|
|
|
|
|
|
sig, err := sk.SignFile(zf)
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "file.dat sign fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(sig != nil, "file.dat sign nil")
|
|
|
|
|
|
|
|
ok, err = pk.VerifyFile(zf, sig)
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "file.dat verify fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(ok, "file.dat verify false")
|
|
|
|
|
|
|
|
// Now, serialize the signature and read it back
|
|
|
|
sf := fmt.Sprintf("%s/file.sig", dn)
|
2022-04-29 21:36:39 +05:30
|
|
|
err = sig.Serialize(sf, "", true)
|
|
|
|
assert(err == nil, "sig serialize fail: %s", err)
|
|
|
|
|
|
|
|
// now try to overwrite it
|
|
|
|
err = sig.Serialize(sf, "", false)
|
|
|
|
assert(err != nil, "sig serialize overwrote?!")
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
s2, err := ReadSignature(sf)
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "file.sig read fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(s2 != nil, "file.sig sig nil")
|
|
|
|
|
|
|
|
assert(byteEq(s2.Sig, sig.Sig), "sig compare fail")
|
|
|
|
|
|
|
|
// If we give a wrong file, verify must fail
|
|
|
|
st, err := os.Stat(zf)
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "file.dat stat fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
|
|
|
|
n := st.Size()
|
|
|
|
assert(n == 8192*8, "file.dat size fail")
|
|
|
|
|
|
|
|
os.Truncate(zf, n-1)
|
|
|
|
|
|
|
|
st, err = os.Stat(zf)
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "file.dat stat2 fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(st.Size() == (n-1), "truncate fail")
|
|
|
|
|
|
|
|
// Now verify this corrupt file
|
|
|
|
ok, err = pk.VerifyFile(zf, sig)
|
2022-04-29 21:36:39 +05:30
|
|
|
assert(err == nil, "file.dat corrupt i/o fail: %s", err)
|
2018-10-18 17:10:29 +09:00
|
|
|
assert(!ok, "file.dat corrupt verify false")
|
|
|
|
|
|
|
|
os.RemoveAll(dn)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Benchmark_Keygen(b *testing.B) {
|
|
|
|
for i := 0; i < b.N; i++ {
|
2022-04-29 21:36:39 +05:30
|
|
|
_, _ = NewPrivateKey()
|
2018-10-18 17:10:29 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Benchmark_Sig(b *testing.B) {
|
|
|
|
var sizes = [...]uint{
|
|
|
|
16,
|
|
|
|
32,
|
|
|
|
64,
|
2019-11-07 11:57:01 +01:00
|
|
|
1024,
|
|
|
|
4096,
|
2020-01-08 09:17:54 -08:00
|
|
|
256 * 1024,
|
2019-11-07 11:57:01 +01:00
|
|
|
1048576,
|
|
|
|
4 * 1048576,
|
2018-10-18 17:10:29 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
b.StopTimer()
|
2022-04-29 21:36:39 +05:30
|
|
|
sk, _ := NewPrivateKey()
|
|
|
|
pk := sk.PublicKey()
|
2018-10-18 17:10:29 +09:00
|
|
|
var sig *Signature
|
|
|
|
for _, sz := range sizes {
|
|
|
|
buf := randbuf(sz)
|
|
|
|
s0 := fmt.Sprintf("%d byte sign", sz)
|
|
|
|
s1 := fmt.Sprintf("%d byte verify", sz)
|
|
|
|
|
|
|
|
b.ResetTimer()
|
|
|
|
|
2019-10-09 14:52:34 -07:00
|
|
|
b.Run(s0, func(b *testing.B) {
|
2022-04-29 21:36:39 +05:30
|
|
|
sig = benchSign(b, buf, sk)
|
2018-10-18 17:10:29 +09:00
|
|
|
})
|
|
|
|
|
2019-10-09 14:52:34 -07:00
|
|
|
b.Run(s1, func(b *testing.B) {
|
2022-04-29 21:36:39 +05:30
|
|
|
benchVerify(b, buf, sig, pk)
|
2018-10-18 17:10:29 +09:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func benchSign(b *testing.B, buf []byte, sk *PrivateKey) (sig *Signature) {
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
sig, _ = sk.SignMessage(buf, "")
|
|
|
|
}
|
|
|
|
return sig
|
|
|
|
}
|
|
|
|
|
|
|
|
func benchVerify(b *testing.B, buf []byte, sig *Signature, pk *PublicKey) {
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
pk.VerifyMessage(buf, sig)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func randbuf(sz uint) []byte {
|
|
|
|
b := make([]byte, sz)
|
2020-03-23 10:44:40 -07:00
|
|
|
randRead(b)
|
2018-10-18 17:10:29 +09:00
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// vim: noexpandtab:ts=8:sw=8:tw=92:
|