Add SHA256 fingerprint utils and helpers (#41)

This commit is contained in:
wussler 2020-04-07 14:59:25 +02:00 committed by GitHub
parent c8b7e87135
commit 3c79f40acb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 88 additions and 3 deletions

View file

@ -3,6 +3,7 @@ package crypto
import ( import (
"bytes" "bytes"
"crypto" "crypto"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"io" "io"
@ -14,9 +15,9 @@ import (
"github.com/ProtonMail/gopenpgp/v2/constants" "github.com/ProtonMail/gopenpgp/v2/constants"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/crypto/openpgp" openpgp "golang.org/x/crypto/openpgp"
xarmor "golang.org/x/crypto/openpgp/armor" xarmor "golang.org/x/crypto/openpgp/armor"
"golang.org/x/crypto/openpgp/packet" packet "golang.org/x/crypto/openpgp/packet"
) )
// Key contains a single private or public key // Key contains a single private or public key
@ -321,8 +322,27 @@ func (key *Key) GetFingerprint() string {
return hex.EncodeToString(key.entity.PrimaryKey.Fingerprint[:]) return hex.EncodeToString(key.entity.PrimaryKey.Fingerprint[:])
} }
// GetSHA256Fingerprints computes the SHA256 fingerprints of the key and subkeys
func (key *Key) GetSHA256Fingerprints() (fingerprints []string) {
fingerprints = append(fingerprints, hex.EncodeToString(getSHA256FingerprintBytes(key.entity.PrimaryKey)))
for _, sub := range key.entity.Subkeys {
fingerprints = append(fingerprints, hex.EncodeToString(getSHA256FingerprintBytes(sub.PublicKey)))
}
return
}
// --- Internal methods // --- Internal methods
// getSHA256FingerprintBytes computes the SHA256 fingerprint of a public key object
func getSHA256FingerprintBytes(pk *packet.PublicKey) []byte {
fingerPrint := sha256.New()
// Hashing can't return an error, and has already been done when parsing the key,
// hence the error is nil
_ = pk.SerializeForHash(fingerPrint)
return fingerPrint.Sum(nil)
}
// readFrom reads unarmored and armored keys from r and adds them to the keyring. // readFrom reads unarmored and armored keys from r and adds them to the keyring.
func (key *Key) readFrom(r io.Reader, armored bool) error { func (key *Key) readFrom(r io.Reader, armored bool) error {
var err error var err error

View file

@ -310,3 +310,16 @@ func TestGetArmoredPublicKey(t *testing.T) {
assert.Exactly(t, eb, b) assert.Exactly(t, eb, b)
} }
func TestGetSHA256FingerprintsV4(t *testing.T) {
publicKey, err := NewKeyFromArmored(readTestFile("keyring_publicKey", false))
if err != nil {
t.Fatal("Cannot unarmor key:", err)
}
sha256Fingerprints := publicKey.GetSHA256Fingerprints()
assert.Len(t, sha256Fingerprints, 2)
assert.Exactly(t, "d9ac0b857da6d2c8be985b251a9e3db31e7a1d2d832d1f07ebe838a9edce9c24", sha256Fingerprints[0])
assert.Exactly(t, "203dfba1f8442c17e59214d9cd11985bfc5cc8721bb4a71740dd5507e58a1a0d", sha256Fingerprints[1])
}

2
go.mod
View file

@ -9,4 +9,4 @@ require (
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392
) )
replace golang.org/x/crypto => github.com/ProtonMail/crypto v0.0.0-20191122234321-e77a1f03baa0 replace golang.org/x/crypto => github.com/ProtonMail/crypto v0.0.0-20200406171318-1e8bf1c40869

5
go.sum
View file

@ -1,5 +1,10 @@
github.com/ProtonMail/crypto v0.0.0-20191122234321-e77a1f03baa0 h1:mCww5Yl0Pm4PZPSooupyWDgihrh96p6+O4PY1hs0FBw= github.com/ProtonMail/crypto v0.0.0-20191122234321-e77a1f03baa0 h1:mCww5Yl0Pm4PZPSooupyWDgihrh96p6+O4PY1hs0FBw=
github.com/ProtonMail/crypto v0.0.0-20191122234321-e77a1f03baa0/go.mod h1:MBriIAodHvZ+YvwvMJWCTmseW/LkeVRPWp/iZKvee4g= github.com/ProtonMail/crypto v0.0.0-20191122234321-e77a1f03baa0/go.mod h1:MBriIAodHvZ+YvwvMJWCTmseW/LkeVRPWp/iZKvee4g=
github.com/ProtonMail/crypto v0.0.0-20200406132833-0ff9e5f60587 h1:tRJioacMtJwCdlCHRaUl/2VfVNazf+ypT+SV5eiLnVY=
github.com/ProtonMail/crypto v0.0.0-20200406132833-0ff9e5f60587/go.mod h1:MBriIAodHvZ+YvwvMJWCTmseW/LkeVRPWp/iZKvee4g=
github.com/ProtonMail/crypto v0.0.0-20200406145536-081a35660375/go.mod h1:MBriIAodHvZ+YvwvMJWCTmseW/LkeVRPWp/iZKvee4g=
github.com/ProtonMail/crypto v0.0.0-20200406171318-1e8bf1c40869 h1:GtxsVknmfEUppe8lCX/Xgs+BbCzXf9bdH8+eBbtGO70=
github.com/ProtonMail/crypto v0.0.0-20200406171318-1e8bf1c40869/go.mod h1:MBriIAodHvZ+YvwvMJWCTmseW/LkeVRPWp/iZKvee4g=
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a h1:W6RrgN/sTxg1msqzFFb+G80MFmpjMw61IU+slm+wln4= github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a h1:W6RrgN/sTxg1msqzFFb+G80MFmpjMw61IU+slm+wln4=
github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

View file

@ -46,3 +46,12 @@ func GenerateKey(name, email string, passphrase []byte, keyType string, bits int
key.ClearPrivateParams() key.ClearPrivateParams()
return locked.Armor() return locked.Armor()
} }
func GetSHA256Fingerprints(publicKey string) ([]string, error) {
key, err := crypto.NewKeyFromArmored(publicKey)
if err != nil {
return nil, err
}
return key.GetSHA256Fingerprints(), nil
}

