Add parsing and serializing interfaces for keyrings (#275)

* Add parsing and serializing interfaces for keyrings

* Make error check more compact
This commit is contained in:
Aron Wussler 2024-04-08 11:38:52 +02:00 committed by GitHub
parent 453e81905b
commit 0d1ce13767
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 69 additions and 0 deletions

View file

@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
- API to serialize KeyRings to binary data:
```go
func (keyRing *KeyRing) Serialize() ([]byte, error)
```
- API to parse KeyRings from binary data:
```go
func NewKeyRingFromBinary(binKeys []byte) (*KeyRing, error)
```
## [2.7.5] 2023-31-01 ## [2.7.5] 2023-31-01
### Added ### Added

View file

@ -49,6 +49,29 @@ func (keyRing *KeyRing) AddKey(key *Key) error {
return nil return nil
} }
// NewKeyRingFromBinary creates a new keyring with all the keys contained in the unarmored binary data.
// Note that it accepts only unlocked or public keys, as KeyRing cannot contain locked keys.
func NewKeyRingFromBinary(binKeys []byte) (*KeyRing, error) {
entities, err := openpgp.ReadKeyRing(bytes.NewReader(binKeys))
if err != nil {
return nil, errors.Wrap(err, "gopenpgp: error in reading keyring")
}
keyring := &KeyRing{}
for _, entity := range entities {
key, err := NewKeyFromEntity(entity)
if err != nil {
return nil, errors.Wrap(err, "gopenpgp: error in reading keyring")
}
if err = keyring.AddKey(key); err != nil {
return nil, errors.Wrap(err, "gopenpgp: error in reading keyring")
}
}
return keyring, nil
}
// --- Extract keys from keyring // --- Extract keys from keyring
// GetKeys returns openpgp keys contained in this KeyRing. // GetKeys returns openpgp keys contained in this KeyRing.
@ -88,6 +111,25 @@ func (keyRing *KeyRing) getSigningEntity() (*openpgp.Entity, error) {
return signEntity, nil return signEntity, nil
} }
// Serialize serializes a KeyRing to binary data.
func (keyRing *KeyRing) Serialize() ([]byte, error) {
var buffer bytes.Buffer
for _, entity := range keyRing.entities {
var err error
if entity.PrivateKey == nil {
err = entity.Serialize(&buffer)
} else {
err = entity.SerializePrivateWithoutSigning(&buffer, nil)
}
if err != nil {
return nil, errors.Wrap(err, "gopenpgp: error in serializing keyring")
}
}
return buffer.Bytes(), nil
}
// --- Extract info from key // --- Extract info from key
// CountEntities returns the number of entities in the keyring. // CountEntities returns the number of entities in the keyring.

View file

@ -148,6 +148,21 @@ func TestMultipleKeyRing(t *testing.T) {
assert.Exactly(t, 1, singleKeyRing.CountDecryptionEntities()) assert.Exactly(t, 1, singleKeyRing.CountDecryptionEntities())
} }
func TestSerializeParse(t *testing.T) {
serialized, err := keyRingTestMultiple.Serialize()
assert.Nil(t, err)
parsed, err := NewKeyRingFromBinary(serialized)
assert.Nil(t, err)
assert.Exactly(t, 3, len(parsed.GetKeys()))
for i, parsedKey := range parsed.GetKeys() {
expectedKey, err := keyRingTestMultiple.GetKey(i)
assert.Nil(t, err)
assert.Exactly(t, parsedKey.GetFingerprint(), expectedKey.GetFingerprint())
}
}
func TestClearPrivateKey(t *testing.T) { func TestClearPrivateKey(t *testing.T) {
keyRingCopy, err := keyRingTestMultiple.Copy() keyRingCopy, err := keyRingTestMultiple.Copy()
if err != nil { if err != nil {