Code Monkey home page Code Monkey logo

smimesign's Introduction

smimesign (S/MIME Sign)

PkgGoDev

Smimesign is an S/MIME signing utility for macOS and Windows that is compatible with Git. This allows developers to sign their Git commits and tags using X.509 certificates issued by public certificate authorities or their organization's internal certificate authority. Smimesign uses keys and certificates already stored in the macOS Keychain or the Windows Certificate Store.

This project is pre-1.0, meaning that APIs and functionality may change without warning.

This package also contains reusable libraries in nested packages:

Contributing

Different organizations do PKI differently and we weren't able to test everyone's setup. Contributions making this tool work better for your organization are welcome. See the contributing docs for more information on how to get involved.

Git Signing, GnuPG, PKI, and S/MIME

Git allows developers to sign their work using GnuPG. This is a form of public key cryptography whereby the notion of trust is distributed. The party verifying a signature may directly know of the signer's identity and public key, or the signer's identity may be vouched for by a third party known to the verifier. Through layers of "vouching", a web-of-trust is established.

Such a model is well suited to an unstructured environment. In hierarchical environments though, such as a corporation or other large organizations, a simpler approach is for digital identities to be issued and vouched for by a centralized authority. With this approach — known as Public Key Infrastructure, or PKI — an organization's certificate authority (CA) issues signed certificates that identify subjects such as people or computers. Embedded in these certificates is the identity's public key, allowing others who trust the CA to verify that identity's signatures.

PKI is used in a variety of applications for encrypting or authenticating communications. Secure Mime (S/MIME) standardized a protocol for encrypting and signing emails using PKI. While protecting email was the original intent, S/MIME can protect any type of data, including Git commits and tags. Signing Git data with S/MIME provides the same protections as GnuPG while allowing for the more hierarchical trust model of PKI.

Installation

macOS

You can install smimesign using Homebrew:

brew install smimesign

You can also download a prebuilt macOS binary here. Put the binary on your $PATH, so Git will be able to find it.

Windows

You can install smimesign using scoop:

scoop install smimesign

You can download prebuilt Windows binaries here. Put the appropriate binary on your %PATH%, so Git will be able to find it.

Building from source

  • Make sure you have the Go compiler installed.
  • You'll probably want to put $GOPATH/bin on your $PATH.
  • Run go get github.com/github/smimesign

Configuring Git

Git needs to be told to sign commits and tags using smimesign instead of GnuPG. This can be configured on a global or per-repository level. The Git configuration directives for changing signing tools was changed in version 2.19.

Git versions 2.19 and newer

Configure Git to use smimesign for a single repository:

$ cd /path/to/my/repository
$ git config --local gpg.x509.program smimesign
$ git config --local gpg.format x509

Configure Git to use smimesign for all repositories:

$ git config --global gpg.x509.program smimesign
$ git config --global gpg.format x509

Git versions 2.18 and older

Configure Git to use smimesign for a single repository:

$ cd /path/to/my/repository
$ git config --local gpg.program smimesign

Configure Git to use smimesign for all repositories:

$ git config --global gpg.program smimesign

Configuring smimesign

No configuration is needed to use smimesign. However, you must already have a certificate and private key in order to make signatures. Furthermore, to sign Git commits or tags, it is best to have a certificate that includes your Git email address.

Find your Git email address:

$ git config --get user.email

List available signing identities

$ smimesign --list-keys

Smart cards (PIV/CAC/Yubikey)

Many large organizations and government agencies distribute certificates and keys to end users via smart cards. These cards allow applications on the user's computer to use private keys for signing or encryption without giving them the ability to export those keys. The native certificate stores on both Windows and macOS can talk to smart cards, though special drivers or middleware may be required.

If you can find your certificate in the Keychain Access app on macOS or in the Certificate Manager (certmgr) on Windows, it will probably work with smimesign. If you can't find it, you may need to install some drivers or middlware.

Yubikey

Many Yubikey models support the PIV smart card interface. To get your operating system to discover certificates and keys on your Yubikey, you may have to install the OpenSC middleware. On macOS avoid installing OpenSC using homebrew, as it omits an important component. Instead use the installer provided by OpenSC or use the homebrew-cask formula.

