agessh: support PKCS#8-encoded Ed25519 private keys

OpenSSH never generated them (unencrypted, and golang.org/x/crypto/ssh
doesn't support encrypted PKCS#8 for now, so the encrypted_keys.go
change is technically superfluous) but there are other systems that
produce them (for example, 1Password). Unfortunately, ParseRawPrivateKey
returns a value type for PKCS#8 and a pointer type for the OpenSSH
format (golang/go#51974), so we need to handle both.

Fixes #429
This commit is contained in:
Filippo Valsorda
2022-06-29 11:46:34 +02:00
parent 92fb4d508c
commit de7c1fb565
3 changed files with 19 additions and 0 deletions

View File

@@ -274,6 +274,9 @@ func ParseIdentity(pemBytes []byte) (age.Identity, error) {
switch k := k.(type) { switch k := k.(type) {
case *ed25519.PrivateKey: case *ed25519.PrivateKey:
return NewEd25519Identity(*k) return NewEd25519Identity(*k)
// ParseRawPrivateKey returns inconsistent types. See Issue 429.
case ed25519.PrivateKey:
return NewEd25519Identity(k)
case *rsa.PrivateKey: case *rsa.PrivateKey:
return NewRSAIdentity(k) return NewRSAIdentity(k)
} }

View File

@@ -113,6 +113,10 @@ func (i *EncryptedSSHIdentity) Unwrap(stanzas []*age.Stanza) (fileKey []byte, er
case *ed25519.PrivateKey: case *ed25519.PrivateKey:
i.decrypted, err = NewEd25519Identity(*k) i.decrypted, err = NewEd25519Identity(*k)
pubKey = k.Public().(ed25519.PublicKey) pubKey = k.Public().(ed25519.PublicKey)
// ParseRawPrivateKey returns inconsistent types. See Issue 429.
case ed25519.PrivateKey:
i.decrypted, err = NewEd25519Identity(k)
pubKey = k.Public().(ed25519.PublicKey)
case *rsa.PrivateKey: case *rsa.PrivateKey:
i.decrypted, err = NewRSAIdentity(k) i.decrypted, err = NewRSAIdentity(k)
pubKey = &k.PublicKey pubKey = &k.PublicKey

12
cmd/age/testdata/pkcs8.txt vendored Normal file
View File

@@ -0,0 +1,12 @@
# https://github.com/FiloSottile/age/discussions/428
# encrypt and decrypt a file with an Ed25519 key encoded with PKCS#8
age -e -i key.pem -o test.age input
age -d -i key.pem test.age
stdout test
-- input --
test
-- key.pem --
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIJT4Wpo+YG11yybKL/bYXQW7ekz4PAsmV/4tfmY1vU7x
-----END PRIVATE KEY-----