![JAR search and dependency download from the Maven repository](/logo.png)
vendor.github.com.cloudflare.circl.pki.pki.go Maven / Gradle / Ivy
The newest version!
package pki
import (
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"errors"
"strings"
"github.com/cloudflare/circl/sign"
"github.com/cloudflare/circl/sign/schemes"
)
var (
allSchemesByOID map[string]sign.Scheme
allSchemesByTLS map[uint]sign.Scheme
)
type pkixPrivKey struct {
Version int
Algorithm pkix.AlgorithmIdentifier
PrivateKey []byte
}
func init() {
allSchemesByOID = make(map[string]sign.Scheme)
allSchemesByTLS = make(map[uint]sign.Scheme)
for _, scheme := range schemes.All() {
if cert, ok := scheme.(CertificateScheme); ok {
allSchemesByOID[cert.Oid().String()] = scheme
}
if tlsScheme, ok := scheme.(TLSScheme); ok {
allSchemesByTLS[tlsScheme.TLSIdentifier()] = scheme
}
}
}
func SchemeByOid(oid asn1.ObjectIdentifier) sign.Scheme { return allSchemesByOID[oid.String()] }
func SchemeByTLSID(id uint) sign.Scheme { return allSchemesByTLS[id] }
// Additional methods when the signature scheme is supported in X509.
type CertificateScheme interface {
// Return the appropriate OIDs for this instance. It is implicitly
// assumed that the encoding is simple: e.g. uses the same OID for
// signature and public key like Ed25519.
Oid() asn1.ObjectIdentifier
}
// Additional methods when the signature scheme is supported in TLS.
type TLSScheme interface {
TLSIdentifier() uint
}
func UnmarshalPEMPublicKey(data []byte) (sign.PublicKey, error) {
block, rest := pem.Decode(data)
if len(rest) != 0 {
return nil, errors.New("trailing data")
}
if !strings.HasSuffix(block.Type, "PUBLIC KEY") {
return nil, errors.New("pem block type is not public key")
}
return UnmarshalPKIXPublicKey(block.Bytes)
}
func UnmarshalPKIXPublicKey(data []byte) (sign.PublicKey, error) {
var pkix struct {
Raw asn1.RawContent
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
if rest, err := asn1.Unmarshal(data, &pkix); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("trailing data")
}
scheme := SchemeByOid(pkix.Algorithm.Algorithm)
if scheme == nil {
return nil, errors.New("unsupported public key algorithm")
}
return scheme.UnmarshalBinaryPublicKey(pkix.PublicKey.RightAlign())
}
func UnmarshalPEMPrivateKey(data []byte) (sign.PrivateKey, error) {
block, rest := pem.Decode(data)
if len(rest) != 0 {
return nil, errors.New("trailing")
}
if !strings.HasSuffix(block.Type, "PRIVATE KEY") {
return nil, errors.New("pem block type is not private key")
}
return UnmarshalPKIXPrivateKey(block.Bytes)
}
func UnmarshalPKIXPrivateKey(data []byte) (sign.PrivateKey, error) {
var pkix pkixPrivKey
if rest, err := asn1.Unmarshal(data, &pkix); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("trailing data")
}
scheme := SchemeByOid(pkix.Algorithm.Algorithm)
if scheme == nil {
return nil, errors.New("unsupported public key algorithm")
}
var sk []byte
if rest, err := asn1.Unmarshal(pkix.PrivateKey, &sk); err != nil {
return nil, err
} else if len(rest) > 0 {
return nil, errors.New("trailing data")
}
return scheme.UnmarshalBinaryPrivateKey(sk)
}
func MarshalPEMPublicKey(pk sign.PublicKey) ([]byte, error) {
data, err := MarshalPKIXPublicKey(pk)
if err != nil {
return nil, err
}
str := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: data,
})
return str, nil
}
func MarshalPKIXPublicKey(pk sign.PublicKey) ([]byte, error) {
data, err := pk.MarshalBinary()
if err != nil {
return nil, err
}
scheme := pk.Scheme()
return asn1.Marshal(struct {
pkix.AlgorithmIdentifier
asn1.BitString
}{
pkix.AlgorithmIdentifier{
Algorithm: scheme.(CertificateScheme).Oid(),
},
asn1.BitString{
Bytes: data,
BitLength: len(data) * 8,
},
})
}
func MarshalPEMPrivateKey(sk sign.PrivateKey) ([]byte, error) {
data, err := MarshalPKIXPrivateKey(sk)
if err != nil {
return nil, err
}
str := pem.EncodeToMemory(&pem.Block{
Type: sk.Scheme().Name() + " PRIVATE KEY",
Bytes: data,
},
)
return str, nil
}
func MarshalPKIXPrivateKey(sk sign.PrivateKey) ([]byte, error) {
data, err := sk.MarshalBinary()
if err != nil {
return nil, err
}
data, err = asn1.Marshal(data)
if err != nil {
return nil, err
}
scheme := sk.Scheme()
return asn1.Marshal(pkixPrivKey{
0,
pkix.AlgorithmIdentifier{
Algorithm: scheme.(CertificateScheme).Oid(),
},
data,
})
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy