refactor functions and merge in keyring

This commit is contained in:
William Gotti 2019-05-14 08:07:49 +00:00 committed by Daniel Huigens
parent ef2f0e8340
commit e1098f7d34
8 changed files with 143 additions and 126 deletions

View file

@ -43,7 +43,7 @@ func TestGenerateKeyRings(t *testing.T) {
t.Fatal("Cannot read RSA key:", err)
}
rsaPublicKey, err = rsaPrivateKeyRing.ArmoredPublicKeyString()
rsaPublicKey, err = rsaPrivateKeyRing.GetArmoredPublicKey()
if err != nil {
t.Fatal("Cannot extract RSA public key:", err)
}
@ -63,7 +63,7 @@ func TestGenerateKeyRings(t *testing.T) {
t.Fatal("Cannot read EC key:", err)
}
ecPublicKey, err = ecPrivateKeyRing.ArmoredPublicKeyString()
ecPublicKey, err = ecPrivateKeyRing.GetArmoredPublicKey()
if err != nil {
t.Fatal("Cannot extract EC public key:", err)
}
@ -142,4 +142,14 @@ func TestIsKeyExpired(t *testing.T) {
assert.Exactly(t, false, rsaRes)
assert.Exactly(t, false, ecRes)
pmCrypto.UpdateTime(1557754627) // 2019-05-13T13:37:07+00:00
expRes, expErr := pmCrypto.IsKeyExpired(readTestFile("key_expiredKey"))
futureRes, futureErr := pmCrypto.IsKeyExpired(readTestFile("key_futureKey"))
assert.Exactly(t, true, expRes)
assert.Exactly(t, true, futureRes)
assert.EqualError(t, expErr, "keys expired")
assert.EqualError(t, futureErr, "keys expired")
}

View file

@ -4,6 +4,7 @@ import (
"bytes"
"crypto/ecdsa"
"crypto/rsa"
"encoding/hex"
"encoding/json"
"errors"
"io"
@ -456,8 +457,8 @@ func (kr *KeyRing) WriteArmoredPublicKey(w io.Writer) (err error) {
return
}
// ArmoredPublicKeyString returns the armored public keys from this keyring.
func (kr *KeyRing) ArmoredPublicKeyString() (s string, err error) {
// GetArmoredPublicKey returns the armored public keys from this keyring.
func (kr *KeyRing) GetArmoredPublicKey() (s string, err error) {
b := &bytes.Buffer{}
if err = kr.WriteArmoredPublicKey(b); err != nil {
return
@ -467,6 +468,60 @@ func (kr *KeyRing) ArmoredPublicKeyString() (s string, err error) {
return
}
// WritePublicKey outputs unarmored public keys from the keyring to w.
func (kr *KeyRing) WritePublicKey(w io.Writer) (err error) {
for _, e := range kr.entities {
if err = e.Serialize(w); err != nil {
return
}
}
return
}
// GetPublicKey returns the unarmored public keys from this keyring.
func (kr *KeyRing) GetPublicKey() (b []byte, err error) {
var outBuf bytes.Buffer
if err = kr.WritePublicKey(&outBuf); err != nil {
return
}
b = outBuf.Bytes()
return
}
// GetFingerprint gets the fingerprint from the keyring
func (kr *KeyRing) GetFingerprint() (string, error) {
for _, entity := range kr.entities {
fp := entity.PrimaryKey.Fingerprint
return hex.EncodeToString(fp[:]), nil
}
return "", errors.New("can't find public key")
}
// CheckPassphrase checks if private key passphrase ok
func (kr *KeyRing) CheckPassphrase(passphrase string) bool {
var keys []*packet.PrivateKey
for _, entity := range kr.entities {
keys = append(keys, entity.PrivateKey)
}
var decryptError error
var n int
for _, key := range keys {
if !key.Encrypted {
continue // Key already decrypted
}
if decryptError = key.Decrypt([]byte(passphrase)); decryptError == nil {
n++
}
}
if n == 0 {
return false
}
return true
}
// readFrom reads unarmored and armored keys from r and adds them to the keyring.
func (kr *KeyRing) readFrom(r io.Reader, armored bool) error {
var err error

View file

@ -75,7 +75,7 @@ func TestKeyRing_Encrypt(t *testing.T) {
}
func TestKeyRing_ArmoredPublicKeyString(t *testing.T) {
s, err := testPrivateKeyRing.ArmoredPublicKeyString()
s, err := testPrivateKeyRing.GetArmoredPublicKey()
if err != nil {
t.Fatal("Expected no error while getting armored public key, got:", err)
}

View file

@ -61,8 +61,8 @@ func (pm *PmCrypto) SignBinDetached(plainData []byte, privateKey *KeyRing, passp
return outBuf.String(), nil
}
// VerifyTextSignDetachedBinKey Verifies detached text - check if signature is valid using a given publicKey in binary format
func (pm *PmCrypto) VerifyTextSignDetachedBinKey(signature string, plainText string, publicKey *KeyRing, verifyTime int64) (bool, error) {
// VerifyTextDetachedSig verifies detached text - check if signature is valid using a given publicKey in binary format
func (pm *PmCrypto) VerifyTextDetachedSig(signature string, plainText string, publicKey *KeyRing, verifyTime int64) (bool, error) {
plainText = internal.TrimNewlines(plainText)
origText := bytes.NewReader(bytes.NewBufferString(plainText).Bytes())
@ -77,7 +77,7 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText *bytes.Reader, s
}
} else {
config.Time = func() time.Time {
return time.Unix(verifyTime + internal.CreationTimeOffset, 0)
return time.Unix(verifyTime+internal.CreationTimeOffset, 0)
}
}
signatureReader := strings.NewReader(signature)
@ -112,8 +112,8 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText *bytes.Reader, s
return true, nil
}
// VerifyBinSignDetachedBinKey Verifies detached text in binary format - check if signature is valid using a given publicKey in binary format
func (pm *PmCrypto) VerifyBinSignDetachedBinKey(signature string, plainData []byte, publicKey *KeyRing, verifyTime int64) (bool, error) {
// VerifyBinDetachedSig verifies detached text in binary format - check if signature is valid using a given publicKey in binary format
func (pm *PmCrypto) VerifyBinDetachedSig(signature string, plainData []byte, publicKey *KeyRing, verifyTime int64) (bool, error) {
origText := bytes.NewReader(plainData)
return verifySignature(publicKey.entities, origText, signature, verifyTime)

13
crypto/testdata/key_expiredKey vendored Normal file
View file

@ -0,0 +1,13 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
xcA4BAAAAAEBAgCgONc0J8rfO6cJw5YTP38x1ze2tAYIO7EcmRCNYwMkXngb
0Qdzg34Q5RW0rNiR56VB6KElPUhePRPVklLFiIvHABEBAAEAAf9qabYMzsz/
/LeRVZSsTgTljmJTdzd2ambUbpi+vt8MXJsbaWh71vjoLMWSXajaKSPDjVU5
waFNt9kLqwGGGLqpAQD5ZdMH2XzTq6GU9Ka69iZs6Pbnzwdz59Vc3i8hXlUj
zQEApHargCTsrtvSrm+hK/pN51/BHAy9lxCAw9f2etx+AeMA/RGrijkFZtYt
jeWdv/usXL3mgHvEcJv63N5zcEvDX5X4W1bND3Rlc3QxIDxhQGIuY29tPsJ7
BBABCAAvBQIAAAABBQMAAAU5BgsJBwgDAgkQzcF99nGrkAkEFQgKAgMWAgEC
GQECGwMCHgEAABAlAfwPehmLZs+gOhOTTaSslqQ50bl/REjmv42Nyr1ZBlQS
DECl1Qu4QyeXin29uEXWiekMpNlZVsEuc8icCw6ABhIZ
=/7PI
-----END PGP PRIVATE KEY BLOCK-----

55
crypto/testdata/key_futureKey vendored Normal file
View file

@ -0,0 +1,55 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
xcEYBH/oGU8BBACilkYen6vxr1LAhqWc0HaS+zMkjeND/P9ENePoNRVo3Bq8
KLacq1pQFitJVcUaz6D5lk0wtijSWb/uUSh6IW6ldVYvsjHdTpGYqH3vLJsp
YXzBzT6sXqht+ceQPi5pIpL/X5240WeaQQtD0arecVAtmtgrN5wJ/3So8llq
mf8q0QARAQABAAP9FZXBxWW0BtLHN7bTMdhzMDGX/phfvbJO6W1beS6Noxg6
7Gld+mVoCLiIvU8HwKF5YOlVYiGCQJBDF46VbcbBJjwUMCmLBF7eCO1tls6G
JPhG0EcVenx2f/V12cq9O+mKIXkfqnc9n9Wd8uVwav6HQsBFcPcmqj/Y5EAw
Yv8D6qkCANL1ABYZoXn/Bo1SfkOGWFGMS0xb/ISEIgEaQuAt7RFThx3BR7TG
cIkUfG10tm0aRz4LJ74jgfEf+34RZVAzlJsCAMVNWQaSQ2zGmMB+CM73BCXb
JPIh0mB6W0XFWl/a0tex+VkmdnCtvnbtA9MjDs1v3WR2+8SRvDe+k/Yx1w2H
lwMB/2pxnIOH7yrCMPDK14Yfay3EOWzTs17FF1sm8HUSR17qwpBEcH2a6TRd
msr2TvmaCI/uSVtX+h7swnBlhC/+p5ugUc0WZXhhbXBsZSA8dGVzdEBleGFt
cGxlPsKtBBMBCgAXBQJ/6BlPAhsvAwsJBwMVCggCHgECF4AACgkQdKKYGB48
OusrOgP/Z7+F/BP4rn0CDyPgXmXvj+EAYF2bRWFbxWGPs8KOua9XvuAO1XJQ
CC7Mgx/D8t/7LfLYn4kTzEbKFT/3ZtNzl74Pl/QlDZqodmT8gFESDd01LsL5
9mI0O9zw7gP7RZkftiFveOGvT4Os/SvOzdpXGGWAfytHtoxmxDq66gzuZUPH
wRcEf+gZTwEEAK0pLhDM5pDxWVfuVFssIdbWhClxlN9ZGhjGM27vf5QE0YAl
uhlv5BTtLU3pYtQYScJksNAFYmENtufWU+c4fv4HHSTGXsW5baw8Ix1vFasr
Aa9atZWBZklQVt3Bsxu9+jOYxGJDjkzyhpLOZgJSYFK36l8dATPF5t1eGy40
5i0nABEBAAEAA/dvmxsVuPricKwlAHdeTBODZL/J9mr9iXBIh3afCb4wqOpe
rfJEctmOo0+P59zK1tyzbjKH4PCHnU9GHd32KXOvNtmFs4BeuJTFMnQd5YdE
45/7UD29fYtv6cqnn4oigIijuwDFL6qBzEfAjgxl9+MbZz2Gkh6zOtwwDlxv
hOjJAgDhktuQCWfZ8oLoHAHYMR2Fn8n16qUhAqZEDOCF4vjiCOp3za/whtMl
bQMngnA9MioHRQ5vsI5ksUgvzE+9hSzlAgDEhH0b68DTJRDZHFeOIltZhcgC
s5VA6rspabCQ2ETthgLmj4UJbloNCr5z/5IOiAeoWWaw98oSw6yVaHta6p0b
Af4mD95MipQfWvHldxAKeTZRkB9wG68KfzJOmmWoQS+JqYGGwjYZV97KG6ai
7N4xGRiiwfaU0oSIcoDhO0kn5VPMokXCwIMEGAEKAA8FAn/oGU8FCQ8JnAAC
Gy4AqAkQdKKYGB48OuudIAQZAQoABgUCf+gZTwAKCRDuSkIwkyAjaKEqA/9X
S9AgN4nV9on6GsuK1ZpQpqcKAf4SZaF3rDXqpYfM+LDpqaIl8LZKzK7EyW2p
VNV9PwnYtMXwQ7A3KAu2audWxSawHNyvgez1Ujl0J7TfKwJyVBrCDjZCJrr+
joPU0To95jJivSrnCYC3l1ngoMIZycfaU6FhYwHd2XJe2kbzc8JPA/9aCPIa
hfTEDEH/giKdtzlLbkri2UYGCJqcoNl0Maz6LVUI3NCo3O77zi2v7gLtu+9h
gfWa8dTxCOszDbNTknb8XXCK74FxwIBgr4gHlvK+xh38RI+8eC2y0qONraQ/
qACJ+UGh1/4smKasSlBi7hZOvNmOxqm4iQ5hve4uWsSlIsfBGAR/6BlPAQQA
w4p7hPgd9QdoQsbEXDYq7hxBfUOub1lAtMN9mvUnLMoohEqocCILNC/xMno5
5+IwEFZZoHySS1CIIBoy1xgRhe0O7+Ls8R/eyXgvjghVdm9ESMlH9+0p94v/
gfwS6dudEWy3zeYziQLVaZ2wSUiw46Vs8wumAV4lFzEa0nRBMFsAEQEAAQAD
+gOnmEdpRm0sMO+Okief8OLNEp4NoHM34LhjvTN4OmiL5dX2ss87DIxWCtTo
d3dDXaYpaMb8cJv7Tjqu7VYbYmMXwnPxD6XxOtqAmmL89KmtNAY77B3OQ+dD
LHzkFDjzB4Lzh9/WHwGeDKAlsuYO7KhVwqZ+J67QeQpXBH4ddgwBAgD9xDfI
r+JQzQEsfThwiPt/+XXd3HvpUOubhkGrNTNjy3J0RKOOIz4WVLWL83Y8he31
ghF6DA2QXEf9zz5aMQS7AgDFQxJmBzSGFCkbHbSphT37SnohLONdxyvmZqj5
sKIA01fs5gO/+AK2/qpLb1BAXFhi8H6RPVNyOho98VVFx5jhAfwIoivqrLBK
GzFJxS+KxUZgAUwj2ifZ2G3xTAmzZK6ZCPf4giwn4KsC1jVF0TO6zp02RcmZ
wavObOiYwaRyhz9bnvvCwIMEGAEKAA8FAn/oGU8FCQ8JnAACGy4AqAkQdKKY
GB48OuudIAQZAQoABgUCf+gZTwAKCRAowa+OShndpzKyA/0Wi6Vlg76uZDCP
JgTuFn3u/+B3NZvpJw76bwmbfRDQn24o1MrA6VM6Ho2tvSrS3VTZqkn/9JBX
TPGZCZZ/Vrmk1HQp2GIPcnTb7eHAuXl1KhjOQ3MD1fOCDVwJtIMX92Asf7HW
J4wE4f3U5NnR+W6uranaXA2ghVyUsk0lJtnM400nA/45gAq9EBZUSL+DWdYZ
+/RgXpw4/7pwDbq/G4k+4YWn/tvCUnwAsCTo2xD6qN+icY5WwBTphdA/0O3U
+8ujuk61ln9b01u49FoVbuwHoS1gVySj2RyRgldlwg6l99MI8eYmuHf4baPX
0uyeibPdgJTjARMuQzDFA8bdbM540vBf5Q==
=WLIN
-----END PGP PRIVATE KEY BLOCK-----

View file

@ -1,33 +0,0 @@
package key
import (
"bytes"
"encoding/hex"
"errors"
"github.com/ProtonMail/go-pm-crypto/armor"
"golang.org/x/crypto/openpgp"
)
// GetFingerprint gets an armored public key fingerprint
func GetFingerprint(publicKey string) (string, error) {
rawPubKey, err := armor.Unarmor(publicKey)
if err != nil {
return "", err
}
return GetFingerprintBinKey(rawPubKey)
}
// GetFingerprintBinKey gets an unarmored public key fingerprint
func GetFingerprintBinKey(publicKey []byte) (string, error) {
pubKeyReader := bytes.NewReader(publicKey)
pubKeyEntries, err := openpgp.ReadKeyRing(pubKeyReader)
if err != nil {
return "", err
}
for _, e := range pubKeyEntries {
fp := e.PrimaryKey.Fingerprint
return hex.EncodeToString(fp[:]), nil
}
return "", errors.New("can't find public key")
}

View file

@ -1,83 +0,0 @@
// Provides key manipulation helper methods
package key
import (
"bytes"
"fmt"
"github.com/ProtonMail/go-pm-crypto/armor"
"github.com/ProtonMail/go-pm-crypto/constants"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/packet"
"strings"
)
// CheckPassphrase checks if private key passphrase ok
func CheckPassphrase(privateKey string, passphrase string) bool {
privKeyReader := strings.NewReader(privateKey)
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
if err != nil {
fmt.Println(err)
return false
}
var keys []*packet.PrivateKey
for _, e := range entries {
keys = append(keys, e.PrivateKey)
}
var decryptError error
var n int
for _, key := range keys {
if !key.Encrypted {
continue // Key already decrypted
}
if decryptError = key.Decrypt([]byte(passphrase)); decryptError == nil {
n++
}
}
if n == 0 {
return false
}
return true
}
// PublicKey gets a public key from a private key
func PublicKey(privateKey string) (string, error) {
privKeyReader := strings.NewReader(privateKey)
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
if err != nil {
return "", err
}
var outBuf bytes.Buffer
for _, e := range entries {
if err := e.Serialize(&outBuf); err != nil {
return "", err
}
}
outString, err := armor.ArmorWithType(outBuf.Bytes(), constants.PublicKeyHeader)
if err != nil {
return "", nil
}
return outString, nil
}
// PublicKeyBinOut gets a public key from a private key
func PublicKeyBinOut(privateKey string) ([]byte, error) {
privKeyReader := strings.NewReader(privateKey)
entries, err := openpgp.ReadArmoredKeyRing(privKeyReader)
if err != nil {
return nil, err
}
var outBuf bytes.Buffer
for _, e := range entries {
if err := e.Serialize(&outBuf); err != nil {
return nil, err
}
}
return outBuf.Bytes(), nil
}