mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-12-26 15:25:39 +08:00
89 lines
3.0 KiB
Go
89 lines
3.0 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
"crypto/rsa"
|
||
|
"crypto/sha1"
|
||
|
"crypto/x509"
|
||
|
"crypto/x509/pkix"
|
||
|
"encoding/asn1"
|
||
|
"encoding/pem"
|
||
|
"math/big"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/sagernet/sing/common/rw"
|
||
|
|
||
|
"github.com/stretchr/testify/require"
|
||
|
)
|
||
|
|
||
|
func createSelfSignedCertificate(t *testing.T, domain string) (caPem, certPem, keyPem string) {
|
||
|
const userAndHostname = "sekai@nekohasekai.local"
|
||
|
tempDir, err := os.MkdirTemp("", "sing-box-test")
|
||
|
require.NoError(t, err)
|
||
|
t.Cleanup(func() {
|
||
|
os.RemoveAll(tempDir)
|
||
|
})
|
||
|
caKey, err := rsa.GenerateKey(rand.Reader, 3072)
|
||
|
require.NoError(t, err)
|
||
|
spkiASN1, err := x509.MarshalPKIXPublicKey(caKey.Public())
|
||
|
var spki struct {
|
||
|
Algorithm pkix.AlgorithmIdentifier
|
||
|
SubjectPublicKey asn1.BitString
|
||
|
}
|
||
|
_, err = asn1.Unmarshal(spkiASN1, &spki)
|
||
|
require.NoError(t, err)
|
||
|
skid := sha1.Sum(spki.SubjectPublicKey.Bytes)
|
||
|
caTpl := &x509.Certificate{
|
||
|
SerialNumber: randomSerialNumber(t),
|
||
|
Subject: pkix.Name{
|
||
|
Organization: []string{"sing-box test CA"},
|
||
|
OrganizationalUnit: []string{userAndHostname},
|
||
|
CommonName: "sing-box " + userAndHostname,
|
||
|
},
|
||
|
SubjectKeyId: skid[:],
|
||
|
NotAfter: time.Now().AddDate(10, 0, 0),
|
||
|
NotBefore: time.Now(),
|
||
|
KeyUsage: x509.KeyUsageCertSign,
|
||
|
BasicConstraintsValid: true,
|
||
|
IsCA: true,
|
||
|
MaxPathLenZero: true,
|
||
|
}
|
||
|
caCert, err := x509.CreateCertificate(rand.Reader, caTpl, caTpl, caKey.Public(), caKey)
|
||
|
require.NoError(t, err)
|
||
|
err = rw.WriteFile(filepath.Join(tempDir, "ca.pem"), pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caCert}))
|
||
|
require.NoError(t, err)
|
||
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||
|
domainTpl := &x509.Certificate{
|
||
|
SerialNumber: randomSerialNumber(t),
|
||
|
Subject: pkix.Name{
|
||
|
Organization: []string{"sing-box test certificate"},
|
||
|
OrganizationalUnit: []string{"sing-box " + userAndHostname},
|
||
|
},
|
||
|
NotBefore: time.Now(), NotAfter: time.Now().AddDate(0, 0, 30),
|
||
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||
|
}
|
||
|
domainTpl.DNSNames = append(domainTpl.DNSNames, domain)
|
||
|
cert, err := x509.CreateCertificate(rand.Reader, domainTpl, caTpl, key.Public(), caKey)
|
||
|
require.NoError(t, err)
|
||
|
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert})
|
||
|
privDER, err := x509.MarshalPKCS8PrivateKey(key)
|
||
|
require.NoError(t, err)
|
||
|
privPEM := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privDER})
|
||
|
err = rw.WriteFile(filepath.Join(tempDir, domain+".pem"), certPEM)
|
||
|
require.NoError(t, err)
|
||
|
err = rw.WriteFile(filepath.Join(tempDir, domain+".key.pem"), privPEM)
|
||
|
require.NoError(t, err)
|
||
|
return filepath.Join(tempDir, "ca.pem"), filepath.Join(tempDir, domain+".pem"), filepath.Join(tempDir, domain+".key.pem")
|
||
|
}
|
||
|
|
||
|
func randomSerialNumber(t *testing.T) *big.Int {
|
||
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||
|
require.NoError(t, err)
|
||
|
return serialNumber
|
||
|
}
|