mirror of
https://github.com/FiloSottile/age.git
synced 2026-09-19 14:34:21 +00:00
cmd/age: add support for encrypted SSH key files
This commit is contained in:
+26
-4
@@ -4,6 +4,7 @@
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
// Package age implements age-tool.com file encryption.
|
||||
package age
|
||||
|
||||
import (
|
||||
@@ -22,6 +23,13 @@ type Identity interface {
|
||||
Unwrap(block *format.Recipient) (fileKey []byte, err error)
|
||||
}
|
||||
|
||||
type IdentityMatcher interface {
|
||||
Identity
|
||||
Matches(block *format.Recipient) error
|
||||
}
|
||||
|
||||
var ErrIncorrectIdentity = errors.New("incorrect identity for recipient block")
|
||||
|
||||
type Recipient interface {
|
||||
Type() string
|
||||
Wrap(fileKey []byte) (*format.Recipient, error)
|
||||
@@ -89,15 +97,29 @@ RecipientsLoop:
|
||||
return nil, errors.New("an scrypt recipient must be the only one")
|
||||
}
|
||||
for _, i := range identities {
|
||||
|
||||
if i.Type() != r.Type {
|
||||
continue
|
||||
}
|
||||
|
||||
fileKey, err = i.Unwrap(r)
|
||||
if err == nil {
|
||||
break RecipientsLoop
|
||||
if i, ok := i.(IdentityMatcher); ok {
|
||||
err := i.Matches(r)
|
||||
if err != nil {
|
||||
if err == ErrIncorrectIdentity {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
fileKey, err = i.Unwrap(r)
|
||||
if err != nil {
|
||||
if err == ErrIncorrectIdentity {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
break RecipientsLoop
|
||||
}
|
||||
}
|
||||
if fileKey == nil {
|
||||
|
||||
@@ -104,7 +104,7 @@ func (i *ScryptIdentity) SetMaxWorkFactor(logN int) {
|
||||
|
||||
func (i *ScryptIdentity) Unwrap(block *format.Recipient) ([]byte, error) {
|
||||
if block.Type != "scrypt" {
|
||||
return nil, errors.New("wrong recipient block type")
|
||||
return nil, ErrIncorrectIdentity
|
||||
}
|
||||
if len(block.Args) != 2 {
|
||||
return nil, errors.New("invalid scrypt recipient block")
|
||||
@@ -134,7 +134,7 @@ func (i *ScryptIdentity) Unwrap(block *format.Recipient) ([]byte, error) {
|
||||
|
||||
fileKey, err := aeadDecrypt(k, block.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decrypt file key: %v", err)
|
||||
return nil, ErrIncorrectIdentity
|
||||
}
|
||||
return fileKey, nil
|
||||
}
|
||||
|
||||
+4
-4
@@ -98,7 +98,7 @@ func NewSSHRSAIdentity(key *rsa.PrivateKey) (*SSHRSAIdentity, error) {
|
||||
|
||||
func (i *SSHRSAIdentity) Unwrap(block *format.Recipient) ([]byte, error) {
|
||||
if block.Type != "ssh-rsa" {
|
||||
return nil, errors.New("wrong recipient block type")
|
||||
return nil, ErrIncorrectIdentity
|
||||
}
|
||||
if len(block.Args) != 1 {
|
||||
return nil, errors.New("invalid ssh-rsa recipient block")
|
||||
@@ -115,7 +115,7 @@ func (i *SSHRSAIdentity) Unwrap(block *format.Recipient) ([]byte, error) {
|
||||
h.Write(i.sshKey.Marshal())
|
||||
hh := h.Sum(nil)
|
||||
if !bytes.Equal(hh[:4], hash) {
|
||||
return nil, errors.New("wrong ssh-rsa key")
|
||||
return nil, ErrIncorrectIdentity
|
||||
}
|
||||
|
||||
fileKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, i.k,
|
||||
@@ -304,7 +304,7 @@ func ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) []byte {
|
||||
func (i *SSHEd25519Identity) Unwrap(block *format.Recipient) ([]byte, error) {
|
||||
// TODO: DRY this up with the X25519 implementation.
|
||||
if block.Type != "ssh-ed25519" {
|
||||
return nil, errors.New("wrong recipient block type")
|
||||
return nil, ErrIncorrectIdentity
|
||||
}
|
||||
if len(block.Args) != 2 {
|
||||
return nil, errors.New("invalid ssh-ed25519 recipient block")
|
||||
@@ -328,7 +328,7 @@ func (i *SSHEd25519Identity) Unwrap(block *format.Recipient) ([]byte, error) {
|
||||
sH.Write(i.sshKey.Marshal())
|
||||
hh := sH.Sum(nil)
|
||||
if !bytes.Equal(hh[:4], hash) {
|
||||
return nil, errors.New("wrong ssh-ed25519 key")
|
||||
return nil, ErrIncorrectIdentity
|
||||
}
|
||||
|
||||
var sharedSecret, theirPublicKey, tweak [32]byte
|
||||
|
||||
@@ -145,7 +145,7 @@ func ParseX25519Identity(s string) (*X25519Identity, error) {
|
||||
|
||||
func (i *X25519Identity) Unwrap(block *format.Recipient) ([]byte, error) {
|
||||
if block.Type != "X25519" {
|
||||
return nil, errors.New("wrong recipient block type")
|
||||
return nil, ErrIncorrectIdentity
|
||||
}
|
||||
if len(block.Args) != 1 {
|
||||
return nil, errors.New("invalid X25519 recipient block")
|
||||
@@ -174,7 +174,7 @@ func (i *X25519Identity) Unwrap(block *format.Recipient) ([]byte, error) {
|
||||
|
||||
fileKey, err := aeadDecrypt(wrappingKey, block.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decrypt file key: %v", err)
|
||||
return nil, ErrIncorrectIdentity
|
||||
}
|
||||
return fileKey, nil
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
// Package format implements the age file format.
|
||||
package format
|
||||
|
||||
import (
|
||||
|
||||
Reference in New Issue
Block a user