Skip to content

Commit e650daf

Browse files
authored
Merge pull request #84 from github/monorepo
Consolidate `smimesign`-specific dependencies into a monorepo.
2 parents ed54d09 + 1a37be2 commit e650daf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+8196
-24
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ Smimesign is an S/MIME signing utility for macOS and Windows that is compatible
44

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

7+
This package also contains reusable libraries in nested packages:
8+
9+
- [`github.com/smimesign/certstore`](./certstore)
10+
- [`github.com/smimesign/fakeca`](./fakeca)
11+
- [`github.com/smimesign/ietf-cms`](./ietf-cms)
12+
713
## Contributing
814

915
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](CONTRIBUTING.md) for more information on how to get involved.

certstore/LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Ben Toews.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

certstore/README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# certstore [![PkgGoDev](https://pkg.go.dev/badge/github.com/github/smimesign/certstore?tab=doc)](https://pkg.go.dev/github.com/github/smimesign/certstore?tab=doc)
2+
3+
Certstore is a Go library for accessing user identities stored in platform certificate stores. On Windows and macOS, certstore can enumerate user identities and sign messages with their private keys.
4+
5+
## Example
6+
7+
```go
8+
package main
9+
10+
import (
11+
"crypto"
12+
"encoding/hex"
13+
"errors"
14+
"fmt"
15+
16+
"crypto/rand"
17+
"crypto/sha256"
18+
19+
"github.com/github/smimesign/certstore"
20+
)
21+
22+
func main() {
23+
sig, err := signWithMyIdentity("Ben Toews", "hello, world!")
24+
if err != nil {
25+
panic(err)
26+
}
27+
28+
fmt.Println(hex.EncodeToString(sig))
29+
}
30+
31+
func signWithMyIdentity(cn, msg string) ([]byte, error) {
32+
// Open the certificate store for use. This must be Close()'ed once you're
33+
// finished with the store and any identities it contains.
34+
store, err := certstore.Open()
35+
if err != nil {
36+
return nil, err
37+
}
38+
defer store.Close()
39+
40+
// Get an Identity slice, containing every identity in the store. Each of
41+
// these must be Close()'ed when you're done with them.
42+
idents, err := store.Identities()
43+
if err != nil {
44+
return nil, err
45+
}
46+
47+
// Iterate through the identities, looking for the one we want.
48+
var me certstore.Identity
49+
for _, ident := range idents {
50+
defer ident.Close()
51+
52+
crt, errr := ident.Certificate()
53+
if errr != nil {
54+
return nil, errr
55+
}
56+
57+
if crt.Subject.CommonName == "Ben Toews" {
58+
me = ident
59+
}
60+
}
61+
62+
if me == nil {
63+
return nil, errors.New("Couldn't find my identity")
64+
}
65+
66+
// Get a crypto.Signer for the identity.
67+
signer, err := me.Signer()
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
// Digest and sign our message.
73+
digest := sha256.Sum256([]byte(msg))
74+
signature, err := signer.Sign(rand.Reader, digest[:], crypto.SHA256)
75+
if err != nil {
76+
return nil, err
77+
}
78+
79+
return signature, nil
80+
}
81+
82+
```

certstore/certstore.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package certstore
2+
3+
import (
4+
"crypto"
5+
"crypto/x509"
6+
"errors"
7+
)
8+
9+
var (
10+
// ErrUnsupportedHash is returned by Signer.Sign() when the provided hash
11+
// algorithm isn't supported.
12+
ErrUnsupportedHash = errors.New("unsupported hash algorithm")
13+
)
14+
15+
// Open opens the system's certificate store.
16+
func Open() (Store, error) {
17+
return openStore()
18+
}
19+
20+
// Store represents the system's certificate store.
21+
type Store interface {
22+
// Identities gets a list of identities from the store.
23+
Identities() ([]Identity, error)
24+
25+
// Import imports a PKCS#12 (PFX) blob containing a certificate and private
26+
// key.
27+
Import(data []byte, password string) error
28+
29+
// Close closes the store.
30+
Close()
31+
}
32+
33+
// Identity is a X.509 certificate and its corresponding private key.
34+
type Identity interface {
35+
// Certificate gets the identity's certificate.
36+
Certificate() (*x509.Certificate, error)
37+
38+
// CertificateChain attempts to get the identity's full certificate chain.
39+
CertificateChain() ([]*x509.Certificate, error)
40+
41+
// Signer gets a crypto.Signer that uses the identity's private key.
42+
Signer() (crypto.Signer, error)
43+
44+
// Delete deletes this identity from the system.
45+
Delete() error
46+
47+
// Close any manually managed memory held by the Identity.
48+
Close()
49+
}

0 commit comments

Comments
 (0)