gotextlog

gotextlog
git clone https://git.ryansepassi.com/git/gotextlog.git
Log | Files | Refs | README

source_test.go (3422B)


      1 package sshkey
      2 
      3 import (
      4 	"context"
      5 	"crypto/ed25519"
      6 	"crypto/rand"
      7 	"crypto/x509"
      8 	"encoding/pem"
      9 	"net"
     10 	"os"
     11 	"path/filepath"
     12 	"strings"
     13 	"testing"
     14 
     15 	"golang.org/x/crypto/ssh"
     16 	"golang.org/x/crypto/ssh/agent"
     17 )
     18 
     19 func TestLocalSourceDiscoversAndSignsWithSelectedEd25519Key(t *testing.T) {
     20 	directory := t.TempDir()
     21 	publicRaw, privateKey, err := ed25519.GenerateKey(rand.Reader)
     22 	if err != nil {
     23 		t.Fatal(err)
     24 	}
     25 	publicKey, err := ssh.NewPublicKey(publicRaw)
     26 	if err != nil {
     27 		t.Fatal(err)
     28 	}
     29 	encodedPrivate, err := x509.MarshalPKCS8PrivateKey(privateKey)
     30 	if err != nil {
     31 		t.Fatal(err)
     32 	}
     33 	privatePath := filepath.Join(directory, "id_example")
     34 	if err := os.WriteFile(privatePath, pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedPrivate}), 0o600); err != nil {
     35 		t.Fatal(err)
     36 	}
     37 	publicText := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(publicKey))) + " test@example\n"
     38 	if err := os.WriteFile(privatePath+".pub", []byte(publicText), 0o644); err != nil {
     39 		t.Fatal(err)
     40 	}
     41 	// Discovery ignores public keys using unsupported algorithms.
     42 	if err := os.WriteFile(filepath.Join(directory, "id_rsa.pub"), []byte("ssh-rsa invalid"), 0o644); err != nil {
     43 		t.Fatal(err)
     44 	}
     45 
     46 	source := NewLocalSource(directory, "")
     47 	keys, err := source.Keys(context.Background())
     48 	if err != nil {
     49 		t.Fatal(err)
     50 	}
     51 	if len(keys) != 1 || keys[0].Path != privatePath+".pub" || keys[0].Fingerprint != ssh.FingerprintSHA256(publicKey) || keys[0].PublicKey != strings.TrimSpace(string(ssh.MarshalAuthorizedKey(publicKey))) {
     52 		t.Fatalf("keys = %#v", keys)
     53 	}
     54 
     55 	message := []byte("gotextlog-auth-v1\ntest")
     56 	encodedSignature, err := source.Sign(context.Background(), keys[0], message)
     57 	if err != nil {
     58 		t.Fatal(err)
     59 	}
     60 	var signature ssh.Signature
     61 	if err := ssh.Unmarshal(encodedSignature, &signature); err != nil {
     62 		t.Fatal(err)
     63 	}
     64 	if err := publicKey.Verify(message, &signature); err != nil {
     65 		t.Fatalf("signature verification: %v", err)
     66 	}
     67 }
     68 func TestLocalSourceSignsWithAgentWhenPrivateFileIsUnavailable(t *testing.T) {
     69 	directory := t.TempDir()
     70 	publicRaw, privateKey, err := ed25519.GenerateKey(rand.Reader)
     71 	if err != nil {
     72 		t.Fatal(err)
     73 	}
     74 	publicKey, err := ssh.NewPublicKey(publicRaw)
     75 	if err != nil {
     76 		t.Fatal(err)
     77 	}
     78 	publicPath := filepath.Join(directory, "agent-only.pub")
     79 	if err := os.WriteFile(publicPath, ssh.MarshalAuthorizedKey(publicKey), 0o644); err != nil {
     80 		t.Fatal(err)
     81 	}
     82 
     83 	keyring := agent.NewKeyring()
     84 	if err := keyring.Add(agent.AddedKey{PrivateKey: privateKey}); err != nil {
     85 		t.Fatal(err)
     86 	}
     87 	socket := filepath.Join(t.TempDir(), "agent.sock")
     88 	listener, err := net.Listen("unix", socket)
     89 	if err != nil {
     90 		t.Fatal(err)
     91 	}
     92 	defer listener.Close()
     93 	go func() {
     94 		connection, acceptErr := listener.Accept()
     95 		if acceptErr == nil {
     96 			defer connection.Close()
     97 			_ = agent.ServeAgent(keyring, connection)
     98 		}
     99 	}()
    100 
    101 	source := NewLocalSource(directory, socket)
    102 	keys, err := source.Keys(context.Background())
    103 	if err != nil {
    104 		t.Fatal(err)
    105 	}
    106 	if len(keys) != 1 {
    107 		t.Fatalf("keys = %#v", keys)
    108 	}
    109 	message := []byte("agent challenge")
    110 	encodedSignature, err := source.Sign(context.Background(), keys[0], message)
    111 	if err != nil {
    112 		t.Fatal(err)
    113 	}
    114 	var signature ssh.Signature
    115 	if err := ssh.Unmarshal(encodedSignature, &signature); err != nil {
    116 		t.Fatal(err)
    117 	}
    118 	if err := publicKey.Verify(message, &signature); err != nil {
    119 		t.Fatalf("signature verification: %v", err)
    120 	}
    121 }