package pki import ( "crypto/ecdsa" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "fmt" "math" "math/big" "os" "os/exec" "path" "time" ) func ClientCertificatePath(serial uint64) string { return path.Join(PKIDir, fmt.Sprintf("%0[2]*[1]X", serial, int(math.Ceil(math.Log2(float64(serial))/8)*2)), "cert.pem") } func ClientPrivkeyPath(serial uint64) string { return path.Join(PKIDir, fmt.Sprintf("%0[2]*[1]X", serial, int(math.Ceil(math.Log2(float64(serial))/8)*2)), "privkey.pem") } func ClientP12Path(serial uint64) string { return path.Join(PKIDir, fmt.Sprintf("%0[2]*[1]X", serial, int(math.Ceil(math.Log2(float64(serial))/8)*2)), "team.p12") } func GenerateClient(serial uint64, notBefore time.Time, notAfter time.Time, parent_cert *x509.Certificate, parent_priv *ecdsa.PrivateKey) error { var certid big.Int certid.SetUint64(serial) client := &x509.Certificate{ SerialNumber: &certid, Subject: pkix.Name{ Organization: []string{"EPITA"}, OrganizationalUnit: []string{"SRS laboratory"}, Country: []string{"FR"}, Locality: []string{"Paris"}, CommonName: fmt.Sprintf("TEAM-%0[2]*[1]X", serial, int(math.Ceil(math.Log2(float64(serial))/8)*2)), }, NotBefore: notBefore, NotAfter: notAfter, IsCA: false, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, KeyUsage: x509.KeyUsageDigitalSignature, BasicConstraintsValid: true, } pub, priv, err := GeneratePrivKey() if err != nil { return err } client_b, err := x509.CreateCertificate(rand.Reader, client, parent_cert, pub, parent_priv) if err != nil { return err } // Create intermediate directory os.MkdirAll(path.Join(PKIDir, fmt.Sprintf("%0[2]*[1]X", serial, int(math.Ceil(math.Log2(float64(serial))/8)*2))), 0777) // Save certificate to file if err := saveCertificate(ClientCertificatePath(serial), client_b); err != nil { return err } // Save private key to file if err := savePrivateKey(ClientPrivkeyPath(serial), priv); err != nil { return err } return nil } func WriteP12(serial uint64, password string) error { cmd := exec.Command("/usr/bin/openssl", "pkcs12", "-export", "-inkey", ClientPrivkeyPath(serial), "-in", ClientCertificatePath(serial), "-name", fmt.Sprintf("TEAM-%0[2]*[1]X", serial, int(math.Ceil(math.Log2(float64(serial))/8)*2)), "-passout", "pass:" + password, "-out", ClientP12Path(serial)) return cmd.Run() }