projects:windows:ssh_phrase
Это старая версия документа!
SSH Phrase
Данный код позволяет указывать фразу из которой будет сгенерирован ключ OpenSSH
Исходный код:
- sshphrase.go
// sshphrase.go package main import ( "bytes" "crypto/ed25519" "crypto/sha256" "encoding/pem" "fmt" "log" "os" "golang.org/x/crypto/ssh" "golang.org/x/term" ) // ===== marshalOpenSSHPrivateKey: Сериализация приватного ключа в OpenSSH-формате ===== func marshalOpenSSHPrivateKey(privateKey ed25519.PrivateKey) ([]byte, error) { // Структура для OpenSSH-ключа type opensshPrivateKey struct { Check1 uint32 Check2 uint32 Key struct { Curve string PubKey []byte Priv []byte } } pub := privateKey.Public().(ed25519.PublicKey) buf := &bytes.Buffer{} buf.Write([]byte("openssh-key-v1\x00")) writeString(buf, "none") // cipher name (без шифрования) writeString(buf, "none") // kdf name (без ключевого деривационного алгоритма) writeString(buf, "") // kdf options (пусто) writeUint32(buf, 1) // количество ключей pubKey, err := ssh.NewPublicKey(pub) if err != nil { return nil, err } writeString(buf, string(ssh.MarshalAuthorizedKey(pubKey))) content := &bytes.Buffer{} check := uint32(0x01020304) // контрольное значение для валидации writeUint32(content, check) writeUint32(content, check) writeString(content, "ssh-ed25519") writeString(content, string(pub)) writeString(content, string(privateKey)) content.WriteByte(0) // завершающий ноль padLen := 8 - (content.Len() % 8) for i := 1; i <= padLen; i++ { content.WriteByte(byte(i)) } writeString(buf, content.String()) final := pem.EncodeToMemory(&pem.Block{ Type: "OPENSSH PRIVATE KEY", Bytes: buf.Bytes(), }) return final, nil } // ===== Конец marshalOpenSSHPrivateKey ===== func writeString(w *bytes.Buffer, s string) { writeUint32(w, uint32(len(s))) w.WriteString(s) } func writeUint32(w *bytes.Buffer, v uint32) { w.WriteByte(byte(v >> 24)) w.WriteByte(byte(v >> 16)) w.WriteByte(byte(v >> 8)) w.WriteByte(byte(v)) } // ===== main: CLI-меню, генерация ключей по введённой фразе ===== func main() { fmt.Print("Введите фразу: ") b, err := term.ReadPassword(int(os.Stdin.Fd())) fmt.Println() if err != nil { log.Fatalf("Ошибка чтения фразы: %v", err) } phrase := string(b) // Создание seed на основе хэша введённой фразы seed := sha256.Sum256([]byte(phrase)) privateKey := ed25519.NewKeyFromSeed(seed[:]) publicKey, err := ssh.NewPublicKey(privateKey.Public()) if err != nil { log.Fatalf("Ошибка создания публичного ключа: %v", err) } for { fmt.Println("\nВыберите действие:") fmt.Println("1 - Показать публичный ключ") fmt.Println("2 - Показать приватный ключ") fmt.Println("0 - Выход") fmt.Print("> ") var choice string fmt.Scanln(&choice) switch choice { case "1": fmt.Println("\n📤 Публичный ключ (копируй в authorized_keys):") fmt.Println(string(ssh.MarshalAuthorizedKey(publicKey))) case "2": fmt.Println("\n🔐 Приватный ключ (в формате OpenSSH):") keyBytes, err := marshalOpenSSHPrivateKey(privateKey) if err != nil { log.Fatalf("Ошибка сериализации приватного ключа: %v", err) } fmt.Println(string(keyBytes)) fmt.Println("(Сохрани как id_ed25519 и установи chmod 600)") case "0": fmt.Println("Выход.") return default: fmt.Println("Неверный выбор. Попробуйте снова.") } } } // ===== Конец main =====
projects/windows/ssh_phrase.1744730929.txt.gz · Последнее изменение: 2025/04/15 18:28 —