diff options
author | Rasmus Dahlberg <rasmus@mullvad.net> | 2022-04-13 15:07:34 +0200 |
---|---|---|
committer | Rasmus Dahlberg <rasmus@mullvad.net> | 2022-04-13 15:07:34 +0200 |
commit | d86d2433e0da077063bb21dc7c29d491c6fe862f (patch) | |
tree | 5f760e33f25bfea5fca3fcb7c9f1f43d79dc99d9 /pkg/signatures/ssh | |
parent | 468b097a63c52fbf851c4cc99d8b716a13c19aa9 (diff) | |
parent | ee322c9e18b9675aab08f4c9f38f6be19b1d6890 (diff) |
Merge branch 'sshsig' into main
Diffstat (limited to 'pkg/signatures/ssh')
-rw-r--r-- | pkg/signatures/ssh/ssh.go | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/pkg/signatures/ssh/ssh.go b/pkg/signatures/ssh/ssh.go index d5fb8f4..99b2a48 100644 --- a/pkg/signatures/ssh/ssh.go +++ b/pkg/signatures/ssh/ssh.go @@ -3,20 +3,105 @@ package ssh import ( "fmt" "io" + "io/ioutil" + "encoding/pem" + sshLib "golang.org/x/crypto/ssh" "git.sigsum.org/sigsum-lib-go/pkg/types" ) type Parser struct{} +const ( + BLOB_PREAMBLE = "SSHSIG" + SIG_VERSION = 0x01 + HASH_ALGO = "sha256" +) + +type sshBlob struct { + MagicPreamble [6]byte + SigVersion uint32 + PublicKey string + Namespace string + Reserved string + HashAlgorithm string + Signature string +} + +type sshKeypart struct { + Type string + Key string +} + func (p *Parser) SignatureSuffix() string { return ".sig" } func (p *Parser) PublicKey(r io.Reader) (*types.PublicKey, error) { - return nil, fmt.Errorf("TODO") + b, err := ioutil.ReadAll(r) + if err != nil { + return nil, fmt.Errorf("ssh: read failed: %v", err) + } + var pub types.PublicKey + if err := parsePub(pub[:], b); err != nil { + return nil, fmt.Errorf("ssh: %v", err) + } + return &pub, nil } func (p *Parser) Signature(r io.Reader) (*types.Signature, error) { - return nil, fmt.Errorf("TODO") + b, err := ioutil.ReadAll(r) + if err != nil { + return nil, fmt.Errorf("ssh: signature read failed: %v", err) + } + + block, rest := pem.Decode(b) + if len(rest) > 0 { + return nil, fmt.Errorf("ssh: invalid signature rest: %v", rest) + } + if block == nil { + return nil, fmt.Errorf("ssh: invalid signature PEM format") + } + if block.Type != "SSH SIGNATURE" { + return nil, fmt.Errorf("ssh: invalid signature PEM type: %v", block.Type) + } + + var blob sshBlob + if err := sshLib.Unmarshal(block.Bytes, &blob); err != nil { + return nil, fmt.Errorf("ssh: invalid signature format: %v", err) + } + if string(blob.MagicPreamble[:]) != BLOB_PREAMBLE { + return nil, fmt.Errorf("ssh: invalid signature magic: %s", string(blob.MagicPreamble[:])) + } + if blob.SigVersion != SIG_VERSION { + return nil, fmt.Errorf("ssh: invalid signature version: %d", blob.SigVersion) + } + if blob.HashAlgorithm != HASH_ALGO { + return nil, fmt.Errorf("ssh: invalid signature hash algorithm: %s", blob.HashAlgorithm) + } + + var sshSig sshLib.Signature + if err := sshLib.Unmarshal([]byte(blob.Signature), &sshSig); err != nil { + return nil, fmt.Errorf("ssh: invalid signature blob: %v", err) + } + + var sig types.Signature + copy(sig[:], sshSig.Blob) + + return &sig, nil +} + +func parsePub(dst, data []byte) error { + pubkey, _, _, _, err := sshLib.ParseAuthorizedKey(data) + if err != nil { + return fmt.Errorf("ssh.ParseAuthorizedKey: %s", err) + } + + var keyPart sshKeypart + if err := sshLib.Unmarshal(pubkey.Marshal(), &keyPart); err != nil { + return fmt.Errorf("ssh: invalid pubkey: %v", err) + } + + copy(dst[:], keyPart.Key) + return nil } |