mirror of
https://github.com/pinpox/pgp2ssh.git
synced 2025-02-05 10:59:19 +01:00
feat: fix & clean up
We did it! It's working! I've also removed lots of code that we don't need anymore.
This commit is contained in:
parent
4cc344b2b2
commit
3c97a34ec4
2
go.mod
2
go.mod
|
@ -3,9 +3,7 @@ module gpg2age
|
||||||
go 1.21.8
|
go 1.21.8
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Mic92/ssh-to-age v0.0.0-20240304065525-796b05d6e3b3
|
|
||||||
github.com/ProtonMail/go-crypto v1.0.0
|
github.com/ProtonMail/go-crypto v1.0.0
|
||||||
github.com/davecgh/go-spew v1.1.1
|
|
||||||
golang.org/x/crypto v0.20.0
|
golang.org/x/crypto v0.20.0
|
||||||
golang.org/x/term v0.18.0
|
golang.org/x/term v0.18.0
|
||||||
)
|
)
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -1,13 +1,9 @@
|
||||||
github.com/Mic92/ssh-to-age v0.0.0-20240304065525-796b05d6e3b3 h1:YT+DB0TTQ/Li1AQOAAP20k2kCT3XndzsprKgTg5GCIc=
|
|
||||||
github.com/Mic92/ssh-to-age v0.0.0-20240304065525-796b05d6e3b3/go.mod h1:M/OUOt0/3WI/tYzEYBhQNyU5OB1YStcJEkUaTDnjxJI=
|
|
||||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
|
98
main.go
98
main.go
|
@ -1,13 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha512"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"strings"
|
|
||||||
"encoding/pem"
|
|
||||||
|
|
||||||
"github.com/ProtonMail/go-crypto/openpgp"
|
"github.com/ProtonMail/go-crypto/openpgp"
|
||||||
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
"github.com/ProtonMail/go-crypto/openpgp/armor"
|
||||||
|
@ -16,18 +14,9 @@ import (
|
||||||
|
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/Mic92/ssh-to-age/bech32"
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"golang.org/x/term"
|
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
// "bytes"
|
"golang.org/x/term"
|
||||||
// "golang.org/x/crypto/ssh"
|
|
||||||
// "golang.org/x/crypto/curve25519"
|
|
||||||
// "https://pkg.go.dev/crypto/ed25519#PrivateKey
|
|
||||||
// "crypto/ed25519"ccc1be8d-24dc-41ad-9d66-b657711419d7
|
|
||||||
"reflect"
|
"reflect"
|
||||||
// "filippo.io/edwards25519"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func readEntity(keypath string) (*openpgp.Entity, error) {
|
func readEntity(keypath string) (*openpgp.Entity, error) {
|
||||||
|
@ -49,45 +38,28 @@ var (
|
||||||
UnsupportedKeyType = errors.New("only ed25519 keys are supported")
|
UnsupportedKeyType = errors.New("only ed25519 keys are supported")
|
||||||
)
|
)
|
||||||
|
|
||||||
func ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) ([]byte, error) {
|
|
||||||
h := sha512.New()
|
|
||||||
_, err := h.Write(pk.Seed())
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
out := h.Sum(nil)
|
|
||||||
return out[:curve25519.ScalarSize], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func SSHPrivateKeyToAge(bytes []byte) (*string, error) {
|
|
||||||
s, err := bech32.Encode("AGE-SECRET-KEY-", bytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s = strings.ToUpper(s)
|
|
||||||
return &s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// TODO turn these into CLI inputs
|
var keyfile string
|
||||||
// keyfile := "/home/pinpox/gnutmp/0xA5BCEFD22D30118A.priv.asc"
|
log.Println("Enter path to private PGP key (default: ./priv.asc):")
|
||||||
keyfile := "./test-key.asc"
|
_, err := fmt.Scanf("%s", &keyfile)
|
||||||
|
if err != nil && err.Error() == "unexpected newline" {
|
||||||
|
keyfile := "./priv.asc"
|
||||||
|
} else if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
e, err := readEntity(keyfile)
|
e, err := readEntity(keyfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
spew.Config.MaxDepth = 2
|
|
||||||
spew.Config.Indent = " "
|
|
||||||
|
|
||||||
log.Println("Keys:")
|
log.Println("Keys:")
|
||||||
log.Println("[0]", e.PrimaryKey.KeyIdString()+" (primary)")
|
log.Println("[0]", e.PrimaryKey.KeyIdString()+" (primary)")
|
||||||
for i := 0; i < len(e.Subkeys); i++ {
|
for i := 0; i < len(e.Subkeys); i++ {
|
||||||
log.Println(fmt.Sprintf("[%d]", i+1), e.Subkeys[i].PublicKey.KeyIdString()+" (subkey)")
|
log.Println(fmt.Sprintf("[%d]", i+1), e.Subkeys[i].PublicKey.KeyIdString()+" (subkey)")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Please choose a key by index (default: 0):")
|
log.Println("Choose key by index (default: 0):")
|
||||||
|
|
||||||
var keyIndex int
|
var keyIndex int
|
||||||
_, err = fmt.Scanf("%d", &keyIndex)
|
_, err = fmt.Scanf("%d", &keyIndex)
|
||||||
|
@ -123,62 +95,22 @@ func main() {
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Fatal("failed to cast")
|
log.Fatal("failed to cast")
|
||||||
}
|
}
|
||||||
// spew.Dump(castkey)
|
|
||||||
|
|
||||||
// get public key as OpenSSH key
|
|
||||||
log.Println("public key type:", reflect.TypeOf(castkey.PublicKey))
|
log.Println("public key type:", reflect.TypeOf(castkey.PublicKey))
|
||||||
var pubkey ed25519.PublicKey = castkey.PublicKey.X
|
var pubkey ed25519.PublicKey = castkey.PublicKey.X
|
||||||
|
|
||||||
agePub, err := bech32.Encode("age", pubkey)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
log.Println("public age key:", string(agePub))
|
|
||||||
|
|
||||||
sshPub, err := ssh.NewPublicKey(pubkey)
|
sshPub, err := ssh.NewPublicKey(pubkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
// log.Println("public key SSH key wire format:", sshPub.Marshal())
|
log.Println("public SSH key:\n" + string(ssh.MarshalAuthorizedKey(sshPub)))
|
||||||
// log.Println("public key SHA256:", ssh.FingerprintSHA256(sshPub))
|
|
||||||
log.Println("public SSH key:", string(ssh.MarshalAuthorizedKey(sshPub)))
|
|
||||||
|
|
||||||
// TODO: are these the correct bytes?
|
|
||||||
// var privkey ed25519.PrivateKey = castkey.D
|
|
||||||
// var privkey ed25519.PrivateKey = castkey.MarshalByteSecret()
|
|
||||||
var privkey = ed25519.NewKeyFromSeed(castkey.D)
|
var privkey = ed25519.NewKeyFromSeed(castkey.D)
|
||||||
|
|
||||||
// TODO is this right?
|
privPem, err := ssh.MarshalPrivateKey(&privkey, "")
|
||||||
bytes, err := ed25519PrivateKeyToCurve25519(privkey)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
privateKeyPem := pem.EncodeToMemory(privPem)
|
||||||
// bytes = privkee
|
log.Println("Private SSH key:\n" + string(privateKeyPem))
|
||||||
|
|
||||||
// TODO trying to get private key as age key
|
|
||||||
agekey, err := SSHPrivateKeyToAge(bytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(*agekey)
|
|
||||||
|
|
||||||
// TODO trying to get private key as OpenSSH key
|
|
||||||
privPem, err := ssh.MarshalPrivateKey(privkey, "")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := pem.Encode(os.Stdout, privPem); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO make sure public key is still the same
|
|
||||||
var priv ed25519.PrivateKey = bytes
|
|
||||||
var pubkey2 = priv.Public()
|
|
||||||
// var pubkey2 = privkey.Public()
|
|
||||||
sshPub2, err := ssh.NewPublicKey(pubkey2)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
log.Println("verify public SSH key:", string(ssh.MarshalAuthorizedKey(sshPub2)))
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue