-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Oskar Sharipov
committed
Jul 21, 2022
0 parents
commit 707a0c7
Showing
9 changed files
with
231 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/mstrusted |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
untrusted comment: minisign public key 27E633F4A0EA7E56 | ||
RWRWfuqg9DPmJzteqVmj5xSm7z1V0ZTNA66UGpF+5vdkUe8llEMWkC6n |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Hello World! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |