This commit is contained in:
Ben Toews 2017-11-15 15:29:01 -07:00
Родитель 1e2be670b3
Коммит 30bf0d4124
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E9C423BE17EFEE70
14 изменённых файлов: 50 добавлений и 202 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -1 +1 @@
bin
test_data

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

@ -1,9 +0,0 @@
default: all
all: bin/certstore
bin:
mkdir -p bin
bin/certstore: certstore.go certstore_darwin.go main.go bin
GOOS=darwin go build -o bin/certstore .

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

@ -1,9 +0,0 @@
* [x] Windows CNG — RSA PKCS1 Signer
* [ ] Windows CNG — RSA PSS Signer
* [x] Windows CNG — ECDSA Signer
* [x] Windows CryptoAPI — RSA PKCS1 Signer
* [ ] Windows CryptoAPI — RSA PSS Signer
* [x] Windows CryptoAPI — ECDSA Signer
* [ ] Darwin — RSA PKCS1 Signer
* [ ] Darwin — RSA PSS Signer
* [ ] Darwin — ECDSA Signer

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

@ -45,7 +45,10 @@ func (s macStore) Identities() ([]Identity, error) {
}
defer C.CFRelease(C.CFTypeRef(absResult))
// don't need to release aryResult since the abstract result is released above.
aryResult := C.CFArrayRef(absResult)
// identRefs aren't owned by us initially. newMacIdentity retains them.
n := C.CFArrayGetCount(aryResult)
identRefs := make([]C.CFTypeRef, n)
C.CFArrayGetValues(aryResult, C.CFRange{0, n}, (*unsafe.Pointer)(&identRefs[0]))
@ -60,7 +63,30 @@ func (s macStore) Identities() ([]Identity, error) {
// Import implements the Store interface.
func (s macStore) Import(data []byte, password string) error {
return errors.New("not implemente4d")
cdata, err := bytesToCFData(data)
if err != nil {
return err
}
defer C.CFRelease(C.CFTypeRef(cdata))
cpass := stringToCFString(password)
defer C.CFRelease(C.CFTypeRef(cpass))
cops := mapToCFDictionary(map[C.CFTypeRef]C.CFTypeRef{
C.CFTypeRef(C.kSecImportExportPassphrase): C.CFTypeRef(cpass),
})
if cops == nil {
return errors.New("error creating CFDictionary")
}
defer C.CFRelease(C.CFTypeRef(cops))
var cret C.CFArrayRef
if err := osStatusError(C.SecPKCS12Import(cdata, cops, &cret)); err != nil {
return err
}
defer C.CFRelease(C.CFTypeRef(cret))
return nil
}
// Close implements the Store interface.
@ -180,6 +206,7 @@ func (i *macIdentity) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts
if err != nil {
return nil, err
}
defer C.CFRelease(C.CFTypeRef(cdigest))
algo, err := i.getAlgo(hash)
if err != nil {
@ -191,6 +218,8 @@ func (i *macIdentity) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts
csig := C.SecKeyCreateSignature(kref, algo, cdigest, &cerr)
if err := cfErrorError(cerr); err != nil {
defer C.CFRelease(C.CFTypeRef(cerr))
return nil, err
}
@ -224,7 +253,7 @@ func (i *macIdentity) getAlgo(hash crypto.Hash) (algo C.SecKeyAlgorithm, err err
case crypto.SHA512:
algo = C.kSecKeyAlgorithmECDSASignatureDigestX962SHA512
default:
err = errors.New("unsupported hash algorithm")
err = ErrUnsupportedHash
}
case *rsa.PublicKey:
switch hash {
@ -237,7 +266,7 @@ func (i *macIdentity) getAlgo(hash crypto.Hash) (algo C.SecKeyAlgorithm, err err
case crypto.SHA512:
algo = C.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
default:
err = errors.New("unsupported hash algorithm")
err = ErrUnsupportedHash
}
default:
err = errors.New("unsupported key type")

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

@ -333,8 +333,6 @@ func (wpk *winPrivateKey) cngSignHash(hash crypto.Hash, digest []byte) ([]byte,
padPtr = unsafe.Pointer(&padInfo)
switch hash {
case crypto.MD5:
padInfo.pszAlgId = BCRYPT_MD5_ALGORITHM
case crypto.SHA1:
padInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM
case crypto.SHA256:

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

@ -1,119 +0,0 @@
package main
import (
"bytes"
"crypto"
"crypto/rand"
"crypto/sha256"
"fmt"
"io"
"os"
"github.com/pkg/errors"
)
func main() {
fmt.Println("foo")
// create()
check()
delete()
}
func check() {
store, err := Open()
if err != nil {
fmt.Println(err)
return
}
defer store.Close()
idents, err := store.Identities()
if err != nil {
fmt.Println(err)
return
}
hash := crypto.SHA256
digest := sha256.Sum256([]byte("hi"))
for _, ident := range idents {
defer ident.Close()
if signer, err := ident.Signer(); err != nil {
fmt.Println(err)
continue
} else {
if _, err := signer.Sign(rand.Reader, digest[:], hash); err != nil {
fmt.Println(err)
continue
}
}
}
fmt.Println("Checked")
}
func create() {
f, err := os.Open("./test_data/rsa.pfx")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
buf := new(bytes.Buffer)
if _, err := io.Copy(buf, f); err != nil {
fmt.Println(err)
return
}
store, err := Open()
if err != nil {
fmt.Println(err)
return
}
defer store.Close()
if err := store.Import(buf.Bytes(), "asdf"); err != nil {
fmt.Println(err)
return
}
fmt.Println("Created")
}
func delete() {
store, err := Open()
if err != nil {
fmt.Println(err)
return
}
defer store.Close()
idents, err := store.Identities()
if err != nil {
fmt.Println(err)
return
}
for _, ident := range idents {
defer ident.Close()
crt, err := ident.Certificate()
if err != nil {
fmt.Println(err)
continue
}
if crt.Subject.CommonName != "certstore-test" {
continue
}
if err := ident.Delete(); err != nil {
fmt.Println(errors.Wrap(err, "failed to destroy identity"))
continue
}
fmt.Println("Deleted")
}
}

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

@ -1,5 +1,11 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/.."
mkdir -p test_data
cd test_data
# generate RSA cert/key/pfx
openssl req -new -days 365 -nodes -x509 -newkey rsa:2048 -sha256 -subj "/CN=certstore-test" -keyout rsa.key -out rsa.crt
openssl pkcs12 -export -out rsa.pfx -inkey rsa.key -in rsa.crt -passout pass:asdf

11
script/test Executable file
Просмотреть файл

@ -0,0 +1,11 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/.."
if [ ! -d test_data ]; then
script/setup
fi
go test

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

@ -1,9 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBITCByAIJAM3H1SutDsfYMAoGCCqGSM49BAMCMBkxFzAVBgNVBAMMDmNlcnRz
dG9yZS10ZXN0MB4XDTE3MTExNDE3MjIyNVoXDTE4MTExNDE3MjIyNVowGTEXMBUG
A1UEAwwOY2VydHN0b3JlLXRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQn
Lf1KU4xHlkoJjX3s22eub62MgWgDbNXDK4Wgim8zFMaeXm6zT72xivzCg6yXff+y
7uoyRog+7/JEBvR7qsSsMAoGCCqGSM49BAMCA0gAMEUCIA2Z64Ymic8UdGmmr+yp
VW0N48RBPWKjFbX929J5GmG+AiEAssFUSCZklw4nHO6jRIMHz6+RSELZ3slV3zqF
3CQf/Bs=
-----END CERTIFICATE-----

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

@ -1,5 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgnRYlR9a+lUsQrU1G
qidQMfTz/qw0nwDjtdisXvvEhS2hRANCAAQnLf1KU4xHlkoJjX3s22eub62MgWgD
bNXDK4Wgim8zFMaeXm6zT72xivzCg6yXff+y7uoyRog+7/JEBvR7qsSs
-----END PRIVATE KEY-----

Двоичные данные
test_data/ec.pfx

Двоичный файл не отображается.

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

@ -1,17 +0,0 @@
-----BEGIN CERTIFICATE-----
MIICrjCCAZYCCQDu0Khex89pejANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDDA5j
ZXJ0c3RvcmUtdGVzdDAeFw0xNzExMTQxNzIyMjVaFw0xODExMTQxNzIyMjVaMBkx
FzAVBgNVBAMMDmNlcnRzdG9yZS10ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAxp8qaCRXz7zWtFQsiIaKn8pP7PqUlXUYIlpqtcQOSHCZ8DPRLbPj
9yf4qO8TBsBmO5ZZjv+9T0IpsqCxSMNRwalUeEUjRNwOn2UALgfmcs13p5MK1gJY
/4Rv6+i4901sCb6Akv/gvHAfkrKYV7hWbiA8ZE1VqxN6MLTYoTpQU1H/YDNAAUVY
C4Wo2/2SF8Wt+4rBhaUMmB3hjXdQeeunh7fuS11cixN1V0hiUinTnQqQVcaxEwmS
7RibMy2Cbmp4gFBl0IWfvOEcwUbFQAW/eBKeSh1qPzETgmD7lYIjheuDVmWOHZdx
bcOa0ab8psE85oUzVdWajVFeYkf87G3QwwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
AQCX6Y7W/ABxxxSIFuAXRkluj+kup0eGgnBYqnsfUAgIx2Z65vP9zzo0x06q9X7J
p4UVzJOz9DbfmU7pHi1k+Nln+IVT4+kZZtg0OWYOelrUR1Ag8V2XJVKBPEWGN0j9
b0CP1SDwJKQcQw2QHxoYJvR8DnTgo07nepoNwidGt2Mlc8IJKVbJK6AGKkNh/lym
jNMGyw56wrOtMLEk3sQfVpR2R3h8XYlmIZaSQ3eY+cDSmsPM91ls7STiFsBW0nco
pENzLVsKu5N3w0Z4K01Ojivkj5uWmyu5UtPHo26NBOUrv3/29yCxusUdxreH/D2P
Y1KTvNKNjg+6GkWHCmNhimjT
-----END CERTIFICATE-----

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

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDGnypoJFfPvNa0
VCyIhoqfyk/s+pSVdRgiWmq1xA5IcJnwM9Ets+P3J/io7xMGwGY7llmO/71PQimy
oLFIw1HBqVR4RSNE3A6fZQAuB+ZyzXenkwrWAlj/hG/r6Lj3TWwJvoCS/+C8cB+S
sphXuFZuIDxkTVWrE3owtNihOlBTUf9gM0ABRVgLhajb/ZIXxa37isGFpQyYHeGN
d1B566eHt+5LXVyLE3VXSGJSKdOdCpBVxrETCZLtGJszLYJuaniAUGXQhZ+84RzB
RsVABb94Ep5KHWo/MROCYPuVgiOF64NWZY4dl3Ftw5rRpvymwTzmhTNV1ZqNUV5i
R/zsbdDDAgMBAAECggEAF13WQVY1Nm1C3QgiDRW27UGB0aFRJZwW8MOuVh/whjkp
Awc1jqjhIsyDBmzJ0juES3JOqvIPNWnVOfyJnsPLtHrVQyjvE0TIO5xIPyISzGK7
tu0nkzHHgpf0Cs7gI8fp8+ODgMe1irWuITX9kiRPlrkYIbyvXWb3Mw+zhJQ1qvd/
g0MRnMLSSOjwPHmtcE+fVtZXhl3ucDzEallpJSEcyni68Y9cOq2vPCZUvNA2PNL9
JHuv++63z0ICSr6OAZKeY5cr9kgT2NziIiNGqkI1XxK8nKmNpIxezquMOM55vp0Y
6/0uGmHKNoCaw7oUmU1fyphpOLa+Pv9nWPlb8X28EQKBgQDhj4JGn1UEUNf3zb5C
/sWBx9RIzSYnU+bdnUU858xZ3oaTh+vGxPk5iRIdxUA274pE8P3x4x4rF+ZKADkO
Kk0z5X0b8m7oYF9Jts+WjlGB05ZrIHeYVMN/eZDh3ZGV/5leFXNSTgL+qg/HCfuW
sRy+BjNQZW8G9TGtnAVmKk5AtQKBgQDhbP6kQQ2C9CWEyA7Eo46xu1O2QbYNovAj
HNO6gC8LZngqAsk/6HAZ4H0HSPJGx1v4iPLVYTyhV6BedJqDiRc56AFS2cVc8yk0
Oipjkd2w8wqWZSSl0WReecKGFVn9QH+3YUh+XY/psK7N/dRtWesd2zMlYBlQIhA0
x5CWQ+TOlwKBgHzfcCYc63o6L3Y25xA776gLsxCi0m6PWo5yFPTE9zMBqMtgQj2G
qtsZcXgdzZEcSBYmvM//BqKg1pM9UFjxPlBuyjaAnrnzMI2ksYQOQj13oByqmssw
khKugHEqswCxwnx9r5xvJ+VIzPdKJYilgN4KnLnzjeXyNJCCgdKvtSbJAoGAWs+O
sVqnd8akyp3RHTQKStz89yH3lfy6olp9jNcQnJYV+E6RBha7+iCuHV4sg4jSKwf4
Uy9Nvm1PZF2y1SRH4ALvbZHe6Pfn9GsuIlhjp2HxNO7f2ZDFzy1byKoXS2dNS/F7
w7QrQmfzs3X6umaLycZBD2BsMhTW1HxEadRF+1cCgYAI1yolkEV5sKAIozhdA0jJ
ouTvPFGRa16PMIV25zVq9RhEKbAxO+llwUASiLaSCSm/xGOvxJ0Szrs2uFAicVRX
x0V7aAM6Kg7gCLra3ieMTYaXmgA4RqbBSO6Uhxy+ZyOWFhJwmc+bznpf1f1TszIK
jrdJHEqNCVMM1J2sgNqRIA==
-----END PRIVATE KEY-----

Двоичные данные
test_data/rsa.pfx

Двоичный файл не отображается.