server/pkg/pgp/rsa_signing_key.go

Summary

Maintainability
A
0 mins
Test Coverage
D
64%
package pgp

import (
    "crypto"
    "crypto/rand"
    "fmt"
    "io"
    "time"

    "golang.org/x/crypto/openpgp"
    "golang.org/x/crypto/openpgp/armor"
    "golang.org/x/crypto/openpgp/packet"
)

type RSASigningKey struct {
    Entity *openpgp.Entity
}

func (key *RSASigningKey) SerializePublicKey(out io.Writer) error {
    armoredOut, err := armor.Encode(out, openpgp.PublicKeyType, nil)
    if err != nil {
        return fmt.Errorf("unable to prepare armored writer: %w", err)
    }

    if err := key.Entity.Serialize(armoredOut); err != nil {
        return err
    }

    if err := armoredOut.Close(); err != nil {
        return fmt.Errorf("unable to close armored writer: %w", err)
    }

    return nil
}

func (key *RSASigningKey) SerializeFull(out io.Writer) error {
    return key.SerializePrivateKey(out)
}

func (key *RSASigningKey) SerializePrivateKey(out io.Writer) error {
    armoredOut, err := armor.Encode(out, openpgp.PrivateKeyType, nil)
    if err != nil {
        return fmt.Errorf("unable to prepare armored writer: %w", err)
    }

    if err := key.Entity.SerializePrivate(armoredOut, nil); err != nil {
        return err
    }

    if err := armoredOut.Close(); err != nil {
        return fmt.Errorf("unable to close armored writer: %w", err)
    }

    return nil
}

func GenerateRSASigningKey() (*RSASigningKey, error) {
    entity, err := openpgp.NewEntity("trdl", "trdl server auto signer", "", &packet.Config{
        Time:          time.Now,
        Rand:          rand.Reader,
        DefaultHash:   crypto.SHA256,
        DefaultCipher: packet.CipherAES128,
        RSABits:       4096,
    })
    if err != nil {
        return nil, fmt.Errorf("unable to generate openpgp entity: %w", err)
    }

    return &RSASigningKey{Entity: entity}, nil
}

func ParseRSASigningKey(in io.Reader) (*RSASigningKey, error) {
    el, err := openpgp.ReadArmoredKeyRing(in)
    if err != nil {
        return nil, err
    }

    if len(el) == 0 {
        return nil, fmt.Errorf("no private PGP signing key entities found")
    }

    return &RSASigningKey{Entity: el[0]}, nil
}

func SignDataStream(detachedSignatureOut io.Writer, dataStream io.Reader, key *RSASigningKey) error {
    return openpgp.DetachSign(detachedSignatureOut, key.Entity, dataStream, nil)
}