Skip to content

Commit

Permalink
Init project
Browse files Browse the repository at this point in the history
  • Loading branch information
Oskar Sharipov committed Jul 21, 2022
0 parents commit 707a0c7
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/mstrusted
133 changes: 133 additions & 0 deletions cmd/mstrusted/mstrusted.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package main

import (
"bufio"
"flag"
"fmt"
"io"
"log"
"os"

"aead.dev/minisign"
"oskarsh.ru/mstrusted"
)

func main() {
var (
hashFlag bool
sigFile string
outputFlag bool
quietFlag bool
prettyQuietFlag bool
file string
)
flag.BoolVar(&hashFlag, "H", false, "require input to be prehashed.")
flag.StringVar(&sigFile, "x", "", "signature file (default: <file>.minisig)")
flag.BoolVar(&outputFlag, "o", false, "output the file content after verification")
flag.BoolVar(&quietFlag, "q", false, "quiet mode, suppress output")
flag.BoolVar(&prettyQuietFlag, "Q", false, "pretty quiet mode, only print the trusted comment")
flag.StringVar(&file, "m", "", "file to verify.")
flag.Parse()

pubKey, err := mstrusted.SearchTrustedPubKey(sigFile)
if err != nil {
log.Fatalf("Error: %v", err)
}
log.Println(pubKey)
verifyFile(sigFile, "", pubKey, outputFlag, quietFlag, prettyQuietFlag, hashFlag, file)
}

// Code below was taken from https://github.com/aead/minisign/blob/0d530c6fc203bf1fee619d51809807cc3ed68e7d/cmd/minisign/minisign.go.
// Copyright (c) 2021 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the https://github.com/aead/minisign/blob/0d530c6fc203bf1fee619d51809807cc3ed68e7d/LICENSE file.

func verifyFile(sigFile, pubFile, pubKeyString string, printOutput, quiet, prettyQuiet, requireHash bool, files ...string) {
if len(files) == 0 {
log.Fatalf("Error: no files to verify. Use -m to specify a file path")
}
if len(files) > 1 {
log.Fatalf("Error: too many files to verify. Only one file can be specified")
}
if sigFile == "" {
sigFile = files[0] + ".minisig"
}

var (
publicKey minisign.PublicKey
err error
)
if pubKeyString != "" {
if err = publicKey.UnmarshalText([]byte(pubKeyString)); err != nil {
log.Fatalf("Error: invalid public key: %v", err)
}
} else {
publicKey, err = minisign.PublicKeyFromFile(pubFile)
if err != nil {
log.Fatalf("Error: %v", err)
}
}

signature, err := minisign.SignatureFromFile(sigFile)
if err != nil {
log.Fatalf("Error: %v", err)
}
if signature.KeyID != publicKey.ID() {
log.Fatalf("Error: key IDs do not match. Try a different public key.\nID (public key): %X\nID (signature) : %X", publicKey.ID(), signature.KeyID)
}

rawSignature, _ := signature.MarshalText()
if requireHash && signature.Algorithm != minisign.HashEdDSA {
log.Fatal("Legacy (non-prehashed) signature found")
}
if signature.Algorithm == minisign.HashEdDSA || requireHash {
file, err := os.Open(files[0])
if err != nil {
log.Fatalf("Error: %v", err)
}
reader := minisign.NewReader(file)
if _, err = io.Copy(io.Discard, reader); err != nil {
file.Close()
log.Fatalf("Error: %v", err)
}

if !reader.Verify(publicKey, rawSignature) {
file.Close()
log.Fatal("Error: signature verification failed")
}
if !quiet {
if !prettyQuiet {
fmt.Println("Signature and comment signature verified")
}
fmt.Println("Trusted comment:", signature.TrustedComment)
}
if printOutput {
if _, err = file.Seek(0, io.SeekStart); err != nil {
file.Close()
log.Fatalf("Error: %v", err)
}
if _, err = io.Copy(os.Stdout, bufio.NewReader(file)); err != nil {
file.Close()
log.Fatalf("Error: %v", err)
}
}
file.Close()
} else {
message, err := os.ReadFile(files[0])
if err != nil {
log.Fatalf("Error: %v", err)
}
if !minisign.Verify(publicKey, message, rawSignature) {
log.Fatal("Error: signature verification failed")
}
if !quiet {
if !prettyQuiet {
fmt.Println("Signature and comment signature verified")
}
fmt.Println("Trusted comment:", signature.TrustedComment)
}
if printOutput {
os.Stdout.Write(message)
}
}
}
10 changes: 10 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module oskarsh.ru/mstrusted

go 1.18

require aead.dev/minisign v0.2.0

require (
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46 h1:V066+OYJ66oTjnhm4Yrn7SXIwSCiDQJxpBxmvqb1N1c=
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
2 changes: 2 additions & 0 deletions internal/testdata/key.priv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
untrusted comment: minisign encrypted secret key
RWRTY0IycmRrG6A41efui3sFVTW/Ft4mlFQfRi2HmK29IWCDllcAAAACAAAAAAAAAEAAAAAAVjdsSvEDVXb/RHvRtitxpZ6FQpJzUJTlZp0y32zwwaEbaUYIBrwJ4Y70XXvqq/If3R69RMlTGVe/umar/kD7ijVmHrapkwqkKU9jJ0vBoravN/weFEJLpPh4R8mKzT+ssPMZLPN7JR4=
2 changes: 2 additions & 0 deletions internal/testdata/key.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
untrusted comment: minisign public key 27E633F4A0EA7E56
RWRWfuqg9DPmJzteqVmj5xSm7z1V0ZTNA66UGpF+5vdkUe8llEMWkC6n
1 change: 1 addition & 0 deletions internal/testdata/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello World!
4 changes: 4 additions & 0 deletions internal/testdata/test.txt.minisig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
untrusted comment: signature from minisign secret key
RWRWfuqg9DPmJ53RyYcQ5hxFSl2VYIcGLj51J2+49WJ9aro2ONvCVs0ruJmpFtQrLWGNYvMXnyLfi4/fqzqI4/EUmyvh0Xucxg4=
trusted comment: timestamp:1658442208 file:test.txt
Q+xNdjGSPRCHer/1q0jZv2I0JvUypYA2plaervO/D4S9RKNB2WcCSocZgxVc/Pav61b0brRMvfOuEZidp/g1AQ==
66 changes: 66 additions & 0 deletions mstrusted.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package mstrusted

import (
"errors"
"io/ioutil"
"log"
"os"
"path/filepath"
"strconv"
"strings"

"aead.dev/minisign"
)

func getTrustedPath() string {
dirname, err := os.UserHomeDir()
if err != nil {
log.Fatal(err)
}
return filepath.Join(dirname, ".minisign/trusted")
}

func ensureTrustedDir() error {
err := os.MkdirAll(getTrustedPath(), 0700)
if !os.IsExist(err) {
return err
}
return nil
}

func extractID(s minisign.Signature) string {
return strings.ToUpper(strconv.FormatUint(s.KeyID, 16))
}

func readPubKey(keyPath string) (minisign.PublicKey, error) {
bytes, err := ioutil.ReadFile(keyPath)
if os.IsNotExist(err) {
return minisign.PublicKey{}, errors.New("mstrusted: public key doesn't exist.")
} else if err != nil {
return minisign.PublicKey{}, errors.New("mstrusted: public key is unreadable.")
}
var key minisign.PublicKey
if err = key.UnmarshalText(bytes); err != nil {
return minisign.PublicKey{}, err
}
return key, nil
}

func SearchTrustedPubKey(sigFile string) (string, error) {
if err := ensureTrustedDir(); err != nil {
return "", errors.New("mstrusted: can't create trusted directory.")
}

signature, err := minisign.SignatureFromFile(sigFile)
if err != nil {
return "", err
}

keyPath := filepath.Join(getTrustedPath(), extractID(signature)+".pub")
key, err := readPubKey(keyPath)
if err != nil {
return "", err
}

return key.String(), nil
}

0 comments on commit 707a0c7

Please sign in to comment.