Additionally, to manage the manage certificates and keys on the Yubikey on macOS, you'll need the Yubikey PIV Manager (GUI) or the Yubikey PIV Tool (command line).

Yubikey PIV Keychain in macOS Keychain Access app

smimesign's People

Contributors

btoews avatar cryptoque avatar grantbirki avatar kant avatar lgarron avatar mastahyeti avatar vcsjones avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smimesign's Issues

Build `x86` on Windows with the built-in tools

We build amd64 directly:

GOARCH=amd64 go build -o "build/amd64/smimesign.exe" -ldflags "-X main.versionString=${{ env.GIT_VERSION }}"

But I had trouble figuring out how to build for GOARCH=386 without errors. Right now, we use https://github.com/egor-tensin/setup-mingw to switch to 32-bit builds, which pulls down a bunch of tooling and takes a few minutes:

- name: Switch MinGW to x86
# Pinned hash from https://github.com/egor-tensin/setup-mingw/releases/tag/v2
uses: egor-tensin/setup-mingw@f3c5d799aadf8fa230ac67a422b01dd085bbc96b
with:
platform: x86

I can't help but feel there must still be a nice (or at least much faster) way to do this using the built-in tools from Actions.

Panic if smart card not present

Hey, I use a certificate on a smart card. If I don't have the smart card inserted, the tol panics.

$ git revert -S HEAD
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x8 pc=0x555585]

goroutine 1 [running]:
github.com/github/smimesign/vendor/github.com/mastahyeti/certstore.(*winPrivateKey).Public(0x0, 0xc0000716b0, 0x4)
        c:/gopath/src/github.com/github/smimesign/vendor/github.com/mastahyeti/certstore/certstore_windows.go:356 +0x5
github.com/github/smimesign/vendor/github.com/mastahyeti/cms/protocol.(*SignedData).AddSignerInfo(0xc00005af70, 0xc000081e68, 0x1, 0x1, 0x799c80, 0x0, 0x0, 0x0)
        c:/gopath/src/github.com/github/smimesign/vendor/github.com/mastahyeti/cms/protocol/protocol.go:587 +0x53
github.com/github/smimesign/vendor/github.com/mastahyeti/cms.(*SignedData).Sign(0xc0000060b0, 0xc000081e68, 0x1, 0x1, 0x799c80, 0x0, 0x0, 0xc000014c30)
        c:/gopath/src/github.com/github/smimesign/vendor/github.com/mastahyeti/cms/sign.go:48 +0x67
main.commandSign(0xc000000008, 0x79b3a8)
        c:/gopath/src/github.com/github/smimesign/command_sign.go:49 +0x254
main.runCommand(0x0, 0x0)
        c:/gopath/src/github.com/github/smimesign/main.go:97 +0x27c
main.main()
        c:/gopath/src/github.com/github/smimesign/main.go:52 +0x2d
error: gpg failed to sign the data
fatal: failed to write commit object

fetching public keys from keyserver

On Linux gpgsm will use its dirmngr to fetch certificates from LDAP. In most cooperate setups that is going to be the Active Directory LDAP. That is also where Email clients get it from. Not sure whether that is a direct call to LDAP or a call to the OS's trust/cert store.

What i do see on Windows is that i can verify my own signatures but verification of other signatures fails. And i assume the reason is that the certificates are not yet known and need to be fetched from the keyserver. I could not really verify that yet.

Maybe someone can explain how i browse the trust-store on Windows, and how i would manually import a cert into it.

But if the asumtion is correct smimesign needs to import the certs when encountered. I would hope that there are libraries that can just be called on MacOS and Windows. Something like OS.smime.find_and_import_according_to_global_config(email)

How to specify a timestamp server

The utility supports a timestamp parameter, but it's not clear how to specify it in the git configuration so that it's used.

How do we specify the timestamp server to use?

Error or warning when using an expired certificate?

Hello! I'm wondering if it would be possible to configure smimesign to error out (or at least display a warning) if the certificate you are using to sign commits has expired. I am trying to implement a system for git signing with shorter-lived developer certificates (30 days) and it would be really helpful if a warning or error message would let developers know that their certificate has expired and they should request a new one.

Currently smimesign will go ahead and sign commits with expired certificates with no output, but then verification fails:

