internal/plugin,cmd/age: add support for encrypting to plugin identities

This commit is contained in:
Filippo Valsorda
2021-04-20 01:35:45 -04:00
parent 7bad9c2ad8
commit 384d0393e0
3 changed files with 26 additions and 3 deletions

View File

@@ -103,7 +103,7 @@ func NewRSAIdentity(key *rsa.PrivateKey) (*RSAIdentity, error) {
return i, nil return i, nil
} }
func (i *RSAIdentity) Recipient() age.Recipient { func (i *RSAIdentity) Recipient() *RSARecipient {
return &RSARecipient{ return &RSARecipient{
sshKey: i.sshKey, sshKey: i.sshKey,
pubKey: &i.k.PublicKey, pubKey: &i.k.PublicKey,
@@ -288,7 +288,7 @@ func ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) []byte {
return out[:curve25519.ScalarSize] return out[:curve25519.ScalarSize]
} }
func (i *Ed25519Identity) Recipient() age.Recipient { func (i *Ed25519Identity) Recipient() *Ed25519Recipient {
return &Ed25519Recipient{ return &Ed25519Recipient{
sshKey: i.sshKey, sshKey: i.sshKey,
theirPublicKey: i.ourPublicKey, theirPublicKey: i.ourPublicKey,

View File

@@ -19,6 +19,7 @@ import (
"filippo.io/age" "filippo.io/age"
"filippo.io/age/agessh" "filippo.io/age/agessh"
"filippo.io/age/armor" "filippo.io/age/armor"
"filippo.io/age/internal/plugin"
"golang.org/x/term" "golang.org/x/term"
) )
@@ -402,6 +403,8 @@ func identitiesToRecipients(ids []age.Identity) ([]age.Recipient, error) {
switch id := id.(type) { switch id := id.(type) {
case *age.X25519Identity: case *age.X25519Identity:
recipients = append(recipients, id.Recipient()) recipients = append(recipients, id.Recipient())
case *plugin.Identity:
recipients = append(recipients, id.Recipient())
case *agessh.RSAIdentity: case *agessh.RSAIdentity:
recipients = append(recipients, id.Recipient()) recipients = append(recipients, id.Recipient())
case *agessh.Ed25519Identity: case *agessh.Ed25519Identity:

View File

@@ -27,6 +27,9 @@ type Recipient struct {
name string name string
encoding string encoding string
// identity is true when encoding is an identity string.
identity bool
// DisplayMessage is a callback that will be invoked by Wrap if the plugin // DisplayMessage is a callback that will be invoked by Wrap if the plugin
// wishes to display a message to the user. If DisplayMessage is nil or // wishes to display a message to the user. If DisplayMessage is nil or
// returns an error, failure will be reported to the plugin. // returns an error, failure will be reported to the plugin.
@@ -73,11 +76,14 @@ func (r *Recipient) Wrap(fileKey []byte) (stanzas []*age.Stanza, err error) {
} }
defer conn.Close() defer conn.Close()
// Phase 1: client sends recipient and file key // Phase 1: client sends recipient or identity and file key
s := &format.Stanza{ s := &format.Stanza{
Type: "add-recipient", Type: "add-recipient",
Args: []string{r.encoding}, Args: []string{r.encoding},
} }
if r.identity {
s.Type = "add-identity"
}
if err := s.Marshal(conn); err != nil { if err := s.Marshal(conn); err != nil {
return nil, err return nil, err
} }
@@ -231,6 +237,20 @@ func (i *Identity) Name() string {
return i.name return i.name
} }
// Recipient returns a Recipient wrapping this identity. When that Recipient is
// used to encrypt a file key, the identity encoding is provided as-is to the
// plugin, which is expected to support encrypting to identities.
func (i *Identity) Recipient() *Recipient {
return &Recipient{
name: i.name,
encoding: i.encoding,
identity: true,
DisplayMessage: i.DisplayMessage,
RequestValue: i.RequestValue,
}
}
func (i *Identity) Unwrap(stanzas []*age.Stanza) (fileKey []byte, err error) { func (i *Identity) Unwrap(stanzas []*age.Stanza) (fileKey []byte, err error) {
defer func() { defer func() {
if err != nil { if err != nil {