116 lines
3.1 KiB
Go
116 lines
3.1 KiB
Go
package su3
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/dsa"
|
|
"crypto/ecdsa"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/asn1"
|
|
"errors"
|
|
"math/big"
|
|
"time"
|
|
)
|
|
|
|
type dsaSignature struct {
|
|
R, S *big.Int
|
|
}
|
|
|
|
type ecdsaSignature dsaSignature
|
|
|
|
func checkSignature(c *x509.Certificate, algo x509.SignatureAlgorithm, signed, signature []byte) (err error) {
|
|
var hashType crypto.Hash
|
|
|
|
switch algo {
|
|
case x509.SHA1WithRSA, x509.DSAWithSHA1, x509.ECDSAWithSHA1:
|
|
hashType = crypto.SHA1
|
|
case x509.SHA256WithRSA, x509.DSAWithSHA256, x509.ECDSAWithSHA256:
|
|
hashType = crypto.SHA256
|
|
case x509.SHA384WithRSA, x509.ECDSAWithSHA384:
|
|
hashType = crypto.SHA384
|
|
case x509.SHA512WithRSA, x509.ECDSAWithSHA512:
|
|
hashType = crypto.SHA512
|
|
default:
|
|
return x509.ErrUnsupportedAlgorithm
|
|
}
|
|
|
|
if !hashType.Available() {
|
|
return x509.ErrUnsupportedAlgorithm
|
|
}
|
|
h := hashType.New()
|
|
|
|
h.Write(signed)
|
|
digest := h.Sum(nil)
|
|
|
|
switch pub := c.PublicKey.(type) {
|
|
case *rsa.PublicKey:
|
|
// the digest is already hashed, so we force a 0 here
|
|
return rsa.VerifyPKCS1v15(pub, 0, digest, signature)
|
|
case *dsa.PublicKey:
|
|
dsaSig := new(dsaSignature)
|
|
if _, err := asn1.Unmarshal(signature, dsaSig); err != nil {
|
|
return err
|
|
}
|
|
if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 {
|
|
return errors.New("x509: DSA signature contained zero or negative values")
|
|
}
|
|
if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) {
|
|
return errors.New("x509: DSA verification failure")
|
|
}
|
|
return
|
|
case *ecdsa.PublicKey:
|
|
ecdsaSig := new(ecdsaSignature)
|
|
if _, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
|
|
return err
|
|
}
|
|
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
|
|
return errors.New("x509: ECDSA signature contained zero or negative values")
|
|
}
|
|
if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
|
|
return errors.New("x509: ECDSA verification failure")
|
|
}
|
|
return
|
|
}
|
|
return x509.ErrUnsupportedAlgorithm
|
|
}
|
|
|
|
func NewSigningCertificate(signerID string, privateKey *rsa.PrivateKey) ([]byte, error) {
|
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
template := &x509.Certificate{
|
|
BasicConstraintsValid: true,
|
|
IsCA: true,
|
|
SubjectKeyId: []byte(signerID),
|
|
SerialNumber: serialNumber,
|
|
Subject: pkix.Name{
|
|
Organization: []string{"I2P Anonymous Network"},
|
|
OrganizationalUnit: []string{"I2P"},
|
|
Locality: []string{"XX"},
|
|
StreetAddress: []string{"XX"},
|
|
Country: []string{"XX"},
|
|
CommonName: signerID,
|
|
},
|
|
NotBefore: time.Now(),
|
|
NotAfter: time.Now().AddDate(10, 0, 0),
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
|
|
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
|
}
|
|
|
|
publicKey := &privateKey.PublicKey
|
|
|
|
// create a self-signed certificate. template = parent
|
|
parent := template
|
|
cert, err := x509.CreateCertificate(rand.Reader, template, parent, publicKey, privateKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return cert, nil
|
|
}
|