forked from alvinbaena/passkit
-
Notifications
You must be signed in to change notification settings - Fork 1
/
signing.go
117 lines (95 loc) · 2.68 KB
/
signing.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package passkit
import (
"crypto/x509"
"errors"
"fmt"
"os"
"go.mozilla.org/pkcs7"
"golang.org/x/crypto/pkcs12"
)
const (
manifestJsonFileName = "manifest.json"
passJsonFileName = "pass.json"
personalizationJsonFileName = "personalization.json"
signatureFileName = "signature"
)
type Signer interface {
CreateSignedAndZippedPassArchive(p *Pass, t PassTemplate, i *SigningInformation) ([]byte, error)
CreateSignedAndZippedPersonalizedPassArchive(p *Pass, pz *Personalization, t PassTemplate, i *SigningInformation) ([]byte, error)
SignManifestFile(manifestJson []byte, i *SigningInformation) ([]byte, error)
}
type SigningInformation struct {
signingCert *x509.Certificate
appleWWDRCACert *x509.Certificate
privateKey interface{}
}
func LoadSigningInformationFromFiles(pkcs12KeyStoreFilePath, keyStorePassword, appleWWDRCAFilePath string) (*SigningInformation, error) {
p12, err := os.ReadFile(pkcs12KeyStoreFilePath)
if err != nil {
return nil, err
}
ca, err := os.ReadFile(appleWWDRCAFilePath)
if err != nil {
return nil, err
}
return LoadSigningInformationFromBytes(p12, keyStorePassword, ca)
}
func LoadSigningInformationFromBytes(pkcs12KeyStoreFile []byte, keyStorePassword string, appleWWDRCAFile []byte) (*SigningInformation, error) {
info := &SigningInformation{}
pk, cer, err := pkcs12.Decode(pkcs12KeyStoreFile, keyStorePassword)
if err != nil {
return nil, err
}
if err := verify(cer); err != nil {
return nil, err
}
wwdrca, err := x509.ParseCertificate(appleWWDRCAFile)
if err != nil {
return nil, err
}
if err := verify(wwdrca); err != nil {
return nil, err
}
info.privateKey = pk
info.signingCert = cer
info.appleWWDRCACert = wwdrca
return info, nil
}
// verify checks if a certificate has expired
func verify(cert *x509.Certificate) error {
_, err := cert.Verify(x509.VerifyOptions{Roots: x509.NewCertPool()})
if err == nil {
return nil
}
switch e := err.(type) {
case x509.CertificateInvalidError:
switch e.Reason {
case x509.Expired:
return errors.New("certificate has expired or is not yet valid")
default:
return err
}
case x509.UnknownAuthorityError:
// Apple cert isn't in the cert pool
// ignoring this error
return nil
default:
return err
}
}
func signManifestFile(manifestJson []byte, i *SigningInformation) ([]byte, error) {
if manifestJson == nil {
return nil, fmt.Errorf("manifestJson has to be present")
}
s, err := pkcs7.NewSignedData(manifestJson)
if err != nil {
return nil, err
}
s.AddCertificate(i.appleWWDRCACert)
err = s.AddSigner(i.signingCert, i.privateKey, pkcs7.SignerInfoConfig{})
if err != nil {
return nil, err
}
s.Detach()
return s.Finish()
}