mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
2.8 KiB
113 lines
2.8 KiB
// cryptopasta - basic cryptography examples |
|
// |
|
// Written in 2015 by George Tankersley <george.tankersley@gmail.com> |
|
// |
|
// To the extent possible under law, the author(s) have dedicated all copyright |
|
// and related and neighboring rights to this software to the public domain |
|
// worldwide. This software is distributed without any warranty. |
|
// |
|
// You should have received a copy of the CC0 Public Domain Dedication along |
|
// with this software. If not, see // <http://creativecommons.org/publicdomain/zero/1.0/>. |
|
|
|
// Provides encoding and decoding routines for various cryptographic structures. |
|
package cryptopasta |
|
|
|
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 |
|
} |
|
|
|
// 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) |
|
} |
|
|
|
// 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) |
|
}
|
|
|