apc-p15-tool/pkg/pkcs15/pem_to_p15.go
2024-01-27 11:35:36 -05:00

138 lines
3.5 KiB
Go

package pkcs15
import (
"apc-p15-tool/pkg/tools/asn1obj"
"math/big"
)
const (
apcKeyLabel = "Private key"
)
// ToP15File turns the key and cert into a properly formatted and encoded
// p15 file
func (p15 *pkcs15KeyCert) ToP15File() ([]byte, error) {
// private key object
pkey, err := p15.toP15PrivateKey()
if err != nil {
return nil, err
}
cert, err := p15.toP15Cert()
if err != nil {
return nil, err
}
// ContentInfo
p15File := asn1obj.Sequence([][]byte{
// contentType: OID: 1.2.840.113549.1.15.3.1 pkcs15content (PKCS #15 content type)
asn1obj.ObjectIdentifier(asn1obj.OIDPkscs15Content),
// content
asn1obj.ExplicitCompound(0, [][]byte{
asn1obj.Sequence([][]byte{
asn1obj.Integer(big.NewInt(0)),
asn1obj.Sequence([][]byte{
asn1obj.ExplicitCompound(0, [][]byte{
asn1obj.ExplicitCompound(0, [][]byte{
pkey,
}),
}),
asn1obj.ExplicitCompound(4, [][]byte{
asn1obj.ExplicitCompound(0, [][]byte{
cert,
}),
}),
}),
}),
}),
})
return p15File, nil
}
// toP15PrivateKey creates the encoded private key. it is broken our from the larger p15
// function for readability
// NOTE: Do not use this to try and turn just a private key into a p15, the format isn't
// quite the same.
func (p15 *pkcs15KeyCert) toP15PrivateKey() ([]byte, error) {
// rsa encrypted key in encrypted envelope
envelope, err := p15.encryptedKeyEnvelope()
if err != nil {
return nil, err
}
// key object
key := asn1obj.Sequence([][]byte{
// commonObjectAttributes - Label
asn1obj.Sequence([][]byte{
asn1obj.UTF8String(apcKeyLabel),
}),
// CommonKeyAttributes
asn1obj.Sequence([][]byte{
// CommonKeyAttributes - iD - uses keyId that is SHA1( SubjectPublicKeyInfo SEQUENCE )
asn1obj.OctetString(p15.keyId()),
// CommonKeyAttributes - usage (trailing 0s will drop)
asn1obj.BitString([]byte{byte(0b11100010)}),
// CommonKeyAttributes - accessFlags (trailing 0s will drop)
asn1obj.BitString([]byte{byte(0b10110000)}),
// CommonKeyAttributes - startDate
asn1obj.GeneralizedTime(p15.cert.NotBefore),
// CommonKeyAttributes - [0] endDate
asn1obj.GeneralizedTimeExplicitValue(0, p15.cert.NotAfter),
}),
// ObjectValue - indirect-protected
asn1obj.ExplicitCompound(1, [][]byte{
asn1obj.Sequence([][]byte{
// AuthEnvelopedData Type ([4])
asn1obj.ExplicitCompound(4, [][]byte{
envelope,
}),
}),
}),
})
return key, nil
}
// toP15Cert creates the encoded certificate. it is broken our from the larger p15
// function for readability
// NOTE: Do not use this to try and turn just a cert into a p15. I don't believe,
// such a thing is permissible under the spec.
func (p15 *pkcs15KeyCert) toP15Cert() ([]byte, error) {
// cert object
cert := asn1obj.Sequence([][]byte{
// commonObjectAttributes - Label
asn1obj.Sequence([][]byte{
asn1obj.UTF8String(apcKeyLabel),
}),
// keyIds of various types
asn1obj.Sequence([][]byte{
asn1obj.OctetString(p15.keyId()),
// additional keyids
asn1obj.ExplicitCompound(2, [][]byte{
p15.keyIdInt2(),
p15.keyIdInt3(),
p15.keyIdInt6(),
p15.keyIdInt7(),
p15.keyIdInt8(),
p15.keyIdInt9(),
}),
// CommonKeyAttributes - startDate
asn1obj.GeneralizedTime(p15.cert.NotBefore),
// CommonKeyAttributes - [4] endDate
asn1obj.GeneralizedTimeExplicitValue(4, p15.cert.NotAfter),
}),
// actual certificate itself
asn1obj.ExplicitCompound(1, [][]byte{
asn1obj.Sequence([][]byte{
asn1obj.ExplicitCompound(0, [][]byte{
p15.cert.Raw,
}),
}),
}),
})
return cert, nil
}