$ git log --show-signature
commit 923459dd4798833eb56f0f376fcd6d0b3fc86e04 (HEAD -> master)
failed to verify signature: x509: certificate has expired or is not yet valid: current time 2021-10-01T13:56:16-05:00 is after 2021-10-01T18:54:21Z

I know we're limited in what git passes to smimesign so i'd be fine to use a wrapper script or command, but would need a command line flag to indicate it should exit with error if the signing certificate is expired.

Let me know your thoughts and I'd be happy to open a PR!

Make documentation clear about Linux

Hello all,

I am aware about both #30 and #31, but not before I actually downloaded the launcher and hit the error message. I suggest to change the README.md to say that Linux is not supported (preferably on top and at Installation section).

I also want to report that official documentation clearly says that smimesign works on Linux which is obviously wrong. I am aware this is not the best place for issues related to that webpage but I didn't find an easy way to report misleading content there so I hope you can forward this to administrators of that site.

Best regards,
Petr Vsetecka

Small error in example in readme

In the code:

sd, _ := ParseSignedData(der)
if err, _ := sd.VerifyDetached(msg, x509.VerifyOptions{}); err != nil {
    panic(err)
}

I think if err, _ should be if _, err

Questions

I have my gpg2 key created for signing commits on git, I need to know that what's the point in using smimesign? PS:- i Know this is protective way of storing keys I want to Know how can I create x.509 keys ? And sign my commits with it and it's handy?
After generating a x.509 key than I have to copy it in which directory in my machine so that git can detect it?, Or after this all I need only x.509 not my old gpg keys?
Suggest me a way to do this! (like: gpgsm, gnup)
PS:- give full steps to do this!

SecTrustEvaluate is deprecated

When compiling on macOS 10.15.6 with xcode 12.0.1:

cgo-gcc-prolog:473:11: warning: 'SecTrustEvaluate' is deprecated: first deprecated in macOS 10.15 [-Wdeprecated-declarations]
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecTrust.h:353:10: note: 'SecTrustEvaluate' has been explicitly marked deprecated here

According to the doc, SecTrustEvaluateWithError should be used.
https://developer.apple.com/documentation/security/2980705-sectrustevaluatewitherror

Windows APP Information

After installing the Windows binary, only the version number is displayed under Settings/APP, but not that it is the smimesign application. The name should actually appear here

image

x509 signatures do not contain signing date

Looking at a repo with x509 signed commits i found that smimesign signatures look different when verified on Linux with gpgsm. They seem to not contain the signing date, or not in the expected format.

A commit signed on Linux will look like that:

gpgsm: Signature made yyyy-mm-dd hh:mm:ss using certificate ID 0xXXXXX
gpgsm: Good signature from ...
...

Signatures made with smimesign Windows and Mac

gpgsm: Signature made [date not given] using certificate ID 0xXXXXX
gpgsm: Good signature from ...
...

this is gpgsm-2.2.10 checking the signatures

certstore: certstore_windows.go type error

After installing & importing the smimesign/certstore package, I get the following error while running my go main program:

....\go\pkg\mod\github.com\github\[email protected]\certstore\certstore_windows.go:640:29: cannot convert cmsg (variable of type *_Ctype_char) to type _Ctype_HANDLE

the only code I have added is the following:

store, err := certstore.Open()
if err != nil {
	fmt.Println(err)
}
defer store.Close()

Is there a way to fix this ?

Support crypto/x509.SystemCertPool

