This commit is contained in:
Ben Toews 2017-11-29 13:50:15 -07:00
Родитель 5abdd89a0b
Коммит f50a4eebe8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E9C423BE17EFEE70
4 изменённых файлов: 123 добавлений и 106 удалений

Просмотреть файл

@ -10,24 +10,16 @@ import (
"github.com/mastahyeti/certstore"
"github.com/mastahyeti/cms"
"github.com/pkg/errors"
)
func commandSign() int {
idents, err := store.Identities()
func commandSign() {
userIdent, err := findUserIdentity()
if err != nil {
panic(err)
}
for _, ident := range idents {
defer ident.Close()
}
userIdent, err := findUserIdentity(idents)
if err != nil {
panic(err)
faile(err, "failed to get identity matching specified user-id")
}
if userIdent == nil {
fmt.Printf("Could not find identity matching specified user-id: %s\n", *localUserOpt)
return 1
failf("Could not find identity matching specified user-id: %s\n", *localUserOpt)
}
// Git is looking for "\n[GNUPG:] SIG_CREATED ", meaning we need to print a
@ -37,17 +29,17 @@ func commandSign() int {
chain, err := userIdent.CertificateChain()
if err != nil {
panic(err)
faile(err, "failed to get idenity certificate chain")
}
signer, err := userIdent.Signer()
if err != nil {
panic(err)
faile(err, "failed to get idenity signer")
}
dataBuf := new(bytes.Buffer)
if _, err = io.Copy(dataBuf, os.Stdin); err != nil {
panic(err)
faile(err, "failed to read message from stdin")
}
var der []byte
@ -57,7 +49,7 @@ func commandSign() int {
der, err = cms.Sign(dataBuf.Bytes(), chain, signer)
}
if err != nil {
panic(err)
faile(err, "failed to sign message")
}
emitSigCreated(chain[0], *detachSignFlag)
@ -71,15 +63,13 @@ func commandSign() int {
_, err = os.Stdout.Write(der)
}
if err != nil {
panic(err)
fail("failed to write signature")
}
return 0
}
// findUserIdentity attempts to find an identity to sign with in the certstore
// by checking available identities against the --local-user argument.
func findUserIdentity(idents []certstore.Identity) (certstore.Identity, error) {
func findUserIdentity() (certstore.Identity, error) {
var (
email string
fpr []byte
@ -98,7 +88,7 @@ func findUserIdentity(idents []certstore.Identity) (certstore.Identity, error) {
for _, ident := range idents {
cert, err := ident.Certificate()
if err != nil {
return nil, err
return nil, errors.Wrap(err, "failed to get identity certificate")
}
if certHasEmail(cert, email) || certHasFingerprint(cert, fpr) {

Просмотреть файл

@ -4,7 +4,6 @@ import (
"bytes"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"os"
@ -12,17 +11,17 @@ import (
"github.com/mastahyeti/cms"
)
func commandVerify() int {
func commandVerify() {
sNewSig.emit()
if len(fileArgs) < 2 {
return verifyAttached()
verifyAttached()
} else {
verifyDetached()
}
return verifyDetached()
}
func verifyAttached() int {
func verifyAttached() {
var (
f *os.File
err error
@ -31,7 +30,7 @@ func verifyAttached() int {
// Read in signature
if len(fileArgs) == 1 {
if f, err = os.Open(fileArgs[0]); err != nil {
panic(err)
failef(err, "failed to open signature file (%s)", fileArgs[0])
}
defer f.Close()
} else {
@ -40,7 +39,7 @@ func verifyAttached() int {
buf := new(bytes.Buffer)
if _, err = io.Copy(buf, f); err != nil {
panic(err)
faile(err, "failed to read signature")
}
// Try decoding as PEM
@ -54,7 +53,7 @@ func verifyAttached() int {
// Parse signature
sd, err := cms.ParseSignedData(der)
if err != nil {
panic(err)
faile(err, "failed to parse signature")
}
// Verify signature
@ -67,8 +66,7 @@ func verifyAttached() int {
sErrSig.emit()
}
fmt.Printf("Sinature verification failed: %s\n", err.Error())
return 1
faile(err, "failed to verify signature")
}
emitGoodSig(certs)
@ -76,21 +74,19 @@ func verifyAttached() int {
// TODO: Maybe split up signature checking and certificate checking so we can
// output something more meaningful.
emitTrustFully()
return 0
}
func verifyDetached() int {
func verifyDetached() {
// Read in signature
f, err := os.Open(fileArgs[0])
if err != nil {
panic(err)
failef(err, "failed to open signature file (%s)", fileArgs[0])
}
defer f.Close()
buf := new(bytes.Buffer)
if _, err = io.Copy(buf, f); err != nil {
panic(err)
faile(err, "failed to read signature file")
}
// Try decoding as PEM
@ -104,7 +100,7 @@ func verifyDetached() int {
// Parse signature
sd, err := cms.ParseSignedData(der)
if err != nil {
panic(err)
faile(err, "failed to parse signature")
}
// Read in signed data
@ -112,7 +108,7 @@ func verifyDetached() int {
f = os.Stdin
} else {
if f, err = os.Open(fileArgs[1]); err != nil {
panic(err)
failef(err, "failed to open message file (%s)", fileArgs[1])
}
defer f.Close()
}
@ -120,7 +116,7 @@ func verifyDetached() int {
// Verify signature
buf.Reset()
if _, err = io.Copy(buf, f); err != nil {
panic(err)
faile(err, "failed to read message file")
}
certs, err := sd.VerifyDetached(buf.Bytes(), rootsPool())
@ -132,8 +128,7 @@ func verifyDetached() int {
sErrSig.emit()
}
fmt.Printf("Sinature verification failed: %s\n", err.Error())
return 1
faile(err, "failed to verify signature")
}
emitGoodSig(certs)
@ -141,8 +136,6 @@ func verifyDetached() int {
// TODO: Maybe split up signature checking and certificate checking so we can
// output something more meaningful.
emitTrustFully()
return 0
}
func rootsPool() *x509.CertPool {
@ -157,10 +150,6 @@ func rootsPool() *x509.CertPool {
}
}
idents, err := store.Identities()
if err != nil {
return roots
}
for _, ident := range idents {
if cert, err := ident.Certificate(); err == nil {
roots.AddCert(cert)

Просмотреть файл

@ -5,19 +5,11 @@ import (
"strings"
)
func commandListKeys() int {
idents, err := store.Identities()
if err != nil {
panic(err)
}
for _, ident := range idents {
defer ident.Close()
}
func commandListKeys() {
for j, ident := range idents {
cert, err := ident.Certificate()
if err != nil {
panic(err)
faile(err, "failed to get identity certificate")
}
if j > 0 {
@ -32,6 +24,4 @@ func commandListKeys() int {
fmt.Println(" Subject:", rdnSequenceString(cert.Subject.ToRDNSequence()))
fmt.Println(" Emails:", strings.Join(certEmails(cert), ", "))
}
return 0
}

138
main.go
Просмотреть файл

@ -6,6 +6,7 @@ import (
"github.com/mastahyeti/certstore"
"github.com/pborman/getopt/v2"
"github.com/pkg/errors"
)
var (
@ -23,16 +24,11 @@ var (
keyFormatOpt = getopt.EnumLong("keyid-format", 0, []string{"long"}, "long", "Select how to display key IDs.", "{long}")
fileArgs []string
store certstore.Store
idents []certstore.Identity
)
func main() {
// Open certificate store
var err error
if store, err = certstore.Open(); err != nil {
panic(err)
}
defer store.Close()
defer handleExit()
// Parse CLI args
getopt.HelpColumn = 30
@ -40,49 +36,101 @@ func main() {
getopt.Parse()
fileArgs = getopt.Args()
status := 1
if *helpFlag {
if *signFlag || *verifyFlag || *listKeysFlag {
fmt.Println("specify --help, --sign, --verify, or --list-keys")
fail("specify --help, --sign, --verify, or --list-keys")
} else {
getopt.Usage()
status = 0
return
}
} else if *signFlag {
if *helpFlag || *verifyFlag || *listKeysFlag {
fmt.Println("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) == 0 {
fmt.Println("specify a USER-ID to sign with")
} else {
status = commandSign()
}
} else if *verifyFlag {
if *helpFlag || *signFlag || *listKeysFlag {
fmt.Println("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) > 0 {
fmt.Println("local-user cannot be specified for verification")
} else if *detachSignFlag {
fmt.Println("detach-sign cannot be specified for verification")
} else if *armorFlag {
fmt.Println("armor cannot be specified for verification")
} else {
status = commandVerify()
}
} else if *listKeysFlag {
if *helpFlag || *signFlag || *verifyFlag {
fmt.Println("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) > 0 {
fmt.Println("local-user cannot be specified for list-keys")
} else if *detachSignFlag {
fmt.Println("detach-sign cannot be specified for list-keys")
} else if *armorFlag {
fmt.Println("armor cannot be specified for list-keys")
} else {
status = commandListKeys()
}
} else {
fmt.Println("specify --help, --sign, --verify, or --list-keys")
}
os.Exit(status)
// Open certificate store
store, err := certstore.Open()
if err != nil {
faile(err, "failed to open certificate store")
}
defer store.Close()
// Get list of identities
idents, err = store.Identities()
if err != nil {
faile(err, "failed to get identities from certificate store")
}
for _, ident := range idents {
defer ident.Close()
}
if *signFlag {
if *helpFlag || *verifyFlag || *listKeysFlag {
fail("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) == 0 {
fail("specify a USER-ID to sign with")
} else {
commandSign()
return
}
}
if *verifyFlag {
if *helpFlag || *signFlag || *listKeysFlag {
fail("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) > 0 {
fail("local-user cannot be specified for verification")
} else if *detachSignFlag {
fail("detach-sign cannot be specified for verification")
} else if *armorFlag {
fail("armor cannot be specified for verification")
} else {
commandVerify()
return
}
}
if *listKeysFlag {
if *helpFlag || *signFlag || *verifyFlag {
fail("specify --help, --sign, --verify, or --list-keys")
} else if len(*localUserOpt) > 0 {
fail("local-user cannot be specified for list-keys")
} else if *detachSignFlag {
fail("detach-sign cannot be specified for list-keys")
} else if *armorFlag {
fail("armor cannot be specified for list-keys")
} else {
commandListKeys()
return
}
}
fail("specify --help, --sign, --verify, or --list-keys")
}
type statusCode int
func handleExit() {
if e := recover(); e != nil {
if sc, isStatusCode := e.(statusCode); isStatusCode {
os.Exit(int(sc))
}
panic(e)
}
}
func faile(err error, message string) {
fail(errors.Wrap(err, message))
}
func failef(err error, format string, a ...interface{}) {
fail(errors.Wrapf(err, format, a...))
}
func fail(a ...interface{}) {
fmt.Fprintln(os.Stderr, a...)
panic(statusCode(1))
}
func failf(format string, a ...interface{}) {
fmt.Fprintf(os.Stderr, format, a...)
panic(statusCode(1))
}