Skip to content

Commit

Permalink
Address review, fix linting issues
Browse files Browse the repository at this point in the history
Signed-off-by: Slavek Kabrda <[email protected]>
  • Loading branch information
bkabrda committed Jul 31, 2024
1 parent 09d589c commit ab939cc
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 31 deletions.
5 changes: 4 additions & 1 deletion pkg/root/trusted_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type CertificateAuthority struct {
Leaf *x509.Certificate
ValidityPeriodStart time.Time
ValidityPeriodEnd time.Time
URI string
}

type TransparencyLog struct {
Expand Down Expand Up @@ -249,7 +250,9 @@ func ParseCertificateAuthority(certAuthority *prototrustroot.CertificateAuthorit
return nil, fmt.Errorf("CertificateAuthority cert chain is empty")
}

certificateAuthority = &CertificateAuthority{}
certificateAuthority = &CertificateAuthority{
URI: certAuthority.Uri,
}
for i, cert := range certChain.GetCertificates() {
parsedCert, err := x509.ParseCertificate(cert.RawBytes)
if err != nil {
Expand Down
71 changes: 52 additions & 19 deletions pkg/root/trusted_root_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"encoding/pem"
"errors"
"fmt"
"sort"
"time"

protocommon "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1"
Expand Down Expand Up @@ -87,17 +88,17 @@ func NewTrustedRootFromTargets(mediaType string, targets []RawTrustedRootTarget)
case TSATarget:
tsaCertChains = append(tsaCertChains, target.GetBytes())
case RekorTarget:
tlInstance, keyId, err := pubkeyToTransparencyLogInstance(target.GetBytes(), now)
tlInstance, keyID, err := pubkeyToTransparencyLogInstance(target.GetBytes(), now)
if err != nil {
return nil, fmt.Errorf("failed to parse rekor key: %w", err)
}
tr.rekorLogs[keyId] = tlInstance
tr.rekorLogs[keyID] = tlInstance
case CTFETarget:
tlInstance, keyId, err := pubkeyToTransparencyLogInstance(target.GetBytes(), now)
tlInstance, keyID, err := pubkeyToTransparencyLogInstance(target.GetBytes(), now)
if err != nil {
return nil, fmt.Errorf("failed to parse ctlog key: %w", err)
}
tr.ctLogs[keyId] = tlInstance
tr.ctLogs[keyID] = tlInstance
}
}

Expand All @@ -121,7 +122,7 @@ func NewTrustedRootFromTargets(mediaType string, targets []RawTrustedRootTarget)
}

func pubkeyToTransparencyLogInstance(keyBytes []byte, tm time.Time) (*TransparencyLog, string, error) {
logId := sha256.Sum256(keyBytes)
logID := sha256.Sum256(keyBytes)
der, _ := pem.Decode(keyBytes)
key, keyDetails, err := getKeyWithDetails(der.Bytes)
if err != nil {
Expand All @@ -130,12 +131,12 @@ func pubkeyToTransparencyLogInstance(keyBytes []byte, tm time.Time) (*Transparen

return &TransparencyLog{
BaseURL: "",
ID: logId[:],
ID: logID[:],
ValidityPeriodStart: tm,
HashFunc: crypto.SHA256, // we can't get this from the keyBytes, assume SHA256
PublicKey: key,
SignatureHashFunc: keyDetails,
}, hex.EncodeToString(logId[:]), nil
}, hex.EncodeToString(logID[:]), nil
}

func getKeyWithDetails(key []byte) (crypto.PublicKey, crypto.Hash, error) {
Expand Down Expand Up @@ -213,9 +214,8 @@ func certsToAuthority(certChainPem []byte) (*CertificateAuthority, error) {
}
}

// TODO: should this rather be the innermost cert?
ca.ValidityPeriodStart = ca.Root.NotBefore
ca.ValidityPeriodEnd = ca.Root.NotAfter
ca.ValidityPeriodStart = certChain[0].NotBefore
ca.ValidityPeriodEnd = certChain[0].NotAfter

return &ca, nil
}
Expand All @@ -224,20 +224,46 @@ func (tr *TrustedRoot) constructProtoTrustRoot() error {
tr.trustedRoot = &prototrustroot.TrustedRoot{}
tr.trustedRoot.MediaType = TrustedRootMediaType01

for logId, transparencyLog := range tr.rekorLogs {
for logID, transparencyLog := range tr.rekorLogs {
tlProto, err := transparencyLogToProtobufTL(*transparencyLog)
if err != nil {
return fmt.Errorf("failed converting rekor log %s to protobuf: %w", logId, err)
return fmt.Errorf("failed converting rekor log %s to protobuf: %w", logID, err)
}
tr.trustedRoot.Tlogs = append(tr.trustedRoot.Tlogs, tlProto)
// ensure stable sorting of the slice
sort.Slice(tr.trustedRoot.Tlogs, func(i, j int) bool {
iTime := time.Unix(0, 0)
jTime := time.Unix(0, 0)

if tr.trustedRoot.Tlogs[i].PublicKey.ValidFor.Start != nil {
iTime = tr.trustedRoot.Tlogs[i].PublicKey.ValidFor.Start.AsTime()
}
if tr.trustedRoot.Tlogs[j].PublicKey.ValidFor.Start != nil {
iTime = tr.trustedRoot.Tlogs[j].PublicKey.ValidFor.Start.AsTime()
}
return iTime.Before(jTime)
})
}

for logId, ctLog := range tr.ctLogs {
for logID, ctLog := range tr.ctLogs {
ctProto, err := transparencyLogToProtobufTL(*ctLog)
if err != nil {
return fmt.Errorf("failed converting ctlog %s to protobuf: %w", logId, err)
return fmt.Errorf("failed converting ctlog %s to protobuf: %w", logID, err)
}
tr.trustedRoot.Ctlogs = append(tr.trustedRoot.Ctlogs, ctProto)
// ensure stable sorting of the slice
sort.Slice(tr.trustedRoot.Ctlogs, func(i, j int) bool {
iTime := time.Unix(0, 0)
jTime := time.Unix(0, 0)

if tr.trustedRoot.Ctlogs[i].PublicKey.ValidFor.Start != nil {
iTime = tr.trustedRoot.Ctlogs[i].PublicKey.ValidFor.Start.AsTime()
}
if tr.trustedRoot.Ctlogs[j].PublicKey.ValidFor.Start != nil {
iTime = tr.trustedRoot.Ctlogs[j].PublicKey.ValidFor.Start.AsTime()
}
return iTime.Before(jTime)
})
}

for _, ca := range tr.fulcioCertAuthorities {
Expand Down Expand Up @@ -277,20 +303,23 @@ func certificateAuthorityToProtobufCA(ca CertificateAuthority) (*prototrustroot.
allCerts = append(allCerts, &protocommon.X509Certificate{RawBytes: ca.Root.Raw})

caProto := prototrustroot.CertificateAuthority{
Uri: "",
Uri: ca.URI,
Subject: &protocommon.DistinguishedName{
Organization: org,
CommonName: ca.Root.Subject.CommonName,
},
ValidFor: &protocommon.TimeRange{
Start: timestamppb.New(ca.ValidityPeriodStart),
End: timestamppb.New(ca.ValidityPeriodEnd),
},
CertChain: &protocommon.X509CertificateChain{
Certificates: allCerts,
},
}

if !ca.ValidityPeriodEnd.IsZero() {
caProto.ValidFor.End = timestamppb.New(ca.ValidityPeriodEnd)
}

return &caProto, nil
}

Expand All @@ -299,7 +328,7 @@ func transparencyLogToProtobufTL(tl TransparencyLog) (*prototrustroot.Transparen
if err != nil {
return nil, fmt.Errorf("failed converting hash algorithm to protobuf: %w", err)
}
publicKey, err := publicKeyToProtobufPublicKey(tl.PublicKey, tl.ValidityPeriodStart)
publicKey, err := publicKeyToProtobufPublicKey(tl.PublicKey, tl.ValidityPeriodStart, tl.ValidityPeriodEnd)
if err != nil {
return nil, fmt.Errorf("failed converting public key to protobuf: %w", err)
}
Expand Down Expand Up @@ -332,13 +361,17 @@ func hashAlgorithmToProtobufHashAlgorithm(hashAlgorithm crypto.Hash) (protocommo
}
}

func publicKeyToProtobufPublicKey(publicKey crypto.PublicKey, tm time.Time) (*protocommon.PublicKey, error) {
func publicKeyToProtobufPublicKey(publicKey crypto.PublicKey, start time.Time, end time.Time) (*protocommon.PublicKey, error) {
pkd := protocommon.PublicKey{
ValidFor: &protocommon.TimeRange{
Start: timestamppb.New(tm),
Start: timestamppb.New(start),
},
}

if !end.IsZero() {
pkd.ValidFor.End = timestamppb.New(end)
}

rawBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return nil, fmt.Errorf("failed marshalling public key: %w", err)
Expand Down
14 changes: 3 additions & 11 deletions pkg/root/trusted_root_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ HOOVHVkwCgYIKoZIzj0EAwIDSAAwRQIhAJkNZmP6sKA+8EebRXFkBa9DPjacBpTc
OljJotvKidRhAiAuNrIazKEw2G4dw8x1z6EYk9G+7fJP5m93bjm/JfMBtA==
-----END CERTIFICATE-----`

fulcioRootCertBase64DER = `MIICNzCCAd2gAwIBAgITPLBoBQhl1hqFND9S+SGWbfzaRTAKBggqhkjOPQQDAjBoMQswCQYDVQQGEwJVSzESMBAGA1UECBMJV2lsdHNoaXJlMRMwEQYDVQQHEwpDaGlwcGVuaGFtMQ8wDQYDVQQKEwZSZWRIYXQxDDAKBgNVBAsTA0NUTzERMA8GA1UEAxMIdGVzdGNlcnQwHhcNMjEwMzEyMjMyNDQ5WhcNMzEwMjI4MjMyNDQ5WjBoMQswCQYDVQQGEwJVSzESMBAGA1UECBMJV2lsdHNoaXJlMRMwEQYDVQQHEwpDaGlwcGVuaGFtMQ8wDQYDVQQKEwZSZWRIYXQxDDAKBgNVBAsTA0NUTzERMA8GA1UEAxMIdGVzdGNlcnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQRn+Alyof6xP3GQClSwgV0NFuYYEwmKP/WLWr/LwB6LUYzt5v49RlqG83KuaJSpeOj7G7MVABdpIZYWwqAiZV3o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUT8Jwm6JuVb0dsiuHUROiHOOVHVkwHwYDVR0jBBgwFoAUT8Jwm6JuVb0dsiuHUROiHOOVHVkwCgYIKoZIzj0EAwIDSAAwRQIhAJkNZmP6sKA+8EebRXFkBa9DPjacBpTcOljJotvKidRhAiAuNrIazKEw2G4dw8x1z6EYk9G+7fJP5m93bjm/JfMBtA==`

ctlogPublicKey = `-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEAu1Ah4n2P8JGt92Qg86FdR8f1pou43yndggMuRCX0JB+bLn1rUFRA
KQVd+xnnd4PXJLLdml8ZohCr0lhBuMxZ7zBzt0T98kblUCxBgABPNpWIkTgacyC8
Expand Down Expand Up @@ -83,8 +81,6 @@ HvD4ejCZJOWQnqAlkqURllvu9M8+VqLbiRK+zSfZCZwsiljRn8MQQRSkXEE5AjEA
g+VxqtojfVfu8DhzzhCx9GKETbJHb19iV72mMKUbDAFmzZ6bQ8b54Zb8tidy5aWe
-----END CERTIFICATE-----`

tsaLeafCertBase64DER = `MIIB3DCCAWKgAwIBAgIUchkNsH36Xa04b1LqIc+qr9DVecMwCgYIKoZIzj0EAwMwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMB4XDTIzMDQxNDAwMDAwMFoXDTI0MDQxMzAwMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgVGltZXN0YW1waW5nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUD5ZNbSqYMd6r8qpOOEX9ibGnZT9GsuXOhr/f8U9FJugBGExKYp40OULS0erjZW7xV9xV52NnJf5OeDq4e5ZKqNWMFQwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUaW1RudOgVt0leqY0WKYbuPr47wAwCgYIKoZIzj0EAwMDaAAwZQIwbUH9HvD4ejCZJOWQnqAlkqURllvu9M8+VqLbiRK+zSfZCZwsiljRn8MQQRSkXEE5AjEAg+VxqtojfVfu8DhzzhCx9GKETbJHb19iV72mMKUbDAFmzZ6bQ8b54Zb8tidy5aWe`

tsaIntermedCert = `-----BEGIN CERTIFICATE-----
MIICEDCCAZWgAwIBAgIUX8ZO5QXP7vN4dMQ5e9sU3nub8OgwCgYIKoZIzj0EAwMw
ODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2
Expand All @@ -100,8 +96,6 @@ AK1B185ygCrIYFlIs3GjswjnwSMG6LY8woLVdakKDZxVa8f8cqMs1DhcxJ0+09w9
HdNmyA==
-----END CERTIFICATE-----`

tsaIntermedCertBase64DER = `MIICEDCCAZWgAwIBAgIUX8ZO5QXP7vN4dMQ5e9sU3nub8OgwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDQxNDAwMDAwMFoXDTI4MDQxMjAwMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEvMLY/dTVbvIJYANAuszEwJnQE1llftynyMKIMhh48HmqbVr5ygybzsLRLVKbBWOdZ21aeJz+gZiytZetqcyF9WlER5NEMf6JV7ZNojQpxHq4RHGoGSceQv/qvTiZxEDKo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaW1RudOgVt0leqY0WKYbuPr47wAwHwYDVR0jBBgwFoAU9NYYlobnAG4c0/qjxyH/lq/wz+QwCgYIKoZIzj0EAwMDaQAwZgIxAK1B185ygCrIYFlIs3GjswjnwSMG6LY8woLVdakKDZxVa8f8cqMs1DhcxJ0+09w95QIxAO+tBzZk7vjUJ9iJgD4R6ZWTxQWKqNm74jO99o+o9sv4FI/SZTZTFyMn0IJEHdNmyA==`

tsaRootCert = `-----BEGIN CERTIFICATE-----
MIIB9DCCAXqgAwIBAgIUa/JAkdUjK4JUwsqtaiRJGWhqLSowCgYIKoZIzj0EAwMw
ODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2
Expand All @@ -115,14 +109,12 @@ z+QwCgYIKoZIzj0EAwMDaAAwZQIxALZLZ8BgRXzKxLMMN9VIlO+e4hrBnNBgF7tz
7Hnrowv2NetZErIACKFymBlvWDvtMAIwZO+ki6ssQ1bsZo98O8mEAf2NZ7iiCgDD
U0Vwjeco6zyeh0zBTs9/7gV6AHNQ53xD
-----END CERTIFICATE-----`

tsaRootCertBase64DER = `MIIB9DCCAXqgAwIBAgIUa/JAkdUjK4JUwsqtaiRJGWhqLSowCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDQxNDAwMDAwMFoXDTMzMDQxMTAwMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEf9jFAXxz4kx68AHRMOkFBhflDcMTvzaXz4x/FCcXjJ/1qEKon/qPIGnaURskDtyNbNDOpeJTDDFqt48iMPrnzpx6IZwqemfUJN4xBEZfza+pYt/iyod+9tZr20RRWSv/o0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQU9NYYlobnAG4c0/qjxyH/lq/wz+QwCgYIKoZIzj0EAwMDaAAwZQIxALZLZ8BgRXzKxLMMN9VIlO+e4hrBnNBgF7tz7Hnrowv2NetZErIACKFymBlvWDvtMAIwZO+ki6ssQ1bsZo98O8mEAf2NZ7iiCgDDU0Vwjeco6zyeh0zBTs9/7gV6AHNQ53xD`
)

func TestConstructTrustedRootJSON(t *testing.T) {
var targets []RawTrustedRootTarget

var tsaCertChain []byte = []byte{}
var tsaCertChain = []byte{}
tsaCertChain = append(tsaCertChain, []byte(tsaLeafCert)...)
tsaCertChain = append(tsaCertChain, byte('\n'))
tsaCertChain = append(tsaCertChain, []byte(tsaIntermedCert)...)
Expand Down Expand Up @@ -210,8 +202,8 @@ func TestConstructTrustedRootJSON(t *testing.T) {
Root: parsedTSARootCert,
Intermediates: []*x509.Certificate{parsedTSAIntermedCert},
Leaf: parsedTSALeafCert,
ValidityPeriodStart: parsedTSARootCert.NotBefore,
ValidityPeriodEnd: parsedTSARootCert.NotAfter,
ValidityPeriodStart: parsedTSALeafCert.NotBefore,
ValidityPeriodEnd: parsedTSALeafCert.NotAfter,
},
}, fromJS.timestampingAuthorities)
}
14 changes: 14 additions & 0 deletions pkg/root/trusted_root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"encoding/json"
"encoding/pem"
"os"
"testing"
Expand Down Expand Up @@ -165,3 +166,16 @@ func TestTrustedMaterialCollectionRSA(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, verifier, verifier2)
}

func TestFromJSONToJSON(t *testing.T) {
trustedrootJSON, err := os.ReadFile("../../examples/trusted-root-public-good.json")
assert.NoError(t, err)

trustedRoot, err := NewTrustedRootFromJSON(trustedrootJSON)
assert.NoError(t, err)

jsonBytes, err := json.Marshal(trustedRoot)
assert.NoError(t, err)

assert.JSONEq(t, string(trustedrootJSON), string(jsonBytes))
}

0 comments on commit ab939cc

Please sign in to comment.