Example #1
0
func TestBuilderLoadInvalidDelegations(t *testing.T) {
	gun := "docker.com/notary"
	tufRepo, _, err := testutils.EmptyRepo(gun, "targets/a", "targets/a/b", "targets/b")
	require.NoError(t, err)

	meta, err := testutils.SignAndSerialize(tufRepo)
	require.NoError(t, err)

	builder := tuf.NewBuilderFromRepo(gun, tufRepo, trustpinning.TrustPinConfig{})

	// modify targets/a to remove the signature and update the snapshot
	// (we're not going to load the timestamp so no need to modify)
	targetsAJSON := meta["targets/a"]
	targetsA := data.Signed{}
	err = json.Unmarshal(targetsAJSON, &targetsA)
	require.NoError(t, err)
	targetsA.Signatures = make([]data.Signature, 0)
	targetsAJSON, err = json.Marshal(&targetsA)
	require.NoError(t, err)
	meta["targets/a"] = targetsAJSON
	delete(tufRepo.Targets, "targets/a")

	snap := tufRepo.Snapshot
	m, err := data.NewFileMeta(
		bytes.NewReader(targetsAJSON),
		"sha256", "sha512",
	)
	require.NoError(t, err)
	snap.AddMeta("targets/a", m)

	// load snapshot directly into repo to bypass signature check (we've invalidated
	// the signature by modifying it)
	tufRepo.Snapshot = snap

	// load targets/a
	require.Error(
		t,
		builder.Load(
			"targets/a",
			meta["targets/a"],
			1,
			false,
		),
	)

	_, invalid, err := builder.Finish()
	require.NoError(t, err)
	_, ok := invalid.Targets["targets/a"]
	require.True(t, ok)
}
Example #2
0
// Sign takes a data.Signed and a key, calculated and adds the signature
// to the data.Signed
func Sign(service CryptoService, s *data.Signed, keys ...data.PublicKey) error {
	logrus.Debugf("sign called with %d keys", len(keys))
	signatures := make([]data.Signature, 0, len(s.Signatures)+1)
	keyIDMemb := make(map[string]struct{})
	keyIDs := make(
		[]idPair,
		0,
		len(keys),
	)

	for _, key := range keys {
		keyID, err := utils.CanonicalKeyID(key)
		if err != nil {
			continue
		}
		keyIDMemb[key.ID()] = struct{}{}
		keyIDs = append(keyIDs, idPair{
			scopedKeyID:    key.ID(),
			canonicalKeyID: keyID,
		})
	}

	// we need to ask the signer to sign with the canonical key ID
	// (ID of the TUF key's public key bytes only), but
	// we need to translate back to the scoped key ID (the hash of the TUF key
	// with the full PEM bytes) before giving the
	// signature back to TUF.
	for _, pair := range keyIDs {
		newSigs, err := service.Sign([]string{pair.canonicalKeyID}, s.Signed)
		if err != nil {
			return err
		}
		// we only asked to sign with 1 key ID, so there will either be 1
		// or zero signatures
		if len(newSigs) == 1 {
			newSig := newSigs[0]
			newSig.KeyID = pair.scopedKeyID
			signatures = append(signatures, newSig)
		}
	}
	if len(signatures) < 1 {
		return errors.ErrInsufficientSignatures{
			Name: fmt.Sprintf("Cryptoservice failed to produce any signatures for keys with IDs: %v", keyIDs),
			Err:  nil,
		}
	}
	for _, sig := range s.Signatures {
		if _, ok := keyIDMemb[sig.KeyID]; ok {
			continue
		}
		signatures = append(signatures, sig)
	}
	s.Signatures = signatures
	return nil
}
Example #3
0
// signs the new metadata, replacing whatever signature was there
func serializeMetadata(cs signed.CryptoService, s *data.Signed, role string,
	pubKeys ...data.PublicKey) ([]byte, error) {

	// delete the existing signatures
	s.Signatures = []data.Signature{}

	if len(pubKeys) < 1 {
		return nil, ErrNoKeyForRole{role}
	}

	if err := signed.Sign(cs, s, pubKeys, 1, nil); err != nil {
		if _, ok := err.(signed.ErrInsufficientSignatures); ok {
			return nil, ErrNoKeyForRole{Role: role}
		}
		return nil, err
	}

	metaBytes, err := json.Marshal(s)
	if err != nil {
		return nil, err
	}

	return metaBytes, nil
}
Example #4
0
// Sign takes a data.Signed and a key, calculated and adds the signature
// to the data.Signed
func Sign(service CryptoService, s *data.Signed, keys ...data.PublicKey) error {
	logrus.Debugf("sign called with %d keys", len(keys))
	signatures := make([]data.Signature, 0, len(s.Signatures)+1)
	signingKeyIDs := make(map[string]struct{})
	ids := make([]string, 0, len(keys))

	privKeys := make(map[string]data.PrivateKey)

	// Get all the private key objects related to the public keys
	for _, key := range keys {
		canonicalID, err := utils.CanonicalKeyID(key)
		ids = append(ids, canonicalID)
		if err != nil {
			continue
		}
		k, _, err := service.GetPrivateKey(canonicalID)
		if err != nil {
			continue
		}
		privKeys[key.ID()] = k
	}

	// Check to ensure we have at least one signing key
	if len(privKeys) == 0 {
		return ErrNoKeys{KeyIDs: ids}
	}

	// Do signing and generate list of signatures
	for keyID, pk := range privKeys {
		sig, err := pk.Sign(rand.Reader, s.Signed, nil)
		if err != nil {
			logrus.Debugf("Failed to sign with key: %s. Reason: %v", keyID, err)
			continue
		}
		signingKeyIDs[keyID] = struct{}{}
		signatures = append(signatures, data.Signature{
			KeyID:     keyID,
			Method:    pk.SignatureAlgorithm(),
			Signature: sig[:],
		})
	}

	// Check we produced at least on signature
	if len(signatures) < 1 {
		return ErrInsufficientSignatures{
			Name: fmt.Sprintf(
				"cryptoservice failed to produce any signatures for keys with IDs: %v",
				ids),
		}
	}

	for _, sig := range s.Signatures {
		if _, ok := signingKeyIDs[sig.KeyID]; ok {
			// key is in the set of key IDs for which a signature has been created
			continue
		}
		signatures = append(signatures, sig)
	}
	s.Signatures = signatures
	return nil
}
Example #5
0
File: sign.go Project: Mic92/docker
// Sign takes a data.Signed and a cryptoservice containing private keys,
// calculates and adds at least minSignature signatures using signingKeys the
// data.Signed.  It will also clean up any signatures that are not in produced
// by either a signingKey or an otherWhitelistedKey.
// Note that in most cases, otherWhitelistedKeys should probably be null. They
// are for keys you don't want to sign with, but you also don't want to remove
// existing signatures by those keys.  For instance, if you want to call Sign
// multiple times with different sets of signing keys without undoing removing
// signatures produced by the previous call to Sign.
func Sign(service CryptoService, s *data.Signed, signingKeys []data.PublicKey,
	minSignatures int, otherWhitelistedKeys []data.PublicKey) error {

	logrus.Debugf("sign called with %d/%d required keys", minSignatures, len(signingKeys))
	signatures := make([]data.Signature, 0, len(s.Signatures)+1)
	signingKeyIDs := make(map[string]struct{})
	tufIDs := make(map[string]data.PublicKey)

	privKeys := make(map[string]data.PrivateKey)

	// Get all the private key objects related to the public keys
	missingKeyIDs := []string{}
	for _, key := range signingKeys {
		canonicalID, err := utils.CanonicalKeyID(key)
		tufIDs[key.ID()] = key
		if err != nil {
			return err
		}
		k, _, err := service.GetPrivateKey(canonicalID)
		if err != nil {
			if _, ok := err.(trustmanager.ErrKeyNotFound); ok {
				missingKeyIDs = append(missingKeyIDs, canonicalID)
				continue
			}
			return err
		}
		privKeys[key.ID()] = k
	}

	// include the list of otherWhitelistedKeys
	for _, key := range otherWhitelistedKeys {
		if _, ok := tufIDs[key.ID()]; !ok {
			tufIDs[key.ID()] = key
		}
	}

	// Check to ensure we have enough signing keys
	if len(privKeys) < minSignatures {
		return ErrInsufficientSignatures{FoundKeys: len(privKeys),
			NeededKeys: minSignatures, MissingKeyIDs: missingKeyIDs}
	}

	emptyStruct := struct{}{}
	// Do signing and generate list of signatures
	for keyID, pk := range privKeys {
		sig, err := pk.Sign(rand.Reader, *s.Signed, nil)
		if err != nil {
			logrus.Debugf("Failed to sign with key: %s. Reason: %v", keyID, err)
			return err
		}
		signingKeyIDs[keyID] = emptyStruct
		signatures = append(signatures, data.Signature{
			KeyID:     keyID,
			Method:    pk.SignatureAlgorithm(),
			Signature: sig[:],
		})
	}

	for _, sig := range s.Signatures {
		if _, ok := signingKeyIDs[sig.KeyID]; ok {
			// key is in the set of key IDs for which a signature has been created
			continue
		}
		var (
			k  data.PublicKey
			ok bool
		)
		if k, ok = tufIDs[sig.KeyID]; !ok {
			// key is no longer a valid signing key
			continue
		}
		if err := VerifySignature(*s.Signed, &sig, k); err != nil {
			// signature is no longer valid
			continue
		}
		// keep any signatures that still represent valid keys and are
		// themselves valid
		signatures = append(signatures, sig)
	}
	s.Signatures = signatures
	return nil
}