Skip to content

Commit 0a4f811

Browse files
committed
sm2
1 parent cb1afb3 commit 0a4f811

File tree

7 files changed

+494
-14
lines changed

7 files changed

+494
-14
lines changed

common/protocol/tls/cert/cert.go

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@ import (
77
"crypto/rand"
88
"crypto/rsa"
99
"crypto/x509"
10+
"crypto/x509/pkix"
1011
"encoding/asn1"
1112
"encoding/pem"
1213
"math/big"
1314
"time"
1415

1516
"github.com/xtls/xray-core/common"
17+
"github.com/xtls/xray-core/common/crypto/gost"
18+
sm2crypto "github.com/xtls/xray-core/common/crypto/sm2"
1619
"github.com/xtls/xray-core/common/errors"
20+
"github.com/tjfoc/gmsm/sm2"
21+
sm2x509 "github.com/tjfoc/gmsm/x509"
1722
)
1823

1924
type Certificate struct {
@@ -45,54 +50,292 @@ func (c *Certificate) ToPEM() ([]byte, []byte) {
4550

4651
type Option func(*x509.Certificate)
4752

53+
// SM2-specific option types
54+
type SM2Option func(*sm2x509.Certificate)
55+
4856
func Authority(isCA bool) Option {
4957
return func(cert *x509.Certificate) {
5058
cert.IsCA = isCA
5159
}
5260
}
5361

62+
func SM2Authority(isCA bool) SM2Option {
63+
return func(cert *sm2x509.Certificate) {
64+
cert.IsCA = isCA
65+
}
66+
}
67+
5468
func NotBefore(t time.Time) Option {
5569
return func(c *x509.Certificate) {
5670
c.NotBefore = t
5771
}
5872
}
5973

74+
func SM2NotBefore(t time.Time) SM2Option {
75+
return func(c *sm2x509.Certificate) {
76+
c.NotBefore = t
77+
}
78+
}
79+
6080
func NotAfter(t time.Time) Option {
6181
return func(c *x509.Certificate) {
6282
c.NotAfter = t
6383
}
6484
}
6585

86+
func SM2NotAfter(t time.Time) SM2Option {
87+
return func(c *sm2x509.Certificate) {
88+
c.NotAfter = t
89+
}
90+
}
91+
6692
func DNSNames(names ...string) Option {
6793
return func(c *x509.Certificate) {
6894
c.DNSNames = names
6995
}
7096
}
7197

98+
func SM2DNSNames(names ...string) SM2Option {
99+
return func(c *sm2x509.Certificate) {
100+
c.DNSNames = names
101+
}
102+
}
103+
72104
func CommonName(name string) Option {
73105
return func(c *x509.Certificate) {
74106
c.Subject.CommonName = name
75107
}
76108
}
77109

110+
func SM2CommonName(name string) SM2Option {
111+
return func(c *sm2x509.Certificate) {
112+
c.Subject.CommonName = name
113+
}
114+
}
115+
78116
func KeyUsage(usage x509.KeyUsage) Option {
79117
return func(c *x509.Certificate) {
80118
c.KeyUsage = usage
81119
}
82120
}
83121

122+
func SM2KeyUsage(usage sm2x509.KeyUsage) SM2Option {
123+
return func(c *sm2x509.Certificate) {
124+
c.KeyUsage = usage
125+
}
126+
}
127+
84128
func Organization(org string) Option {
85129
return func(c *x509.Certificate) {
86130
c.Subject.Organization = []string{org}
87131
}
88132
}
89133

134+
func SM2Organization(org string) SM2Option {
135+
return func(c *sm2x509.Certificate) {
136+
c.Subject.Organization = []string{org}
137+
}
138+
}
139+
90140
func MustGenerate(parent *Certificate, opts ...Option) *Certificate {
91141
cert, err := Generate(parent, opts...)
92142
common.Must(err)
93143
return cert
94144
}
95145

146+
// MustGenerateGOST2012_256 generates a certificate using GOST 2012-256 algorithm
147+
func MustGenerateGOST2012_256(parent *Certificate, opts ...SM2Option) *Certificate {
148+
cert, err := GenerateGOST2012_256(parent, opts...)
149+
common.Must(err)
150+
return cert
151+
}
152+
153+
// MustGenerateGOST2012_512 generates a certificate using GOST 2012-512 algorithm
154+
func MustGenerateGOST2012_512(parent *Certificate, opts ...SM2Option) *Certificate {
155+
cert, err := GenerateGOST2012_512(parent, opts...)
156+
common.Must(err)
157+
return cert
158+
}
159+
160+
// MustGenerateSM2 generates a certificate using SM2 algorithm
161+
func MustGenerateSM2(parent *Certificate, opts ...SM2Option) *Certificate {
162+
cert, err := GenerateSM2(parent, opts...)
163+
common.Must(err)
164+
return cert
165+
}
166+
167+
// GenerateGOST2012_256 generates a certificate using GOST 2012-256 algorithm
168+
func GenerateGOST2012_256(parent *Certificate, opts ...SM2Option) (*Certificate, error) {
169+
var (
170+
err error
171+
)
172+
selfKey, err := gost.GenerateKeyPair(gost.GOST2012_256)
173+
if err != nil {
174+
return nil, errors.New("failed to generate GOST 2012-256 private key").Base(err)
175+
}
176+
177+
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
178+
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
179+
if err != nil {
180+
return nil, errors.New("failed to generate serial number").Base(err)
181+
}
182+
template := &sm2x509.Certificate{
183+
SerialNumber: serialNumber,
184+
Subject: pkix.Name{
185+
Organization: []string{"Xray GOST 2012-256 Certificate"},
186+
CommonName: "",
187+
},
188+
NotBefore: time.Now().Add(time.Hour * -1),
189+
NotAfter: time.Now().Add(time.Hour),
190+
KeyUsage: sm2x509.KeyUsageKeyEncipherment | sm2x509.KeyUsageDigitalSignature,
191+
ExtKeyUsage: []sm2x509.ExtKeyUsage{sm2x509.ExtKeyUsageServerAuth},
192+
BasicConstraintsValid: true,
193+
}
194+
parentCert := template
195+
if parent != nil {
196+
pCert, err := sm2x509.ParseCertificate(parent.Certificate)
197+
if err != nil {
198+
return nil, errors.New("failed to parse parent certificate").Base(err)
199+
}
200+
parentCert = pCert
201+
}
202+
if parentCert.NotAfter.Before(template.NotAfter) {
203+
template.NotAfter = parentCert.NotAfter
204+
}
205+
if parentCert.NotBefore.After(template.NotBefore) {
206+
template.NotBefore = parentCert.NotBefore
207+
}
208+
for _, opt := range opts {
209+
opt(template)
210+
}
211+
certDER, err := sm2x509.CreateCertificate(template, parentCert, &selfKey.PublicKey, selfKey)
212+
if err != nil {
213+
return nil, errors.New("failed to create GOST 2012-256 certificate").Base(err)
214+
}
215+
privateKey, err := sm2x509.MarshalSm2UnecryptedPrivateKey(selfKey)
216+
if err != nil {
217+
return nil, errors.New("Unable to marshal GOST 2012-256 private key").Base(err)
218+
}
219+
return &Certificate{
220+
Certificate: certDER,
221+
PrivateKey: privateKey,
222+
}, nil
223+
}
224+
225+
// GenerateGOST2012_512 generates a certificate using GOST 2012-512 algorithm
226+
func GenerateGOST2012_512(parent *Certificate, opts ...SM2Option) (*Certificate, error) {
227+
var (
228+
err error
229+
)
230+
selfKey, err := gost.GenerateKeyPair(gost.GOST2012_512)
231+
if err != nil {
232+
return nil, errors.New("failed to generate GOST 2012-512 private key").Base(err)
233+
}
234+
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
235+
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
236+
if err != nil {
237+
return nil, errors.New("failed to generate serial number").Base(err)
238+
}
239+
template := &sm2x509.Certificate{
240+
SerialNumber: serialNumber,
241+
Subject: pkix.Name{
242+
Organization: []string{"Xray GOST 2012-512 Certificate"},
243+
CommonName: "",
244+
},
245+
NotBefore: time.Now().Add(time.Hour * -1),
246+
NotAfter: time.Now().Add(time.Hour),
247+
KeyUsage: sm2x509.KeyUsageKeyEncipherment | sm2x509.KeyUsageDigitalSignature,
248+
ExtKeyUsage: []sm2x509.ExtKeyUsage{sm2x509.ExtKeyUsageServerAuth},
249+
BasicConstraintsValid: true,
250+
}
251+
parentCert := template
252+
if parent != nil {
253+
pCert, err := sm2x509.ParseCertificate(parent.Certificate)
254+
if err != nil {
255+
return nil, errors.New("failed to parse parent certificate").Base(err)
256+
}
257+
parentCert = pCert
258+
}
259+
if parentCert.NotAfter.Before(template.NotAfter) {
260+
template.NotAfter = parentCert.NotAfter
261+
}
262+
if parentCert.NotBefore.After(template.NotBefore) {
263+
template.NotBefore = parentCert.NotBefore
264+
}
265+
for _, opt := range opts {
266+
opt(template)
267+
}
268+
certDER, err := sm2x509.CreateCertificate(template, parentCert, &selfKey.PublicKey, selfKey)
269+
if err != nil {
270+
return nil, errors.New("failed to create GOST 2012-512 certificate").Base(err)
271+
}
272+
privateKey, err := sm2x509.MarshalSm2UnecryptedPrivateKey(selfKey)
273+
if err != nil {
274+
return nil, errors.New("Unable to marshal GOST 2012-512 private key").Base(err)
275+
}
276+
return &Certificate{
277+
Certificate: certDER,
278+
PrivateKey: privateKey,
279+
}, nil
280+
}
281+
282+
// GenerateSM2 generates a certificate using SM2 algorithm
283+
func GenerateSM2(parent *Certificate, opts ...SM2Option) (*Certificate, error) {
284+
var (
285+
err error
286+
)
287+
selfKey, err := sm2crypto.GenerateKeyPair()
288+
if err != nil {
289+
return nil, errors.New("failed to generate SM2 private key").Base(err)
290+
}
291+
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
292+
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
293+
if err != nil {
294+
return nil, errors.New("failed to generate serial number").Base(err)
295+
}
296+
template := &sm2x509.Certificate{
297+
SerialNumber: serialNumber,
298+
Subject: pkix.Name{
299+
Organization: []string{"Xray SM2 Certificate"},
300+
CommonName: "",
301+
},
302+
NotBefore: time.Now().Add(time.Hour * -1),
303+
NotAfter: time.Now().Add(time.Hour),
304+
KeyUsage: sm2x509.KeyUsageKeyEncipherment | sm2x509.KeyUsageDigitalSignature,
305+
ExtKeyUsage: []sm2x509.ExtKeyUsage{sm2x509.ExtKeyUsageServerAuth},
306+
BasicConstraintsValid: true,
307+
}
308+
parentCert := template
309+
if parent != nil {
310+
pCert, err := sm2x509.ParseCertificate(parent.Certificate)
311+
if err != nil {
312+
return nil, errors.New("failed to parse parent certificate").Base(err)
313+
}
314+
parentCert = pCert
315+
}
316+
if parentCert.NotAfter.Before(template.NotAfter) {
317+
template.NotAfter = parentCert.NotAfter
318+
}
319+
if parentCert.NotBefore.After(template.NotBefore) {
320+
template.NotBefore = parentCert.NotBefore
321+
}
322+
for _, opt := range opts {
323+
opt(template)
324+
}
325+
certDER, err := sm2x509.CreateCertificate(template, parentCert, &selfKey.PublicKey, selfKey)
326+
if err != nil {
327+
return nil, errors.New("failed to create SM2 certificate").Base(err)
328+
}
329+
privateKey, err := sm2x509.MarshalSm2UnecryptedPrivateKey(selfKey)
330+
if err != nil {
331+
return nil, errors.New("Unable to marshal SM2 private key").Base(err)
332+
}
333+
return &Certificate{
334+
Certificate: certDER,
335+
PrivateKey: privateKey,
336+
}, nil
337+
}
338+
96339
func publicKey(priv interface{}) interface{} {
97340
switch k := priv.(type) {
98341
case *rsa.PrivateKey:
@@ -101,6 +344,8 @@ func publicKey(priv interface{}) interface{} {
101344
return &k.PublicKey
102345
case ed25519.PrivateKey:
103346
return k.Public().(ed25519.PublicKey)
347+
case *sm2.PrivateKey:
348+
return &k.PublicKey
104349
default:
105350
return nil
106351
}

0 commit comments

Comments
 (0)