#Create a self-signed X.509 certificate through PKCS 11

23 messages · Page 1 of 1 (latest)

undone ibex
#

Hello, I want to create a self-signed X.509 certificate through the following PKCS #11 implementation: https://pkg.go.dev/github.com/miekg/[email protected]/p11.

privateKeyObject, err = t.session.FindObject(privateKeyTemplate)
if err != nil {
    return nil, err
}

certTemplate := &x509.Certificate{
    SerialNumber: big.NewInt(2022),
    Subject: pkix.Name{
        CommonName: "test",
    },
    SignatureAlgorithm: x509.SHA512WithRSA,
    NotBefore:          time.Now(),
    NotAfter:           time.Now().AddDate(1, 0, 0),
}

signer, err = NewSigner(p11.PrivateKey(privateKeyObject))
if err != nil {
    return nil, err
}

cert, err = x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, signer.PublicKey, signer)
if err != nil {
    return nil, err
}

Of course I had to implement the crypto.Signer interface because RSA key pair is stored in an HSM.

type Signer struct {
    PrivateKey p11.PrivateKey
    PublicKey  *rsa.PublicKey
}

func (s Signer) Public() crypto.PublicKey {
    return s.PublicKey
}

func (s Signer) Sign(_ io.Reader, digest []byte, _ crypto.SignerOpts) ([]byte, error) {
    return s.PrivateKey.Sign(pkcs11.Mechanism{Mechanism: pkcs11.CKM_SHA512_RSA_PKCS}, digest)
}

func NewSigner(privateKey p11.PrivateKey) (*Signer, error) {
    var (
        modulus, publicExponent []byte
        err                     error
    )

    modulus, err = p11.Object(privateKey).Attribute(pkcs11.CKA_MODULUS)
    if err != nil {
        return nil, err
    }

    publicExponent, err = p11.Object(privateKey).Attribute(pkcs11.CKA_PUBLIC_EXPONENT)
    if err != nil {
        return nil, err
    }

    publicKey := &rsa.PublicKey{
        N: new(big.Int).SetBytes(modulus),
        E: int(big.NewInt(0).SetBytes(publicExponent).Uint64()),
    }

    return &Signer{PrivateKey: privateKey, PublicKey: publicKey}, nil
}
rare hill
#

Since it's a verification error, I'm guessing it might be related to how you're returning a clone of the public key. Is there any reason to do that instead of just returning the *rsa.PublicKey?

rare hill
#

Yes

#

IIRC, each private key from the stdlib has a public key associated with it. Or maybe it's the other way around.

#

No, the other way would be dangerous.

#

You may need to have the caller pass in a p11.KeyPair.

undone ibex
#

So the way I build the public key is not optimal?

rare hill
#

I'm concerned it might be part of why you're getting validation errors. It seems to me to be easy to get wrong.
If I were in your shoes, that's what I'd be looking more closely at.

undone ibex
rare hill
#

More specifically, I would be looking to avoid manually setting up that struct at all and making the library do it for me.

#

Yes I think p11.KeyPairs is what you want.

undone ibex
#

Deep down, I knew it wasn't good 😄

#

So the Signer structure should look like this?

type Signer struct {
    PrivateKey p11.PrivateKey
    PublicKey p11.PublicKey
}
#

No actually I have to keep *rsa.PublicKey but I just don't understand how I can get it via my private key

rare hill
#

IIRC, PKCS11 is a padding system. You ought to be able to use RSA keys with it, but I don't know the details. 😕

#

I believe you may need to construct an RSA public key / private key pair then use it alongside pkcs11.

undone ibex
rare hill
#

That sounds reasonable, if it was originally an rsa.PublicKey.

undone ibex