18
helper/key_test.go Normal file
View file

@ -0,0 +1,18 @@
package helper
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetSHA256FingerprintsV4(t *testing.T) {
sha256Fingerprints, err := GetSHA256Fingerprints(readTestFile("keyring_publicKey", false))
if err != nil {
t.Fatal("Cannot unarmor key:", err)
}
assert.Len(t, sha256Fingerprints, 2)
assert.Exactly(t, "d9ac0b857da6d2c8be985b251a9e3db31e7a1d2d832d1f07ebe838a9edce9c24", sha256Fingerprints[0])
assert.Exactly(t, "203dfba1f8442c17e59214d9cd11985bfc5cc8721bb4a71740dd5507e58a1a0d", sha256Fingerprints[1])
}

View file

@ -1,6 +1,8 @@
package helper package helper
import ( import (
"encoding/json"
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
) )
@ -65,3 +67,12 @@ func EncryptAttachment(plainData []byte, fileName string, keyRing *crypto.KeyRin
} }
return decrypted, nil return decrypted, nil
} }
func GetJsonSHA256Fingerprints(publicKey string) ([]byte, error) {
key, err := crypto.NewKeyFromArmored(publicKey)
if err != nil {
return nil, err
}
return json.Marshal(key.GetSHA256Fingerprints())
}

View file

@ -53,3 +53,12 @@ func TestMobileSignedMessageDecryption(t *testing.T) {
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Nil(t, decrypted) assert.Nil(t, decrypted)
} }
func TestGetJsonSHA256FingerprintsV4(t *testing.T) {
sha256Fingerprints, err := GetJsonSHA256Fingerprints(readTestFile("keyring_publicKey", false))
if err != nil {
t.Fatal("Cannot unarmor key:", err)
}
assert.Exactly(t, []byte("[\"d9ac0b857da6d2c8be985b251a9e3db31e7a1d2d832d1f07ebe838a9edce9c24\",\"203dfba1f8442c17e59214d9cd11985bfc5cc8721bb4a71740dd5507e58a1a0d\"]"), sha256Fingerprints)
}