mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 18:11:28 +00:00
127 lines
3.7 KiB
Go
127 lines
3.7 KiB
Go
|
// Copyright 2022 Cloudflare, Inc. All rights reserved. Use of this source code
|
||
|
// is governed by a BSD-style license that can be found in the LICENSE file.
|
||
|
|
||
|
//go:build ignore
|
||
|
|
||
|
// Generate a delegated credential with the given signature scheme, signed with
|
||
|
// the given x.509 key pair. Outputs to 'dc.cred' and 'dckey.pem' and will
|
||
|
// overwrite existing files.
|
||
|
|
||
|
// Example usage:
|
||
|
// generate_delegated_credential -cert-path cert.pem -key-path key.pem -signature-scheme Ed25519 -duration 24h
|
||
|
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"crypto"
|
||
|
"crypto/ecdsa"
|
||
|
"crypto/ed25519"
|
||
|
"crypto/rsa"
|
||
|
"crypto/tls"
|
||
|
"crypto/x509"
|
||
|
"encoding/pem"
|
||
|
"errors"
|
||
|
"flag"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"time"
|
||
|
|
||
|
circlSign "github.com/cloudflare/circl/sign"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
validFor = flag.Duration("duration", 5*24*time.Hour, "Duration that credential is valid for")
|
||
|
signatureScheme = flag.String("signature-scheme", "", "The signature scheme used by the DC")
|
||
|
certPath = flag.String("cert-path", "./cert.pem", "Path to signing cert")
|
||
|
keyPath = flag.String("key-path", "./key.pem", "Path to signing key")
|
||
|
isClient = flag.Bool("client-dc", false, "Create a client Delegated Credential")
|
||
|
outPath = flag.String("out-path", "./", "Path to output directory")
|
||
|
)
|
||
|
|
||
|
var SigStringMap = map[string]tls.SignatureScheme{
|
||
|
// ECDSA algorithms. Only constrained to a specific curve in TLS 1.3.
|
||
|
"ECDSAWithP256AndSHA256": tls.ECDSAWithP256AndSHA256,
|
||
|
"ECDSAWithP384AndSHA384": tls.ECDSAWithP384AndSHA384,
|
||
|
"ECDSAWithP521AndSHA512": tls.ECDSAWithP521AndSHA512,
|
||
|
|
||
|
// EdDSA algorithms.
|
||
|
"Ed25519": tls.Ed25519,
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
flag.Parse()
|
||
|
sa := SigStringMap[*signatureScheme]
|
||
|
|
||
|
cert, err := tls.LoadX509KeyPair(*certPath, *keyPath)
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to load certificate and key: %v", err)
|
||
|
}
|
||
|
cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to parse leaf certificate: %v", err)
|
||
|
}
|
||
|
|
||
|
validTime := time.Since(cert.Leaf.NotBefore) + *validFor
|
||
|
dc, priv, err := tls.NewDelegatedCredential(&cert, sa, validTime, *isClient)
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to create a DC: %v\n", err)
|
||
|
}
|
||
|
dcBytes, err := dc.Marshal()
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to marshal DC: %v\n", err)
|
||
|
}
|
||
|
|
||
|
DCOut, err := os.Create(filepath.Join(*outPath, "dc.cred"))
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to open dc.cred for writing: %v", err)
|
||
|
}
|
||
|
|
||
|
DCOut.Write(dcBytes)
|
||
|
if err := DCOut.Close(); err != nil {
|
||
|
log.Fatalf("Error closing dc.cred: %v", err)
|
||
|
}
|
||
|
log.Print("wrote dc.cred\n")
|
||
|
|
||
|
derBytes, err := x509.MarshalPKCS8PrivateKey(priv)
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to marshal DC private key: %v\n", err)
|
||
|
}
|
||
|
|
||
|
DCKeyOut, err := os.Create(filepath.Join(*outPath, "dckey.pem"))
|
||
|
if err != nil {
|
||
|
log.Fatalf("Failed to open dckey.pem for writing: %v", err)
|
||
|
}
|
||
|
|
||
|
if err := pem.Encode(DCKeyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: derBytes}); err != nil {
|
||
|
log.Fatalf("Failed to write data to dckey.pem: %v\n", err)
|
||
|
}
|
||
|
if err := DCKeyOut.Close(); err != nil {
|
||
|
log.Fatalf("Error closing dckey.pem: %v\n", err)
|
||
|
}
|
||
|
log.Print("wrote dckey.pem\n")
|
||
|
|
||
|
fmt.Println("Success")
|
||
|
}
|
||
|
|
||
|
// Copied from tls.go, because it's private.
|
||
|
func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
|
||
|
if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
|
||
|
return key, nil
|
||
|
}
|
||
|
if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
|
||
|
switch key := key.(type) {
|
||
|
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey, circlSign.PrivateKey:
|
||
|
return key, nil
|
||
|
default:
|
||
|
return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping")
|
||
|
}
|
||
|
}
|
||
|
if key, err := x509.ParseECPrivateKey(der); err == nil {
|
||
|
return key, nil
|
||
|
}
|
||
|
|
||
|
return nil, errors.New("tls: failed to parse private key")
|
||
|
}
|