2019-05-09 20:12:28 +02:00
|
|
|
package crypto
|
|
|
|
|
|
|
|
|
|
import (
|
2019-05-13 14:06:54 +00:00
|
|
|
"encoding/base64"
|
2019-05-09 20:12:28 +02:00
|
|
|
"regexp"
|
2019-05-13 14:06:54 +00:00
|
|
|
"strings"
|
2019-05-09 20:12:28 +02:00
|
|
|
"testing"
|
2019-05-14 14:42:38 +00:00
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2019-06-03 17:00:01 +02:00
|
|
|
|
|
|
|
|
"golang.org/x/crypto/rsa"
|
2019-05-09 20:12:28 +02:00
|
|
|
)
|
|
|
|
|
|
2019-06-03 17:00:01 +02:00
|
|
|
const name = "Richard M. Stallman"
|
|
|
|
|
const domain = "rms@protonmail.ch"
|
2019-05-09 20:12:28 +02:00
|
|
|
|
2019-05-13 14:06:54 +00:00
|
|
|
var passphrase = "I love GNU"
|
|
|
|
|
var rsaKey, ecKey, rsaPublicKey, ecPublicKey string
|
2019-05-09 20:12:28 +02:00
|
|
|
|
2019-05-13 14:06:54 +00:00
|
|
|
var (
|
|
|
|
|
rsaPrivateKeyRing *KeyRing
|
|
|
|
|
ecPrivateKeyRing *KeyRing
|
|
|
|
|
rsaPublicKeyRing *KeyRing
|
|
|
|
|
ecPublicKeyRing *KeyRing
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestGenerateKeys(t *testing.T) {
|
2019-05-14 18:05:01 +02:00
|
|
|
rsaKey, err = pgp.GenerateKey(name, domain, passphrase, "rsa", 1024)
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot generate RSA key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 18:05:01 +02:00
|
|
|
ecKey, err = pgp.GenerateKey(name, domain, passphrase, "x25519", 256)
|
2019-05-09 20:12:28 +02:00
|
|
|
if err != nil {
|
2019-05-13 14:06:54 +00:00
|
|
|
t.Fatal("Cannot generate EC key:", err)
|
2019-05-09 20:12:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rTest := regexp.MustCompile("(?s)^-----BEGIN PGP PRIVATE KEY BLOCK-----.*-----END PGP PRIVATE KEY BLOCK-----$")
|
|
|
|
|
assert.Regexp(t, rTest, rsaKey)
|
2019-05-13 14:06:54 +00:00
|
|
|
assert.Regexp(t, rTest, ecKey)
|
2019-05-09 20:12:28 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-13 14:06:54 +00:00
|
|
|
func TestGenerateKeyRings(t *testing.T) {
|
2019-05-14 14:42:38 +00:00
|
|
|
rsaPrivateKeyRing, err = ReadArmoredKeyRing(strings.NewReader(rsaKey))
|
2019-05-09 20:12:28 +02:00
|
|
|
if err != nil {
|
2019-05-13 14:06:54 +00:00
|
|
|
t.Fatal("Cannot read RSA key:", err)
|
2019-05-09 20:12:28 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-14 08:07:49 +00:00
|
|
|
rsaPublicKey, err = rsaPrivateKeyRing.GetArmoredPublicKey()
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot extract RSA public key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 14:42:38 +00:00
|
|
|
rsaPublicKeyRing, err = ReadArmoredKeyRing(strings.NewReader(rsaPublicKey))
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot read RSA public key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:00:01 +02:00
|
|
|
err = rsaPrivateKeyRing.UnlockWithPassphrase(passphrase)
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot decrypt RSA key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 14:42:38 +00:00
|
|
|
ecPrivateKeyRing, err = ReadArmoredKeyRing(strings.NewReader(ecKey))
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot read EC key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 08:07:49 +00:00
|
|
|
ecPublicKey, err = ecPrivateKeyRing.GetArmoredPublicKey()
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot extract EC public key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 14:42:38 +00:00
|
|
|
ecPublicKeyRing, err = ReadArmoredKeyRing(strings.NewReader(ecPublicKey))
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot read EC public key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:00:01 +02:00
|
|
|
err = ecPrivateKeyRing.UnlockWithPassphrase(passphrase)
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot decrypt EC key:", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUpdatePrivateKeysPassphrase(t *testing.T) {
|
|
|
|
|
newPassphrase := "I like GNU"
|
2019-05-14 18:05:01 +02:00
|
|
|
rsaKey, err = pgp.UpdatePrivateKeyPassphrase(rsaKey, passphrase, newPassphrase)
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Error in changing RSA key's passphrase:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 18:05:01 +02:00
|
|
|
ecKey, err = pgp.UpdatePrivateKeyPassphrase(ecKey, passphrase, newPassphrase)
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Error in changing EC key's passphrase:", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
passphrase = newPassphrase
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:00:01 +02:00
|
|
|
func ExamplePrintFingerprints() {
|
|
|
|
|
_, _ = pgp.PrintFingerprints(readTestFile("keyring_publicKey", false))
|
2019-05-13 14:06:54 +00:00
|
|
|
// Output:
|
|
|
|
|
// SubKey:37e4bcf09b36e34012d10c0247dc67b5cb8267f6
|
|
|
|
|
// PrimaryKey:6e8ba229b0cccaf6962f97953eb6259edf21df24
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:00:01 +02:00
|
|
|
func TestIsArmoredKeyExpired(t *testing.T) {
|
|
|
|
|
rsaRes, err := pgp.IsArmoredKeyExpired(rsaPublicKey)
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Error in checking expiration of RSA key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 17:00:01 +02:00
|
|
|
ecRes, err := pgp.IsArmoredKeyExpired(ecPublicKey)
|
2019-05-13 14:06:54 +00:00
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Error in checking expiration of EC key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert.Exactly(t, false, rsaRes)
|
|
|
|
|
assert.Exactly(t, false, ecRes)
|
2019-05-14 08:07:49 +00:00
|
|
|
|
2019-05-14 18:05:01 +02:00
|
|
|
pgp.UpdateTime(1557754627) // 2019-05-13T13:37:07+00:00
|
2019-05-14 08:07:49 +00:00
|
|
|
|
2019-06-03 17:00:01 +02:00
|
|
|
expRes, expErr := pgp.IsArmoredKeyExpired(readTestFile("key_expiredKey", false))
|
|
|
|
|
futureRes, futureErr := pgp.IsArmoredKeyExpired(readTestFile("key_futureKey", false))
|
2019-05-14 08:07:49 +00:00
|
|
|
|
|
|
|
|
assert.Exactly(t, true, expRes)
|
|
|
|
|
assert.Exactly(t, true, futureRes)
|
|
|
|
|
assert.EqualError(t, expErr, "keys expired")
|
|
|
|
|
assert.EqualError(t, futureErr, "keys expired")
|
2019-05-09 20:12:28 +02:00
|
|
|
}
|
2019-06-03 17:00:01 +02:00
|
|
|
|
|
|
|
|
func TestGenerateKeyWithPrimes(t *testing.T) {
|
|
|
|
|
prime1, _ := base64.StdEncoding.DecodeString(
|
|
|
|
|
"/thF8zjjk6fFx/y9NId35NFx8JTA7jvHEl+gI0dp9dIl9trmeZb+ESZ8f7bNXUmTI8j271kyenlrVJiqwqk80Q==")
|
|
|
|
|
prime2, _ := base64.StdEncoding.DecodeString(
|
|
|
|
|
"0HyyG/TShsw7yObD+DDP9Ze39ye1Redljx+KOZ3iNDmuuwwI1/5y44rD/ezAsE7A188NsotMDTSy5xtfHmu0xQ==")
|
|
|
|
|
prime3, _ := base64.StdEncoding.DecodeString(
|
|
|
|
|
"3OyJpAdnQXNjPNzI1u3BWDmPrzWw099E0UfJj5oJJILSbsAg/DDrmrdrIZDt7f24d06HCnTErCNWjvFJ3Kdq4w==")
|
|
|
|
|
prime4, _ := base64.StdEncoding.DecodeString(
|
|
|
|
|
"58UEDXTX29Q9JqvuE3Tn+Qj275CXBnJbA8IVM4d05cPYAZ6H43bPN01pbJqJTJw/cuFxs+8C+HNw3/MGQOExqw==")
|
|
|
|
|
|
|
|
|
|
staticRsaKey, err := pgp.GenerateRSAKeyWithPrimes(name, domain, passphrase, 1024, prime1, prime2, prime3, prime4)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot generate RSA key:", err)
|
|
|
|
|
}
|
|
|
|
|
rTest := regexp.MustCompile("(?s)^-----BEGIN PGP PRIVATE KEY BLOCK-----.*-----END PGP PRIVATE KEY BLOCK-----$")
|
|
|
|
|
assert.Regexp(t, rTest, staticRsaKey)
|
|
|
|
|
|
|
|
|
|
staticRsaKeyRing, err := ReadArmoredKeyRing(strings.NewReader(staticRsaKey))
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot read RSA key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = staticRsaKeyRing.UnlockWithPassphrase(passphrase)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal("Cannot decrypt RSA key:", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pk := staticRsaKeyRing.GetEntities()[0].PrivateKey.PrivateKey.(*rsa.PrivateKey)
|
|
|
|
|
assert.Exactly(t, prime1, pk.Primes[1].Bytes())
|
|
|
|
|
assert.Exactly(t, prime2, pk.Primes[0].Bytes())
|
|
|
|
|
}
|