123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- // Copyright 2012 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // Code originally from https://go-review.googlesource.com/c/crypto/+/218620
- // TODO: replace with upstream once the above change is merged and released.
- package format
- import (
- "crypto"
- "crypto/ed25519"
- "crypto/rand"
- "encoding/binary"
- "encoding/pem"
- "fmt"
- "golang.org/x/crypto/ssh"
- )
- const privateKeyAuthMagic = "openssh-key-v1\x00"
- type openSSHEncryptedPrivateKey struct {
- CipherName string
- KDFName string
- KDFOptions string
- KeysCount uint32
- PubKey []byte
- KeyBlocks []byte
- }
- type openSSHPrivateKey struct {
- Check1 uint32
- Check2 uint32
- Keytype string
- Rest []byte `ssh:"rest"`
- }
- type openSSHEd25519PrivateKey struct {
- Pub []byte
- Priv []byte
- Comment string
- Pad []byte `ssh:"rest"`
- }
- func OpenSSHPrivateKey(key crypto.PrivateKey, comment string) (*pem.Block, error) {
- var check uint32
- if err := binary.Read(rand.Reader, binary.BigEndian, &check); err != nil {
- return nil, err
- }
- var pk1 openSSHPrivateKey
- pk1.Check1 = check
- pk1.Check2 = check
- var w openSSHEncryptedPrivateKey
- w.KeysCount = 1
- if k, ok := key.(*ed25519.PrivateKey); ok {
- key = *k
- }
- switch k := key.(type) {
- case ed25519.PrivateKey:
- pub, priv := k[32:], k
- key := openSSHEd25519PrivateKey{
- Pub: pub,
- Priv: priv,
- Comment: comment,
- }
- pk1.Keytype = ssh.KeyAlgoED25519
- pk1.Rest = ssh.Marshal(key)
- w.PubKey = ssh.Marshal(struct {
- KeyType string
- Pub []byte
- }{
- ssh.KeyAlgoED25519, pub,
- })
- default:
- return nil, fmt.Errorf("ssh: unknown key type %T", k)
- }
- w.KeyBlocks = openSSHPadding(ssh.Marshal(pk1), 8)
- w.CipherName, w.KDFName, w.KDFOptions = "none", "none", ""
- return &pem.Block{
- Type: "OPENSSH PRIVATE KEY",
- Bytes: append([]byte(privateKeyAuthMagic), ssh.Marshal(w)...),
- }, nil
- }
- func openSSHPadding(block []byte, blocksize int) []byte {
- for i, j := 0, len(block); (j+i)%blocksize != 0; i++ {
- block = append(block, byte(i+1))
- }
- return block
- }
|