aboutsummaryrefslogtreecommitdiff
path: root/pkg/signatures/ssh
diff options
context:
space:
mode:
authorRasmus Dahlberg <rasmus@mullvad.net>2022-04-13 15:07:34 +0200
committerRasmus Dahlberg <rasmus@mullvad.net>2022-04-13 15:07:34 +0200
commitd86d2433e0da077063bb21dc7c29d491c6fe862f (patch)
tree5f760e33f25bfea5fca3fcb7c9f1f43d79dc99d9 /pkg/signatures/ssh
parent468b097a63c52fbf851c4cc99d8b716a13c19aa9 (diff)
parentee322c9e18b9675aab08f4c9f38f6be19b1d6890 (diff)
Merge branch 'sshsig' into main
Diffstat (limited to 'pkg/signatures/ssh')
-rw-r--r--pkg/signatures/ssh/ssh.go89
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
}