Skip to content

Commit

Permalink
Merge pull request #12 from lukpueh/misc-refactor
Browse files Browse the repository at this point in the history
Clean up InTotoVerify and rsa public key loading
  • Loading branch information
SantiagoTorres authored Jan 8, 2019
2 parents 0fec144 + 7e2dc50 commit 0ffe145
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 54 deletions.
56 changes: 29 additions & 27 deletions in_toto/keylib.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,29 @@ import (
"reflect"
)

func ParseRSAPublicKeyFromPEM(pemBytes []byte) (*rsa.PublicKey, error) {
// TODO: There could be more key data in _, which we silently ignore here.
// Should we handle it / fail / say something about it?
data, _ := pem.Decode([]byte(pemBytes))
if data == nil {
return nil, fmt.Errorf("Could not find a public key PEM block")
}

pub, err := x509.ParsePKIXPublicKey(data.Bytes)
if err != nil {
return nil, err
}

//ParsePKIXPublicKey might return an rsa, dsa, or ecdsa public key
rsaPub, isRsa := pub.(*rsa.PublicKey)
if !isRsa {
return nil, fmt.Errorf("We currently only support rsa keys: got '%s'",
reflect.TypeOf(pub))
}

return rsaPub, nil
}

func (k *Key) LoadPublicKey(path string) error {
keyFile, err := os.Open(path)
defer keyFile.Close()
Expand All @@ -27,24 +50,13 @@ func (k *Key) LoadPublicKey(path string) error {
return err
}

// Parse just to see if this is a pem formatted key
// TODO: There could be more key data in _, which we silently ignore here.
// Should we handle it / fail / say something about it?
data, _ := pem.Decode([]byte(keyBytes))
if data == nil {
return fmt.Errorf("No valid public rsa key found at '%s'", path)
}

// Parse just to see if this is indeed an rsa public key
pub, err := x509.ParsePKIXPublicKey(data.Bytes)
// We only parse to see if this is indeed a pem formatted rsa public key,
// but don't use the returned *rsa.PublicKey. Instead, we continue with
// the original keyBytes from above.
_, err = ParseRSAPublicKeyFromPEM(keyBytes)
if err != nil {
return err
}
_, isRsa := pub.(*rsa.PublicKey)
if !isRsa {
return fmt.Errorf("We currently only support rsa keys: got '%s'",
reflect.TypeOf(pub))
}

// Strip leading and trailing data from PEM file like securesystemslib does
// TODO: Should we instead use the parsed public key to reconstruct the PEM?
Expand All @@ -54,7 +66,7 @@ func (k *Key) LoadPublicKey(path string) error {
keyEnd := strings.Index(string(keyBytes), keyFooter) + len(keyFooter)

// Fail if header and footer are not present
// TODO: Is this necessary? pem.Decode or ParsePKIXPublicKey should already
// TODO: Is this necessary? ParseRSAPublicKeyFromPEM should already
// return an error if header and footer are not present
if keyStart == -1 || keyEnd == -1 {
return fmt.Errorf("No valid public rsa key found at '%s'", path)
Expand Down Expand Up @@ -112,21 +124,11 @@ func VerifySignature(key Key, sig Signature, data []byte) error {
if err != nil {
return err
}

block, _ := pem.Decode(pemBytes)
if block == nil {
return fmt.Errorf("Could not find a public key PEM block")
}

pub, err := x509.ParsePKIXPublicKey(block.Bytes)
rsaPub, err := ParseRSAPublicKeyFromPEM(pemBytes)
if err != nil {
return err
}

rsaPub, ok := pub.(*rsa.PublicKey)
if !ok {
return fmt.Errorf("Expected '*rsa.PublicKey' got '%s", reflect.TypeOf(pub))
}

hashed := sha256.Sum256(data)

Expand Down
39 changes: 30 additions & 9 deletions in_toto/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,25 @@ type Link struct {
const LinkNameFormat = "%s.%.8s.link"
const LinkNameFormatShort = "%s.link"

type Inspection struct {
Type string `json:"_type"`
Run []string `json:"run"`
// TODO: Abstraction for Steps and Inspections?

type SupplyChainItem struct {
Name string `json:"name"`
ExpectedMaterials [][]string `json:"expected_materials"`
ExpectedProducts [][]string `json:"expected_products"`
}

type Inspection struct {
Type string `json:"_type"`
Run []string `json:"run"`
SupplyChainItem
}

type Step struct {
Type string `json:"_type"`
PubKeys []string `json:"pubkeys"`
ExpectedCommand []string `json:"expected_command"`
Threshold int `json:"threshold"`

// TODO: Abstraction for Steps and Inspections?
Name string `json:"name"`
ExpectedMaterials [][]string `json:"expected_materials"`
ExpectedProducts [][]string `json:"expected_products"`
SupplyChainItem
}

type Layout struct {
Expand All @@ -68,6 +68,27 @@ type Layout struct {
Readme string `json:"readme"`
}

// Go does not allow to pass `[]T` (slice with certain type) to a function
// that accepts `[]interface{}` (slice with generic type)
// We have to manually create the interface slice first, see
// https://golang.org/doc/faq#convert_slice_of_interface
// TODO: Is there a better way to do polymorphism for steps and inspections?
func (l *Layout) StepsAsInterfaceSlice() []interface{} {
stepsI := make([]interface{}, len(l.Steps))
for i, v := range l.Steps {
stepsI[i] = v
}
return stepsI
}
func (l *Layout) InspectAsInterfaceSlice() []interface{} {
inspectionsI := make([]interface{}, len(l.Inspect))
for i, v := range l.Inspect {
inspectionsI[i] = v
}
return inspectionsI
}


type Metablock struct {
// NOTE: Whenever we want to access an attribute of `Signed` we have to
// perform type assertion, e.g. `metablock.Signed.(Layout).Keys`
Expand Down
20 changes: 2 additions & 18 deletions in_toto/verifylib.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,15 +477,8 @@ func InTotoVerify(layoutPath string, layoutKeys map[string]Key,
return err
}

// Go does not allow to pass []Step as []interface{}
// We have to manually copy first :(
// https://golang.org/doc/faq#convert_slice_of_interface
stepsI := make([]interface{}, len(layout.Steps))
for i, v := range layout.Steps {
stepsI[i] = v
}
// Verify artifact rules
if err := VerifyArtifacts(stepsI, stepsMetadataReduced); err != nil {
if err := VerifyArtifacts(layout.StepsAsInterfaceSlice(), stepsMetadataReduced); err != nil {
return err
}

Expand All @@ -500,18 +493,9 @@ func InTotoVerify(layoutPath string, layoutKeys map[string]Key,
inspectionMetadata[k] = v
}

// Convert []Inspections to []interace{} (see `stepsI` above)
inspectionsI := make([]interface{}, len(layout.Inspect))
for i, v := range layout.Inspect {
inspectionsI[i] = v
}

if err := VerifyArtifacts(inspectionsI, inspectionMetadata); err != nil {
if err := VerifyArtifacts(layout.InspectAsInterfaceSlice(), inspectionMetadata); err != nil {
return err
}

return nil
}



0 comments on commit 0ffe145

Please sign in to comment.