Currently, smimesign relies on system trust stores (via #7) for Darwin and Windows. This leaves other systems (namely linux) unable to build:

$ go get github.com/github/smimesign
# github.com/github/smimesign/vendor/github.com/mastahyeti/certstore
../src/github.com/github/smimesign/vendor/github.com/mastahyeti/certstore/certstore.go:17:9: undefined: openStore
$ echo $?
2

One solution (I think) would be to add support for Go's CertPool. This could be a suitable backend in certstore; at a glance, I believe the interface is compatible:

// Open opens the system's certificate store.
func Open() (Store, error) {
return openStore()
}
// Store represents the system's certificate store.
type Store interface {
// Identities gets a list of identities from the store.
Identities() ([]Identity, error)
// Import imports a PKCS#12 (PFX) blob containing a certificate and private
// key.
Import(data []byte, password string) error
// Close closes the store.
Close()
}
// Identity is a X.509 certificate and its corresponding private key.
type Identity interface {
// Certificate gets the identity's certificate.
Certificate() (*x509.Certificate, error)
// CertificateChain attempts to get the identity's full certificate chain.
CertificateChain() ([]*x509.Certificate, error)
// Signer gets a crypto.Signer that uses the identity's private key.
Signer() (crypto.Signer, error)
// Delete deletes this identity from the system.
Delete() error
// Close any manually managed memory held by the Identity.
Close()
}

go env
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/me/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/me"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build685245200=/tmp/go-build -gno-record-gcc-switches"

Build failure when upgrade to `v0.0.13`

relates to Homebrew/homebrew-core#39770

failure log

==> go build -o /usr/local/Cellar/smimesign/0.0.13/bin/smimesign -ldflags -X main.versionString=0.0.13
command_verify.go:11:2: cannot find package "github.com/certifi/gocertifi" in any of:
	/usr/local/Cellar/go/1.12.5/libexec/src/github.com/certifi/gocertifi (from $GOROOT)
	/private/tmp/smimesign-20190513-77950-ig2itw/smimesign-0.0.13/src/github.com/certifi/gocertifi (from $GOPATH)
command_sign.go:12:2: cannot find package "github.com/mastahyeti/certstore" in any of:
	/usr/local/Cellar/go/1.12.5/libexec/src/github.com/mastahyeti/certstore (from $GOROOT)
	/private/tmp/smimesign-20190513-77950-ig2itw/smimesign-0.0.13/src/github.com/mastahyeti/certstore (from $GOPATH)
command_sign.go:13:2: cannot find package "github.com/mastahyeti/cms" in any of:
	/usr/local/Cellar/go/1.12.5/libexec/src/github.com/mastahyeti/cms (from $GOROOT)
	/private/tmp/smimesign-20190513-77950-ig2itw/smimesign-0.0.13/src/github.com/mastahyeti/cms (from $GOPATH)
main.go:11:2: cannot find package "github.com/pborman/getopt/v2" in any of:
	/usr/local/Cellar/go/1.12.5/libexec/src/github.com/pborman/getopt/v2 (from $GOROOT)
	/private/tmp/smimesign-20190513-77950-ig2itw/smimesign-0.0.13/src/github.com/pborman/getopt/v2 (from $GOPATH)
command_sign.go:14:2: cannot find package "github.com/pkg/errors" in any of:
	/usr/local/Cellar/go/1.12.5/libexec/src/github.com/pkg/errors (from $GOROOT)
	/private/tmp/smimesign-20190513-77950-ig2itw/smimesign-0.0.13/src/github.com/pkg/errors (from $GOPATH)
status.go:11:2: cannot find package "golang.org/x/crypto/openpgp/packet" in any of:
	/usr/local/Cellar/go/1.12.5/libexec/src/golang.org/x/crypto/openpgp/packet (from $GOROOT)
	/private/tmp/smimesign-20190513-77950-ig2itw/smimesign-0.0.13/src/golang.org/x/crypto/openpgp/packet (from $GOPATH)
status.go:12:2: cannot find package "golang.org/x/crypto/openpgp/s2k" in any of:
	/usr/local/Cellar/go/1.12.5/libexec/src/golang.org/x/crypto/openpgp/s2k (from $GOROOT)
	/private/tmp/smimesign-20190513-77950-ig2itw/smimesign-0.0.13/src/golang.org/x/crypto/openpgp/s2k (from $GOPATH)

failed build, https://jenkins.brew.sh/job/Homebrew%20Core%20Pull%20Requests/41860/version=mojave/console

smimesign and gpgsm compability

It's seems for me that signatures made by smimesign cannot be verified by gpgsm. gpgsm uses for ID string like this 0x85B45FC2 and smimesign just cert fingerprint. So gpgsm simply cannot found this cert:

gpgsm: Signature made 2022-08-02 08:31:38 UTC
gpgsm:                using rsa1024 key 1330B26E34290E780CF1B34E14E0D06F85B45FC2
gpgsm: certificate not found: No public key
gpgsm: certificate #7C0015897CCB1524C0A9128ADE00000015897C/CN=test,DC=test
gpgsm: checking the CRL failed: Not found
gpgsm: invalid certification chain: Not found

Export the psd in cms.SignedData

hi could please export the psd filed in
type SignedData struct { psd *protocol.SignedData }
or provide a function that return this filed

Certificate that can not be parsed

I am using Microsoft Skype for Business.
This software automatically generates a certificate when I sign in.
smimesign can't parse it.

smimesign --list-keys
WARNING: failed to get identity certificate: certificate parsing failed: asn1: syntax error: PrintableString contains invalid character

The content of the certificate is as follows.
I can not export the private key of this certificate, but I hope that it will give you some clues.

-----BEGIN CERTIFICATE-----
MIIDkjCCAnqgAwIBAgIK/CPxFSbWT3GRATANBgkqhkiG9w0BAQsFADAgMR4wHAYD
VQQDExVDb21tdW5pY2F0aW9ucyBTZXJ2ZXIwHhcNMTgxMTA4MDMxMTQzWhcNMTgx
MTA4MTExMTQzWjAZMRcwFQYDVQQDEw5hZXRvc0BhZXJpZS5qcDCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJleXQfrjQGptnfAjT6e6G0zCQbVXliZcak1
uSRyPrhMpL0P82crX6yfT1GW2qbeQzHBu4EwfpPEZYSr9MQPiMK+6S23CxVCD/FM
L2HRxFVJSCORefA3ZMiu81dG2wac0t+pUXJngwTAoVN0c0Xzkm6rL1JGcLDTK1qP
ZEfiTIR8teCn2iB8lFsOO3BPKIS3UH3icqOQyh5cqNQsLJ24EDuF8yT1JIKasAwx
Q9MVeLRTIvCqKty/81wZriN6oBDBzKw0qZ9BgC/EM71B5Wd734YTptEwn4IK2C5j
HjjuHie5gDkJq+Bze94ks+Tn/M6K7qIhQwEpJMzX1dtXB4V/t4kCAwEAAaOB1DCB
0TATBgNVHSUEDDAKBggrBgEFBQcDAjAtBgNVHQ4EJgQkNzQ1RTIyMDYtMDY0OS01
M0IyLTgyNDYtQzE3NDZGNTdDMTA1MEcGA1UdIwRAMD6AHHR5MWpwMTA2ZmVzMDIu
aW5mcmEubHluYy5jb22hHoIcdHkxanAxMDZmZXMwMi5pbmZyYS5seW5jLmNvbTAn
BgNVHRIEIDAeghx0eTFqcDEwNmZlczAyLmluZnJhLmx5bmMuY29tMBkGA1UdEQQS
MBCBDmFldG9zQGFlcmllLmpwMA0GCSqGSIb3DQEBCwUAA4IBAQCZDJOf6fMta56I
3A5coCk+NdC8Vz6Eda2GcRHNkimA1S+3l1bZlnlQKsR/pHfuS//F6xPhLqxQ8UFL
t6a9lPwYxcvd7wYiMUPb7TARLcamZvKXqusCjaA8VUBNhcUlild2WLj6LhODpY0A
ExsU7BY11HfMvtfYl0B+TdjRWHDyI1ajJQV8Xl/mKfPlUm7LRrvnnnDJzeROzkYa
7TAjrfqYYiq4rWBt4namTapo9/MJlsyNLFmJmpWWzUuKnRycUowMR/NUuvWMMqtb
IDzuqu75PMowS4OWpNODNTSjNoaHW22FCf54MKwGKxtKU68EGK9tNm1+iX9oJBx2
brbYB8Tw
-----END CERTIFICATE-----

smimesign --version
0.0.6

certstore: supply pin code

I can successfully access the certificate stored on the smart card, but is there a way to programatically set the pin code?

Should I use ID instead of certificate S/N?

The documentation is described as:

  1. From the list of X.509 keys, copy the serial number (S/N) of the X.509 key you'd like to use. In this example, the serial number is a2dfa7e8c9c4d1616f1009c988bb70f:

However, it's incorrect.

When I did that, I could not sign a commit.
When I used ID (thumbprint) instead of S/N, I could sign successfully.

Environments:

smimesign --version
0.0.6
git --version
git version 2.19.1.windows.1

ListKeys fails with Certificate Parsing Failed

I'm not able to list all my installed keys, the command --list-keys fails with:

failed to get identity certificate: certificate parsing failed: asn1: syntax error: PrintableString contains invalid character

How can I find the offending certificate?

Mention incompatibility with linux in readme?

Maybe it's just me, but I put some time in this because we thought we could use smimesign for our project. I tried to compile from source as per instructions given in your readme.
Only to find out just now that smimesign depends on a go library (certstore) that is not supported in linux environments (yet).

->
https://github.com/github/certstore/blob/master/certstore_linux.go

package certstore

import "errors"

// This will hopefully give a compiler error that will hint at the fact that
// this package isn't designed to work on Linux.
func init() {
	CERTSTORE_DOESNT_WORK_ON_LINIX
}

Just thought if you could mention this in your readme maybe it would save someone else's time so they don't have to go through the whole process only to find out it's not supported.

protocol: BER2DER does not handle empty indefinite length objects

For indefinite length objects, we check for the terminator here:

if indefinite {

However, this does not consider that a SEQUENCE or SET can be potentially empty with indefinite length.
Instead, I think the proper thing is to first check for the termination sequence and only then read the object.
I.e., move the if condition above this line:

var subObj asn1Object

Unexpected "certificate has expired or is not yet valid"

I have a file and a CMS signature for it and I'm trying to verify them using ietf-cms, but it returns an error saying the certificate is expired. When performing the same check using openssl, it succeeds.

I'm not very familiar with CMS, so the only information I'm able to give you are both files, the code I wrote to check them using ietf-cms, and the command I used to validate them using openssl.

Files

Archive.zip

OpenSSL Command

openssl cms -verify -inform DER -in ./sig -content ./dat -purpose any

OpenSSL Output

CMS Verification successful

IETF-CMS Code

package main

import (
	"crypto/x509"
	"encoding/base64"
	"log"

	"github.com/github/smimesign/ietf-cms"
)

const (
	dat64 = "2TGNnpt9PwNF0Xxb4tQaU4gIW8U="
	sig64 = "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"
)

func main() {
	dat, err := base64.StdEncoding.DecodeString(dat64)
	if err != nil {
		log.Panic(err)
	}

	sig, err := base64.StdEncoding.DecodeString(sig64)
	if err != nil {
		log.Panic(err)
	}

	sd, err := cms.ParseSignedData(sig)
	if err != nil {
		log.Panic(err)
	}

	certs, err := sd.VerifyDetached(dat, x509.VerifyOptions{})
	if err != nil {
		log.Panic(err)
	}

	log.Print(certs)
}

IETF-CMS Output

2022/03/22 01:20:13 x509: certificate has expired or is not yet valid: current time 2022-03-22T01:20:13Z is after 2019-10-28T23:50:01Z
panic: x509: certificate has expired or is not yet valid: current time 2022-03-22T01:20:13Z is after 2019-10-28T23:50:01Z

goroutine 1 [running]:
log.Panic({0xc000199f60, 0x0, 0x0})
    /nix/store/d9rw46ym59cszc79n4vs60yqfz5rkps9-go-1.17.3/share/go/src/log/log.go:354 +0x65
main.main()
    /home/runner/IllustriousHandsomeComputeranimation/main.go:34 +0x1eb

Move from Travis CI and Appveyor to GitHub Actions

The following files are historical artifacts:

In fact, the macOS build doesn't upload releases anymore.

Both of these should be moved to GitHub Actions. I have a test branch for macOS at:
https://github.com/github/smimesign/tree/macos-build

This is not a high priority for us, but if someone took the time to migrate and debug the CI files for GH Actions it would help us maintain this project!

Signer ignores PSS

On both windows and darwin, using the Signer of an Identity object as a private key of a TLS certificate doesn't work against a server that requires TLS v1.3.
In this case, a GO TLS server, for example, returns an "error decrypting message" error due to missing 0xbc at the end of the signature during the handshake. The reason for this is not using the padding scheme when signing the digest.

Sign aj

ox00000000219ab540356cBB839Cbe05303d7705Fa

macOS Big Sur: smimesign v0.1.0: Invalid Signatures

smimesign v0.1.0 when installed via Homebrew for macOS Big Sur creates invalid/corrupt signatures. Specifically, this happens when smimesign is installed as follows on macOS Big Sur:

brew install smimesign

This causes the following bottle to be used: https://homebrew.bintray.com/bottles/smimesign-0.1.0.big_sur.bottle.tar.gz

Interestingly enough, these invalid signatures (signatures created with the smimesign binary for macOS Big Sur) can be verified successfully by the same smimesign binary that created them, but are (correctly) reported as invalid by all other smimesign binaries as well as the GitHub UI/API.

To workaround this issue, when installing smimesign on macOS Big Sur, you can explicitly request a bottle that does
not suffer from this issue. Specifically, the smimesign-0.1.0.catalina.bottle.tar.gz bottle (compiled for macOS
Catalina) does not suffer from the issue and works on macOS BigSur:

brew install https://homebrew.bintray.com/bottles/smimesign-0.1.0.catalina.bottle.tar.gz

If this workaround is not performed, corrupt git commit signatures will be produced. Any attempt to verify these
commits using a version of smimesign that does not suffer from the issue will result in the following failure:

[~/dev/test-repo]$ git log --show-signature -1
commit 982cca63826ab8e894fc48db2825dd7805d1f9ae (HEAD -> master, origin/master, origin/HEAD)
failed to verify signature: crypto/rsa: verification error
Merge: 59b2361 26ce50c
Author: Redacted User <[email protected]>
Date:   Fri Sep 18 19:07:50 2020 -0400

    #1: Test Issue
[~/dev/test-repo]$ git verify-commit HEAD
failed to verify signature: crypto/rsa: verification error

Show smartcard token's labels and certs' key usage

Please consider exposing the label such as "Certificate For Digital Signature" and the key usage ("Digital Signature" and "Non Repudiation"). My PIV token has multiple certificates on it, one of which for the purpose of making signatures. One certificate has the usage of "Key Encipherment" and is inappropriate to use for any signing operations. I cannot currently distinguish between my certificates using the output of smimesign --list-keys.

It may also make sense to filter out any keys that do not have the "Digital Signature" key usage. (This isn't enough alone, 3 of my 4 keys have this usage.) This setting could be optional.

  1. Add a Usages: section to the --list-keys output. This information is available in the .KeyUsage .ExtKeyUsage properties of the ident.Certificate().

  2. Add the "label" of each certificate on the token to the output. This information is not available in the certificate itself, it will need to be added to the platform specific certstore code. On macOS it is available in the labl attribute of the identity (test with the command line comand:security export-smartcard -t identities).

As a workaround, I'm currently using pkcs11-tool to list the certificates with labels, then matching it's certificate serial to the output of smimesign --list-keys:

$ pkcs11-tool --list-objects --type cert
Using slot 0 with a present token (0x0)
Certificate Object; type = X.509 cert
  label:      Certificate for PIV Authentication
  subject:    [REDACTED]
  ID:         01
Certificate Object; type = X.509 cert
  label:      Certificate for Digital Signature
  subject:    [REDACTED]
  ID:         02
Certificate Object; type = X.509 cert
  label:      Certificate for Key Management
  subject:    [REDACTED]
  ID:         03
Certificate Object; type = X.509 cert
  label:      Certificate for Card Authentication
  subject:    [REDACTED]
  ID:         04
# Pick a key's ID based on it's label. Then get it's serial:
$ pkcs11-tool --read-object --type cert --id 02 | openssl x509 -inform DER  -noout -serial
Using slot 0 with a present token (0x0)
serial=12345678
# Match the desired serial to an smimesign key ID:
$ smimesign --list-keys

Failing Travis unit tests using "go: master" configuration

Since commit 7e96b8b, Travis unit tests have been failing. The tests fail when there is an equality test between leaf certificates. I believe that this bug is not due to some bug in smimesign after some troubleshooting.

Expected Behavior

Unit tests should pass on all versions of golang

Current Behavior

Several unit tests fail when testing against the development branch of golang. This occurs when comparing two leaf certificates. After troubleshooting I found that the first handful of bytes match between the two certs (so I assume that they are the same cert). However, the length does not match, and the length does not match the results when testing against the other versions of golang. In all local tests, and in the golang 1.12 and 1.14 tests in Travis, both certs are 842 bytes in length. In the Travis unit tests using the devel branch of golang, the certs are 866 bytes in length for the cert parsed from signed data, and 875 bytes for the test cert used to generate the signed data.

There doesn't seem to be any issues in creating signed data, parsing the content or reading certs from signed data.

Possible Solution

Because both the cert used to sign (Unmodified since generation), and the cert recovered from the signed data both have different lengths, I believe this issue likely did not originate from a bug in this project. I cannot offer any possible solutions currently but will continue to troubleshoot this issue.

Steps to Reproduce

Link to latest failed Travis run

  1. Trigger a Travis test using the go: master configuration

Context (Environment)

This issue has not affected me in my use of smimesign on Windows using go version 1.14.6 (64 bit), and it does not seem to affect other platforms using the latest version of go either. Unit tests are run on OSX only and I have not had a chance to swap platforms.

Missing verfication output on Windows

On Linux (using gpgsm) i am used to seeing its output inside the output of git log --show-signature or git tag -v. With smimesign i do not get such output and can not tell a regular commit from a signed one ... did not try invalid signature.
git log --pretty="format:%h %G? %aN %s" gives me the expected output, so the verification itself is working.
Maybe related to #41 and the output of smimesign going to the wrong fd.

--list-keys lists items that I cannot find in Keychain Access

Hi everyone, allow me to ask for some help here.
I use Nexus' "Personal Desktop Client" as a middleware, it recognizes my smart card nicely if I put it in the reader.
Also, when smimesign --list-keys, the items I expect from the card are listed.
However, I cannot find them reflected in Keychain Access. Where are they (from)?
Background is: I want to make use of Acrobat's PDF signing but that does not work this way, it doesn't discover the identities…

Any help is much appreciated!

Trying to sign a file using a smartcard and not being asked for password or PIN

Hi,

smimesign looks promising. I was looking for a simple application for macOS to sign files in P7S format.

$ smimesign --list-keys
       ID: 7cfe93760af9e1714d5********31bbb96365
      S/N: *****
Algorithm: SHA256-RSA
 Validity: 2018-10-17 15:45:09 +0000 UTC - 2021-10-17 15:45:09 +0000 UTC
   Issuer: CN=certSIGN Qualified CA,O=CERTSIGN SA,C=RO
  Subject: SERIALNUMBER=****,CN=**** *******,O=********,C=RO
   Emails: ******@******.ro

It sees my certificate but when I sign, it hangs and nothing happens.

$ smimesign -s -u 7cfe93760af9e1714d5********31bbb96365 "file.pdf"

Linux install (WSL)

When I run the install command I get this output:

$ go get github.com/github/smimesign
# github.com/github/smimesign/vendor/github.com/mastahyeti/certstore
src/github.com/github/smimesign/vendor/github.com/mastahyeti/certstore/certstore.go:17: undefined: openStore
# github.com/github/smimesign/vendor/github.com/mastahyeti/cms
src/github.com/github/smimesign/vendor/github.com/mastahyeti/cms/verify.go:151: unknown x509.CertificateInvalidError field 'Detail' in struct literal

I have previously installed this on my Ubuntu:

$ sudo apt-get install golang
$ export GOPATH=~

How can I fix this?

Custom PKI on GitHub?

Hi, perhaps a bit off-topic but I was wondering since the README mentions a private PKI for S/MIME commit signing on git, is this supported on GitHub?

Provide an Official Chocolatey Package

I notice that you provide a scoop installer package but can I suggest that you also provide an official Chocolatey package too?

There is already a unofficial package available at https://chocolatey.org/packages/smimesign however, as the developer you can claim ownership of the package from the current maintainer and provide official releases as part of your release cycle.

Caching of smartcard PIN

Dear smimesign team,

we use X.509 certificates to sign our commits.
Currently, we need to enter the certificate PIN for every single commit. Is it technically possible to cache the PIN such that we need to enter it e.g. only once a day?

Best regards
Per Ahrens

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.