Skip to content

Permanent Certificates

benny daon edited this page Jun 6, 2021 · 3 revisions

Motivation

The need arose in peerbook signaling server. Users of peerbook have a address book of peers. For each peer it stores it's fingerprint, owner and and is it verified. The fingerprint can't be ephemeral has it's the peer's ID.

Browser Implementation

In the browser user's code have no access to the private parts of the certificates. The only way to storre & load a certificate is by using IndexedDB. IndexedDB is a low-level db with a complicated interface. Instead of using it directly it's recommended to use(idb)[https://www.npmjs.com/package/idb] that adds promises and lessens the pain.

In Pion

To support this feature in pion you will first need to create a certificate. Normally, pion creates a very short lived certificates - lasting only one months. To create a long lasting candidates you can use a slightly modified version of pion.GenerateCertificate():

func GeneratePermCert() (*webrtc.Certificate, error) {
        secretKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
        if err != nil {
                return nil, fmt.Errorf("Failed to generate key: %w", err)
        }
        origin := make([]byte, 16)
        /* #nosec */
        if _, err := rand.Read(origin); err != nil {
                return nil, err
        }

        // Max random value, a 130-bits integer, i.e 2^130 - 1
        maxBigInt := new(big.Int)
        /* #nosec */
        maxBigInt.Exp(big.NewInt(2), big.NewInt(130), nil).Sub(maxBigInt, big.NewInt(1))
        /* #nosec */
        serialNumber, err := rand.Int(rand.Reader, maxBigInt)
        if err != nil {
                return nil, err
        }

        return webrtc.NewCertificate(secretKey, x509.Certificate{
                ExtKeyUsage: []x509.ExtKeyUsage{
                        x509.ExtKeyUsageClientAuth,
                        x509.ExtKeyUsageServerAuth,
                },
                BasicConstraintsValid: true,
                NotBefore:             time.Now(),
                KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
                NotAfter:              time.Now().AddDate(10, 0, 0),
                SerialNumber:          serialNumber,
                Version:               2,
                Subject:               pkix.Name{CommonName: hex.EncodeToString(origin)},
                IsCA:                  true,
        })
}

To store the certificate you can use its PEM() method which returns string with two PEM blocks CERTIFICATE & PRIVATE KEY.

You'll probably want to store this string in a certnkey.pem file. To load a certificate from this string user webrtc.CertificateFromPEM() function.