From 07a71d7b77dad8754205483dfc069fc136a26854 Mon Sep 17 00:00:00 2001
From: Gibheer <gibheer+git@zero-knowledge.org>
Date: Sat, 10 Sep 2022 18:45:00 +0200
Subject: vendor all dependencies

---
 vendor/git.zero-knowledge.org/gibheer/pki/AUTHORS  |   3 +
 vendor/git.zero-knowledge.org/gibheer/pki/LICENSE  |  13 ++
 .../git.zero-knowledge.org/gibheer/pki/README.md   |   7 +
 .../gibheer/pki/certificate.go                     | 181 +++++++++++++++++++++
 vendor/git.zero-knowledge.org/gibheer/pki/ecdsa.go | 142 ++++++++++++++++
 .../git.zero-knowledge.org/gibheer/pki/ed25519.go  | 119 ++++++++++++++
 .../gibheer/pki/pem_marshal.go                     |  16 ++
 vendor/git.zero-knowledge.org/gibheer/pki/rsa.go   | 115 +++++++++++++
 vendor/git.zero-knowledge.org/gibheer/pki/types.go |  66 ++++++++
 vendor/modules.txt                                 |   3 +
 10 files changed, 665 insertions(+)
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/AUTHORS
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/LICENSE
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/README.md
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/certificate.go
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/ecdsa.go
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/ed25519.go
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/pem_marshal.go
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/rsa.go
 create mode 100644 vendor/git.zero-knowledge.org/gibheer/pki/types.go
 create mode 100644 vendor/modules.txt

(limited to 'vendor')

diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/AUTHORS b/vendor/git.zero-knowledge.org/gibheer/pki/AUTHORS
new file mode 100644
index 0000000..3d1b9f5
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/AUTHORS
@@ -0,0 +1,3 @@
+This is the list of contributors to this project:
+
+* Stefan Radomski
diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/LICENSE b/vendor/git.zero-knowledge.org/gibheer/pki/LICENSE
new file mode 100644
index 0000000..c0f36b1
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2014, the authors of pkictl <gibheer@zero-knowledge.org>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/README.md b/vendor/git.zero-knowledge.org/gibheer/pki/README.md
new file mode 100644
index 0000000..8c9a336
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/README.md
@@ -0,0 +1,7 @@
+pki
+===
+
+This is a small library to make building private keys, public keys, signatures
+and most of the certificate stuff a bit easier.
+
+For a cli you can take a look at [pkictl](https://git.zero-knowledge.org/gibheer/pkictl)
diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/certificate.go b/vendor/git.zero-knowledge.org/gibheer/pki/certificate.go
new file mode 100644
index 0000000..b90e9fa
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/certificate.go
@@ -0,0 +1,181 @@
+package pki
+
+import (
+	"crypto/rand"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/pem"
+	"fmt"
+	"io"
+	"math/big"
+	"net"
+	"time"
+)
+
+// labels used in the pem file format to mark certificate sign requests and certificates
+const (
+	PemLabelCertificateRequest = "CERTIFICATE REQUEST"
+	PemLabelCertificate        = "CERTIFICATE"
+)
+
+type (
+	// Use CertificateData to fill in the minimum data you need to create a certificate
+	// sign request.
+	CertificateData struct {
+		Subject pkix.Name
+
+		DNSNames       []string
+		EmailAddresses []string
+		IPAddresses    []net.IP
+	}
+
+	// Certificate is an alias on the x509.Certificate to add some methods.
+	Certificate x509.Certificate
+	// CertificateRequest is an alias on the x509.CertificateRequest to add some methods.
+	CertificateRequest x509.CertificateRequest
+
+	// CertificateOptions is used to provide the necessary information to create
+	// a certificate from a certificate sign request.
+	CertificateOptions struct {
+		SerialNumber *big.Int
+		NotBefore    time.Time
+		NotAfter     time.Time // Validity bounds.
+		IsCA         bool
+		// how many sub ca are allowed between this ca and the end/final certificate
+		// if it is -1, then no limit will be set
+		CALength         int
+		KeyUsage         x509.KeyUsage      // for what can the certificate be used
+		KeyExtendedUsage []x509.ExtKeyUsage // extended usage for the certificate
+		CRLUrls          []string
+	}
+)
+
+// Create a new set of certificate data.
+func NewCertificateData() *CertificateData {
+	return &CertificateData{Subject: pkix.Name{}}
+}
+
+// Create a certificate sign request from the input data and the private key of
+// the request creator.
+func (c *CertificateData) ToCertificateRequest(private_key PrivateKey) (*CertificateRequest, error) {
+	csr := &x509.CertificateRequest{}
+
+	csr.Subject = c.Subject
+	csr.DNSNames = c.DNSNames
+	csr.IPAddresses = c.IPAddresses
+	csr.EmailAddresses = c.EmailAddresses
+
+	csr_asn1, err := x509.CreateCertificateRequest(rand.Reader, csr, private_key.PrivateKey())
+	if err != nil {
+		return nil, err
+	}
+	return LoadCertificateSignRequest(csr_asn1)
+}
+
+// Load a certificate sign request from its asn1 representation.
+func LoadCertificateSignRequest(raw []byte) (*CertificateRequest, error) {
+	csr, err := x509.ParseCertificateRequest(raw)
+	if err != nil {
+		return nil, err
+	}
+	return (*CertificateRequest)(csr), nil
+}
+
+// ToPem returns a pem.Block representing the CertificateRequest.
+func (c *CertificateRequest) ToPem() (pem.Block, error) {
+	return pem.Block{Type: PemLabelCertificateRequest, Bytes: c.Raw}, nil
+}
+
+// Return the certificate sign request as a pem block.
+func (c *CertificateRequest) MarshalPem() (io.WriterTo, error) {
+	if block, err := c.ToPem(); err != nil {
+		return nil, err
+	} else {
+		return marshalledPemBlock(pem.EncodeToMemory(&block)), nil
+	}
+}
+
+// Convert the certificate sign request to a certificate using the private key
+// of the signer and the certificate of the signer.
+// If the certificate is null, the sign request will be used to sign itself.
+// Please also see the certificate options struct for information on mandatory fields.
+// For more information, please read http://golang.org/pkg/crypto/x509/#CreateCertificate
+func (c *CertificateRequest) ToCertificate(private_key PrivateKey,
+	cert_opts CertificateOptions, ca *Certificate) (*Certificate, error) {
+
+	if err := cert_opts.Valid(); err != nil {
+		return nil, err
+	}
+
+	template := &x509.Certificate{}
+	template.Subject = c.Subject
+	template.DNSNames = c.DNSNames
+	template.IPAddresses = c.IPAddresses
+	template.EmailAddresses = c.EmailAddresses
+
+	// if no ca is given, we have to set IsCA to self sign
+	if ca == nil {
+		template.IsCA = true
+	}
+
+	template.NotBefore = cert_opts.NotBefore
+	template.NotAfter = cert_opts.NotAfter
+	template.KeyUsage = cert_opts.KeyUsage
+	template.ExtKeyUsage = cert_opts.KeyExtendedUsage
+	template.CRLDistributionPoints = cert_opts.CRLUrls
+	template.IsCA = cert_opts.IsCA
+	if cert_opts.IsCA {
+		template.BasicConstraintsValid = true
+	}
+	if cert_opts.CALength >= 0 {
+		template.MaxPathLen = cert_opts.CALength
+		template.MaxPathLenZero = true
+		template.BasicConstraintsValid = true
+	}
+	template.SerialNumber = cert_opts.SerialNumber
+
+	var cert_asn1 []byte
+	var err error
+	// if we have no ca which can sign the cert, a self signed cert is wanted
+	// (or isn't it? Maybe we should split creation of the template? But that would be ugly)
+	if ca == nil {
+		cert_asn1, err = x509.CreateCertificate(rand.Reader, template, template, c.PublicKey, private_key.PrivateKey())
+	} else {
+		cert_asn1, err = x509.CreateCertificate(rand.Reader, template, (*x509.Certificate)(ca), c.PublicKey, private_key.PrivateKey())
+	}
+	if err != nil {
+		return nil, err
+	}
+	return LoadCertificate(cert_asn1)
+}
+
+// Load a certificate from its asn1 representation.
+func LoadCertificate(raw []byte) (*Certificate, error) {
+	cert, err := x509.ParseCertificate(raw)
+	if err != nil {
+		return nil, err
+	}
+	return (*Certificate)(cert), nil
+}
+
+// marshal the certificate to a pem block
+func (c *Certificate) MarshalPem() (io.WriterTo, error) {
+	if block, err := c.ToPem(); err != nil {
+		return nil, err
+	} else {
+		return marshalledPemBlock(pem.EncodeToMemory(&block)), nil
+	}
+}
+
+// ToPem returns the pem block of the certificate.
+func (c *Certificate) ToPem() (pem.Block, error) {
+	return pem.Block{Type: PemLabelCertificate, Bytes: c.Raw}, nil
+}
+
+// Check if the certificate options have the required fields set.
+func (co *CertificateOptions) Valid() error {
+	if co.SerialNumber == nil {
+		return fmt.Errorf("No serial number set!")
+	}
+	return nil
+}
diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/ecdsa.go b/vendor/git.zero-knowledge.org/gibheer/pki/ecdsa.go
new file mode 100644
index 0000000..4202bd6
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/ecdsa.go
@@ -0,0 +1,142 @@
+package pki
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/rand"
+	"crypto/x509"
+	"encoding/asn1"
+	"encoding/pem"
+	"errors"
+	"io"
+	"math/big"
+)
+
+// This label is used as the type in the pem encoding of ECDSA private keys.
+const PemLabelEcdsa = "EC PRIVATE KEY"
+
+type (
+	// This type handles the function calls to the ecdsa private key by
+	// implementing the interface.
+	EcdsaPrivateKey struct {
+		private_key *ecdsa.PrivateKey
+	}
+
+	// EcdsaPublicKey is the specific public key type for ecdsa. It implements the
+	// the PublicKey interface.
+	EcdsaPublicKey struct {
+		public_key *ecdsa.PublicKey
+	}
+
+	// This struct is used to marshal and parse the ecdsa signature.
+	signatureEcdsa struct {
+		R, S *big.Int
+	}
+)
+
+// Create a new ECDSA private key using the specified curve.
+// For available curves, please take a look at the crypto/elliptic package.
+func NewPrivateKeyEcdsa(curve elliptic.Curve) (*EcdsaPrivateKey, error) {
+	key, err := ecdsa.GenerateKey(curve, rand.Reader)
+	if err != nil {
+		return nil, err
+	}
+	return &EcdsaPrivateKey{key}, nil
+}
+
+// Load the private key from the asn1 representation.
+func LoadPrivateKeyEcdsa(raw []byte) (*EcdsaPrivateKey, error) {
+	key, err := x509.ParseECPrivateKey(raw)
+	if err != nil {
+		return nil, err
+	}
+	return &EcdsaPrivateKey{key}, nil
+}
+
+// Create a new public key from the private key.
+func (pr EcdsaPrivateKey) Public() PublicKey {
+	return &EcdsaPublicKey{pr.private_key.Public().(*ecdsa.PublicKey)}
+}
+
+// Sign a message using the private key and the provided hash function.
+func (pr EcdsaPrivateKey) Sign(message []byte, hash crypto.Hash) ([]byte, error) {
+	empty := make([]byte, 0)
+	if !hash.Available() {
+		return empty, errors.New("Hash method is not available!")
+	}
+	hashed_message := hash.New()
+	hashed_message.Write(message)
+	return pr.private_key.Sign(rand.Reader, hashed_message.Sum(nil), hash)
+}
+
+// This function returns the crypto.PrivateKey structure of the ECDSA key.
+func (pr EcdsaPrivateKey) PrivateKey() crypto.PrivateKey {
+	return pr.private_key
+}
+
+// This function implements the Pemmer interface to marshal the private key
+// into a pem block.
+func (pr EcdsaPrivateKey) MarshalPem() (io.WriterTo, error) {
+	pem_block, err := pr.ToPem()
+	if err != nil {
+		return nil, err
+	}
+	return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+}
+
+// This function implements ToPem to return the raw pem block.
+func (pr EcdsaPrivateKey) ToPem() (pem.Block, error) {
+	asn1, err := x509.MarshalECPrivateKey(pr.private_key)
+	if err != nil {
+		return pem.Block{}, err
+	}
+	return pem.Block{Type: PemLabelEcdsa, Bytes: asn1}, nil
+}
+
+// This functoin loads an ecdsa public key from the asn.1 representation.
+func LoadPublicKeyEcdsa(raw []byte) (*EcdsaPublicKey, error) {
+	raw_pub, err := x509.ParsePKIXPublicKey(raw)
+	if err != nil {
+		return nil, err
+	}
+
+	pub, ok := raw_pub.(*ecdsa.PublicKey)
+	if !ok {
+		return nil, errors.New("Not an ecdsa key!")
+	}
+	return &EcdsaPublicKey{pub}, nil
+}
+
+// ToPem returns the pem block of the public key.
+func (pu *EcdsaPublicKey) ToPem() (pem.Block, error) {
+	asn1, err := x509.MarshalPKIXPublicKey(pu.public_key)
+	if err != nil {
+		return pem.Block{}, err
+	}
+	return pem.Block{Type: PemLabelPublic, Bytes: asn1}, nil
+}
+
+// This function implements the Pemmer interface to marshal the public key into
+// a pem block.
+func (pu *EcdsaPublicKey) MarshalPem() (io.WriterTo, error) {
+	if block, err := pu.ToPem(); err != nil {
+		return nil, err
+	} else {
+		return marshalledPemBlock(pem.EncodeToMemory(&block)), nil
+	}
+}
+
+// This function verifies a message using the public key, signature and hash
+// function.
+// The hash function must be the same as was used to create the signature.
+func (pu *EcdsaPublicKey) Verify(message []byte, signature_raw []byte, hash crypto.Hash) (bool, error) {
+	var sig signatureEcdsa
+	_, err := asn1.Unmarshal(signature_raw, &sig)
+	if err != nil {
+		return false, err
+	}
+	hashed_message := hash.New()
+	hashed_message.Write(message)
+	return ecdsa.Verify(pu.public_key, hashed_message.Sum(nil), sig.R, sig.S), nil
+}
diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/ed25519.go b/vendor/git.zero-knowledge.org/gibheer/pki/ed25519.go
new file mode 100644
index 0000000..0104beb
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/ed25519.go
@@ -0,0 +1,119 @@
+package pki
+
+import (
+	"bytes"
+	"crypto"
+	"crypto/ed25519"
+	"crypto/rand"
+	"encoding/pem"
+	"errors"
+	"fmt"
+	"io"
+)
+
+const (
+	PemLabelEd25519 = "ED25519 PRIVATE KEY" // TODO find correct label
+)
+
+type (
+	Ed25519PrivateKey struct {
+		private_key ed25519.PrivateKey
+	}
+
+	Ed25519PublicKey struct {
+		public_key ed25519.PublicKey
+	}
+)
+
+// Create a new private key of type ed25519.
+func NewPrivateKeyEd25519() (*Ed25519PrivateKey, error) {
+	_, pr_raw, err := ed25519.GenerateKey(rand.Reader)
+	if err != nil {
+		return nil, err
+	}
+	return &Ed25519PrivateKey{pr_raw}, nil
+}
+
+// Restore an ed25519 private key from a raw byte stream.
+// TODO does this have to be asn1? all other functions expect asn1
+func LoadPrivateKeyEd25519(raw []byte) (*Ed25519PrivateKey, error) {
+	pr_loaded := make([]byte, ed25519.PrivateKeySize)
+	length := copy(pr_loaded, raw)
+	if length != ed25519.PrivateKeySize {
+		return nil, fmt.Errorf("private key length incorrect - got: %d - expected: %d", length, ed25519.PrivateKeySize)
+	}
+	return &Ed25519PrivateKey{pr_loaded}, nil
+}
+
+// TODO implement the raw API for the private key
+func (pr *Ed25519PrivateKey) PrivateKey() crypto.PrivateKey {
+	return nil
+}
+
+// Return the public key for this private key.
+func (pr *Ed25519PrivateKey) Public() PublicKey {
+	buf := bytes.NewBufferString(string(pr.private_key[:])) // create a bytes buffer to read the private key
+	pu_raw, _, err := ed25519.GenerateKey(buf)              // use the already built private key again
+	if err != nil {
+		return nil
+	}
+	return &Ed25519PublicKey{pu_raw}
+}
+
+// Hash the message given the hash algorythm and sign the hash using the private key.
+func (pr *Ed25519PrivateKey) Sign(message []byte, hash crypto.Hash) ([]byte, error) {
+	hashed_message := hash.New()
+	hashed_message.Write(message)
+	result := ed25519.Sign(pr.private_key, hashed_message.Sum(nil))[:]
+	return result, nil
+}
+
+// Export the private key into the Pem format.
+func (pr Ed25519PrivateKey) MarshalPem() (io.WriterTo, error) {
+	pem_block, err := pr.ToPem()
+	if err != nil { // it does not currently return an error, but maybe that will change
+		return nil, err
+	}
+	return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+}
+
+func (pr Ed25519PrivateKey) ToPem() (pem.Block, error) {
+	return pem.Block{Type: PemLabelEd25519, Bytes: pr.private_key[:]}, nil
+}
+
+// Load the public key from a raw byte stream.
+// TODO should this be read from ASN.1? All other functions do that.
+func LoadPublicKeyEd25519(raw []byte) (*Ed25519PublicKey, error) {
+	pu_loaded := make([]byte, ed25519.PublicKeySize)
+	length := copy(pu_loaded, raw)
+	if length != ed25519.PublicKeySize {
+		return nil, errors.New("public key length incorrect")
+	}
+	return &Ed25519PublicKey{pu_loaded}, nil
+}
+
+// ToPem returns the pem encoded public key.
+func (pu Ed25519PublicKey) ToPem() (pem.Block, error) {
+	return pem.Block{Type: PemLabelPublic, Bytes: pu.public_key[:]}, nil
+}
+
+// Export the public key into the pem format.
+func (pu Ed25519PublicKey) MarshalPem() (io.WriterTo, error) {
+	pem_block, err := pu.ToPem()
+	if err != nil {
+		return nil, err
+	}
+	return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+}
+
+// Hash the message with the hash algorythm and check the signature against the result.
+func (pu Ed25519PublicKey) Verify(message []byte, signature []byte, hash crypto.Hash) (bool, error) {
+	sig := make([]byte, ed25519.SignatureSize)
+	length := copy(sig[:], signature)
+	if length != ed25519.SignatureSize {
+		return false, errors.New("signature does not fit length")
+	}
+	hashed_message := hash.New()
+	hashed_message.Write(message)
+	return ed25519.Verify(pu.public_key, hashed_message.Sum(nil), sig), nil
+}
diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/pem_marshal.go b/vendor/git.zero-knowledge.org/gibheer/pki/pem_marshal.go
new file mode 100644
index 0000000..89bd477
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/pem_marshal.go
@@ -0,0 +1,16 @@
+package pki
+
+import (
+	"io"
+)
+
+type (
+	marshalledPemBlock []byte
+)
+
+// This function writes the marshalled pem block to a writer and returns the
+// number of written bytes and eventual errors.
+func (b marshalledPemBlock) WriteTo(stream io.Writer) (int64, error) {
+	numBytes, err := stream.Write(b)
+	return int64(numBytes), err
+}
diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/rsa.go b/vendor/git.zero-knowledge.org/gibheer/pki/rsa.go
new file mode 100644
index 0000000..b4024ac
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/rsa.go
@@ -0,0 +1,115 @@
+package pki
+
+import (
+	"crypto"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/pem"
+	"errors"
+	"io"
+)
+
+const (
+	PemLabelRsa = "RSA PRIVATE KEY"
+)
+
+type (
+	RsaPrivateKey struct {
+		private_key *rsa.PrivateKey
+	}
+
+	RsaPublicKey struct {
+		public_key *rsa.PublicKey
+	}
+)
+
+// generate a new rsa private key
+func NewPrivateKeyRsa(size int) (*RsaPrivateKey, error) {
+	key, err := rsa.GenerateKey(rand.Reader, size)
+	if err != nil {
+		return nil, err
+	}
+	return &RsaPrivateKey{key}, nil
+}
+
+// load a rsa private key its ASN.1 presentation
+func LoadPrivateKeyRsa(raw []byte) (*RsaPrivateKey, error) {
+	key, err := x509.ParsePKCS1PrivateKey(raw)
+	if err != nil {
+		return nil, err
+	}
+	return &RsaPrivateKey{key}, nil
+}
+
+func (pr *RsaPrivateKey) Public() PublicKey {
+	return &RsaPublicKey{pr.private_key.Public().(*rsa.PublicKey)}
+}
+
+func (pr RsaPrivateKey) Sign(message []byte, hash crypto.Hash) ([]byte, error) {
+	if !hash.Available() {
+		return make([]byte, 0), errors.New("Hash method is not available!")
+	}
+	hashed_message := hash.New()
+	hashed_message.Write(message)
+	return rsa.SignPKCS1v15(rand.Reader, pr.private_key, hash, hashed_message.Sum(nil))
+}
+
+// get the private key
+func (pr RsaPrivateKey) PrivateKey() crypto.PrivateKey {
+	return pr.private_key
+}
+
+func (pr RsaPrivateKey) MarshalPem() (io.WriterTo, error) {
+	pem_block, err := pr.ToPem()
+	if err != nil { // it does not currently return an error, but maybe that will change
+		return nil, err
+	}
+	return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+}
+
+func (pr RsaPrivateKey) ToPem() (pem.Block, error) {
+	return pem.Block{
+		Type:  PemLabelRsa,
+		Bytes: x509.MarshalPKCS1PrivateKey(pr.private_key),
+	}, nil
+}
+
+// restore a rsa public key
+func LoadPublicKeyRsa(raw []byte) (*RsaPublicKey, error) {
+	pub := &RsaPublicKey{}
+	if pub_raw, err := x509.ParsePKIXPublicKey(raw); err != nil {
+		return nil, err
+	} else {
+		pub.public_key = pub_raw.(*rsa.PublicKey)
+	}
+	return pub, nil
+}
+
+// ToPem returns the pem encoded public key.
+func (pu *RsaPublicKey) ToPem() (pem.Block, error) {
+	asn1, err := x509.MarshalPKIXPublicKey(pu.public_key)
+	if err != nil {
+		return pem.Block{}, err
+	}
+	return pem.Block{Type: PemLabelPublic, Bytes: asn1}, nil
+}
+
+// marshal a rsa public key into pem format
+func (pu *RsaPublicKey) MarshalPem() (io.WriterTo, error) {
+	pem_block, err := pu.ToPem()
+	if err != nil {
+		return nil, err
+	}
+	return marshalledPemBlock(pem.EncodeToMemory(&pem_block)), nil
+}
+
+// verify a message with a signature using the public key
+func (pu *RsaPublicKey) Verify(message []byte, signature []byte, hash crypto.Hash) (bool, error) {
+	hashed_message := hash.New()
+	hashed_message.Write(message)
+	if err := rsa.VerifyPKCS1v15(pu.public_key, hash, hashed_message.Sum(nil), signature); err != nil {
+		return false, err
+	}
+	return true, nil
+}
diff --git a/vendor/git.zero-knowledge.org/gibheer/pki/types.go b/vendor/git.zero-knowledge.org/gibheer/pki/types.go
new file mode 100644
index 0000000..f2c6902
--- /dev/null
+++ b/vendor/git.zero-knowledge.org/gibheer/pki/types.go
@@ -0,0 +1,66 @@
+// Package pki provides an easier way to create crypto related structures
+// with the intent of making the management of these structures easier for
+// other programs.
+// Currently it provides mechanisms to create private keys in ECDSA and RSA,
+// create public keys, create certificate sign requests and certificates.
+//
+// To create a new private key, there are two ways
+// for an ecdsa key
+//   private_key, err := NewPrivateKeyEcdsa(elliptic.P521())
+// or for a RSA key
+//   private_key, err := NewPrivateKeyRSA(4096)
+//
+// Getting a private key from the private key can be done with
+//   public_key := private_key.Public()
+package pki
+
+import (
+	"crypto"
+	"encoding/pem"
+	"io"
+)
+
+// This label is used as the type in the pem encoding of public keys.
+const PemLabelPublic = "PUBLIC KEY"
+
+type (
+	// PrivateKey is a common interface for all crypto implementations to provide
+	// the same functions, like deriving a public key or signing a message.
+	PrivateKey interface {
+		// Derive a new public key from the private key.
+		Public() PublicKey
+		// Sign a message using the public key and the given hash method.
+		// To use a hash method, include the package
+		//   import _ "crypto/sha512"
+		Sign(message []byte, hash crypto.Hash) ([]byte, error)
+
+		// Return the original go structure of the private key.
+		PrivateKey() crypto.PrivateKey
+
+		// ToPem must return a pem block of the private key.
+		ToPem() (pem.Block, error)
+	}
+
+	// PublicKey is used by the different crypto implementations to provide the
+	// same functionality like verifying a message against a signature.
+	PublicKey interface {
+		Pemmer
+		PemOutput
+		// This function can be used to verify a message against a provided signature
+		// using the given hash function.
+		Verify(message []byte, signature []byte, hash crypto.Hash) (bool, error)
+	}
+
+	// Pemmer is used by all crypto structures which need to be available
+	// in the pem format. The result can then be written to any structure
+	// implementing the io.Writer interface.
+	Pemmer interface {
+		MarshalPem() (io.WriterTo, error)
+	}
+
+	// ToPem returns the raw pem block to make it possible to write the result to
+	// any place.
+	PemOutput interface {
+		ToPem() (pem.Block, error)
+	}
+)
diff --git a/vendor/modules.txt b/vendor/modules.txt
new file mode 100644
index 0000000..42f4cea
--- /dev/null
+++ b/vendor/modules.txt
@@ -0,0 +1,3 @@
+# git.zero-knowledge.org/gibheer/pki v0.0.0-20220815203810-d34a8ab26ec7
+## explicit; go 1.19
+git.zero-knowledge.org/gibheer/pki
-- 
cgit v1.2.3-70-g09d2