mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 18:36:30 +02:00
- Refactored middleware and request hander logging. - Request refactored to use context.Context. - Add helper (based on Alice) to allow middleware chaining. - Add helper scripts to generate elliptic curve self-signed certificate that can be used to sign JWT. - Changed LetsEncrypt scripts to use acme instead of certbot. - Add script to have LetsEncrypt sign an RSA based certificate. - Add documentation to explain how to verify headers. - Refactored internal/cryptutil signer's code to expect a valid EC priv key. - Changed JWT expiries to use default leeway period. - Update docs and add screenshots. - Replaced logging handler logic to use context.Context. - Removed specific XML error handling. - Refactored handler function signatures to prefer standard go idioms.
102 lines
2.4 KiB
Go
102 lines
2.4 KiB
Go
// Package cryptutil provides encoding and decoding routines for various cryptographic structures.
|
|
package cryptutil
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/x509"
|
|
"encoding/base64"
|
|
"encoding/pem"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// DecodePublicKey decodes a PEM-encoded ECDSA public key.
|
|
func DecodePublicKey(encodedKey []byte) (*ecdsa.PublicKey, error) {
|
|
block, _ := pem.Decode(encodedKey)
|
|
if block == nil || block.Type != "PUBLIC KEY" {
|
|
return nil, fmt.Errorf("marshal: could not decode PEM block type %s", block.Type)
|
|
|
|
}
|
|
|
|
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ecdsaPub, ok := pub.(*ecdsa.PublicKey)
|
|
if !ok {
|
|
return nil, errors.New("marshal: data was not an ECDSA public key")
|
|
}
|
|
|
|
return ecdsaPub, nil
|
|
}
|
|
|
|
// EncodePublicKey encodes an ECDSA public key to PEM format.
|
|
func EncodePublicKey(key *ecdsa.PublicKey) ([]byte, error) {
|
|
derBytes, err := x509.MarshalPKIXPublicKey(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
block := &pem.Block{
|
|
Type: "PUBLIC KEY",
|
|
Bytes: derBytes,
|
|
}
|
|
|
|
return pem.EncodeToMemory(block), nil
|
|
}
|
|
|
|
// DecodePrivateKey decodes a PEM-encoded ECDSA private key.
|
|
func DecodePrivateKey(encodedKey []byte) (*ecdsa.PrivateKey, error) {
|
|
var skippedTypes []string
|
|
var block *pem.Block
|
|
|
|
for {
|
|
block, encodedKey = pem.Decode(encodedKey)
|
|
|
|
if block == nil {
|
|
return nil, fmt.Errorf("failed to find EC PRIVATE KEY in PEM data after skipping types %v", skippedTypes)
|
|
}
|
|
|
|
if block.Type == "EC PRIVATE KEY" {
|
|
break
|
|
} else {
|
|
skippedTypes = append(skippedTypes, block.Type)
|
|
continue
|
|
}
|
|
}
|
|
|
|
privKey, err := x509.ParseECPrivateKey(block.Bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return privKey, nil
|
|
}
|
|
|
|
// EncodePrivateKey encodes an ECDSA private key to PEM format.
|
|
func EncodePrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
|
|
derKey, err := x509.MarshalECPrivateKey(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
keyBlock := &pem.Block{
|
|
Type: "EC PRIVATE KEY",
|
|
Bytes: derKey,
|
|
}
|
|
|
|
return pem.EncodeToMemory(keyBlock), nil
|
|
}
|
|
|
|
// EncodeSignatureJWT encodes an ECDSA signature according to
|
|
// https://tools.ietf.org/html/rfc7515#appendix-A.3.1
|
|
func EncodeSignatureJWT(sig []byte) string {
|
|
return base64.RawURLEncoding.EncodeToString(sig)
|
|
}
|
|
|
|
// DecodeSignatureJWT decodes an ECDSA signature according to
|
|
// https://tools.ietf.org/html/rfc7515#appendix-A.3.1
|
|
func DecodeSignatureJWT(b64sig string) ([]byte, error) {
|
|
return base64.RawURLEncoding.DecodeString(b64sig)
|
|
}
|