예제 #1
0
파일: repo.go 프로젝트: pombredanne/go-tuf
func (r *Repo) GenKeyWithExpires(keyRole string, expires time.Time) (string, error) {
	if !keys.ValidRole(keyRole) {
		return "", ErrInvalidRole{keyRole}
	}

	if !validExpires(expires) {
		return "", ErrInvalidExpires{expires}
	}

	root, err := r.root()
	if err != nil {
		return "", err
	}

	key, err := keys.NewKey()
	if err != nil {
		return "", err
	}
	if err := r.local.SaveKey(keyRole, key.SerializePrivate()); err != nil {
		return "", err
	}

	role, ok := root.Roles[keyRole]
	if !ok {
		role = &data.Role{KeyIDs: []string{}, Threshold: 1}
		root.Roles[keyRole] = role
	}
	role.KeyIDs = append(role.KeyIDs, key.ID)

	root.Keys[key.ID] = key.Serialize()
	root.Expires = expires.Round(time.Second)
	root.Version++

	return key.ID, r.setMeta("root.json", root)
}
예제 #2
0
func (RepoSuite) TestSign(c *C) {
	meta := map[string]json.RawMessage{"root.json": []byte(`{"signed":{},"signatures":[]}`)}
	local := MemoryStore(meta, nil)
	r, err := NewRepo(local)
	c.Assert(err, IsNil)

	// signing with no keys returns ErrInsufficientKeys
	c.Assert(r.Sign("root.json"), Equals, ErrInsufficientKeys{"root.json"})

	checkSigIDs := func(keyIDs ...string) {
		rootJSON, ok := meta["root.json"]
		if !ok {
			c.Fatal("missing root.json")
		}
		s := &data.Signed{}
		c.Assert(json.Unmarshal(rootJSON, s), IsNil)
		c.Assert(s.Signatures, HasLen, len(keyIDs))
		for i, id := range keyIDs {
			c.Assert(s.Signatures[i].KeyID, Equals, id)
		}
	}

	// signing with an available key generates a signature
	key, err := keys.NewKey()
	c.Assert(err, IsNil)
	c.Assert(local.SaveKey("root", key.SerializePrivate()), IsNil)
	c.Assert(r.Sign("root.json"), IsNil)
	checkSigIDs(key.ID)

	// signing again does not generate a duplicate signature
	c.Assert(r.Sign("root.json"), IsNil)
	checkSigIDs(key.ID)

	// signing with a new available key generates another signature
	newKey, err := keys.NewKey()
	c.Assert(err, IsNil)
	c.Assert(local.SaveKey("root", newKey.SerializePrivate()), IsNil)
	c.Assert(r.Sign("root.json"), IsNil)
	checkSigIDs(key.ID, newKey.ID)
}
예제 #3
0
func (RepoSuite) TestKeyPersistence(c *C) {
	tmp := newTmpDir(c)
	passphrase := []byte("s3cr3t")
	store := FileSystemStore(tmp.path, testPassphraseFunc(passphrase))

	assertEqual := func(actual []*data.Key, expected []*keys.Key) {
		c.Assert(actual, HasLen, len(expected))
		for i, key := range expected {
			c.Assert(actual[i].ID(), Equals, key.ID)
			c.Assert(actual[i].Value.Public, DeepEquals, data.HexBytes(key.Public[:]))
			c.Assert(actual[i].Value.Private, DeepEquals, data.HexBytes(key.Private[:]))
		}
	}

	assertKeys := func(role string, enc bool, expected []*keys.Key) {
		keysJSON := tmp.readFile("keys/" + role + ".json")
		pk := &persistedKeys{}
		c.Assert(json.Unmarshal(keysJSON, pk), IsNil)

		// check the persisted keys are correct
		var actual []*data.Key
		if enc {
			c.Assert(pk.Encrypted, Equals, true)
			decrypted, err := encrypted.Decrypt(pk.Data, passphrase)
			c.Assert(err, IsNil)
			c.Assert(json.Unmarshal(decrypted, &actual), IsNil)
		} else {
			c.Assert(pk.Encrypted, Equals, false)
			c.Assert(json.Unmarshal(pk.Data, &actual), IsNil)
		}
		assertEqual(actual, expected)

		// check GetKeys is correct
		actual, err := store.GetKeys(role)
		c.Assert(err, IsNil)
		assertEqual(actual, expected)
	}

	// save a key and check it gets encrypted
	key, err := keys.NewKey()
	c.Assert(err, IsNil)
	c.Assert(store.SaveKey("root", key.SerializePrivate()), IsNil)
	assertKeys("root", true, []*keys.Key{key})

	// save another key and check it gets added to the existing keys
	newKey, err := keys.NewKey()
	c.Assert(err, IsNil)
	c.Assert(store.SaveKey("root", newKey.SerializePrivate()), IsNil)
	assertKeys("root", true, []*keys.Key{key, newKey})

	// check saving a key to an encrypted file without a passphrase fails
	insecureStore := FileSystemStore(tmp.path, nil)
	key, err = keys.NewKey()
	c.Assert(err, IsNil)
	c.Assert(insecureStore.SaveKey("root", key.SerializePrivate()), Equals, ErrPassphraseRequired{"root"})

	// save a key to an insecure store and check it is not encrypted
	key, err = keys.NewKey()
	c.Assert(err, IsNil)
	c.Assert(insecureStore.SaveKey("targets", key.SerializePrivate()), IsNil)
	assertKeys("targets", false, []*keys.Key{key})
}
예제 #4
0
func (VerifySuite) Test(c *C) {
	type test struct {
		name  string
		keys  []*data.Key
		roles map[string]*data.Role
		s     *data.Signed
		ver   int
		exp   *time.Time
		typ   string
		role  string
		err   error
		mut   func(*test)
	}

	expiredTime := time.Now().Add(-time.Hour)
	minVer := 10
	tests := []test{
		{
			name: "no signatures",
			mut:  func(t *test) { t.s.Signatures = []data.Signature{} },
			err:  ErrNoSignatures,
		},
		{
			name: "unknown role",
			role: "foo",
			err:  ErrUnknownRole,
		},
		{
			name: "wrong signature method",
			mut:  func(t *test) { t.s.Signatures[0].Method = "foo" },
			err:  ErrWrongMethod,
		},
		{
			name: "signature wrong length",
			mut:  func(t *test) { t.s.Signatures[0].Signature = []byte{0} },
			err:  ErrInvalid,
		},
		{
			name: "key missing from role",
			mut:  func(t *test) { t.roles["root"].KeyIDs = nil },
			err:  ErrRoleThreshold,
		},
		{
			name: "invalid signature",
			mut:  func(t *test) { t.s.Signatures[0].Signature = make([]byte, ed25519.SignatureSize) },
			err:  ErrInvalid,
		},
		{
			name: "not enough signatures",
			mut:  func(t *test) { t.roles["root"].Threshold = 2 },
			err:  ErrRoleThreshold,
		},
		{
			name: "exactly enough signatures",
		},
		{
			name: "more than enough signatures",
			mut: func(t *test) {
				k, _ := keys.NewKey()
				Sign(t.s, k.SerializePrivate())
				t.keys = append(t.keys, k.Serialize())
				t.roles["root"].KeyIDs = append(t.roles["root"].KeyIDs, k.ID)
			},
		},
		{
			name: "duplicate key id",
			mut: func(t *test) {
				t.roles["root"].Threshold = 2
				t.s.Signatures = append(t.s.Signatures, t.s.Signatures[0])
			},
			err: ErrRoleThreshold,
		},
		{
			name: "unknown key",
			mut: func(t *test) {
				k, _ := keys.NewKey()
				Sign(t.s, k.Serialize())
			},
		},
		{
			name: "unknown key below threshold",
			mut: func(t *test) {
				k, _ := keys.NewKey()
				Sign(t.s, k.Serialize())
				t.roles["root"].Threshold = 2
			},
			err: ErrRoleThreshold,
		},
		{
			name: "unknown keys in db",
			mut: func(t *test) {
				k, _ := keys.NewKey()
				Sign(t.s, k.Serialize())
				t.keys = append(t.keys, k.Serialize())
			},
		},
		{
			name: "unknown keys in db below threshold",
			mut: func(t *test) {
				k, _ := keys.NewKey()
				Sign(t.s, k.Serialize())
				t.keys = append(t.keys, k.Serialize())
				t.roles["root"].Threshold = 2
			},
			err: ErrRoleThreshold,
		},
		{
			name: "wrong type",
			typ:  "bar",
			err:  ErrWrongType,
		},
		{
			name: "low version",
			ver:  minVer - 1,
			err:  ErrLowVersion{minVer - 1, minVer},
		},
		{
			name: "expired",
			exp:  &expiredTime,
			err:  ErrExpired{expiredTime},
		},
	}
	for _, t := range tests {
		if t.role == "" {
			t.role = "root"
		}
		if t.ver == 0 {
			t.ver = minVer
		}
		if t.exp == nil {
			expires := time.Now().Add(time.Hour)
			t.exp = &expires
		}
		if t.typ == "" {
			t.typ = t.role
		}
		if t.keys == nil && t.s == nil {
			k, _ := keys.NewKey()
			t.s, _ = Marshal(&signedMeta{Type: t.typ, Version: t.ver, Expires: *t.exp}, k.SerializePrivate())
			t.keys = []*data.Key{k.Serialize()}
		}
		if t.roles == nil {
			t.roles = map[string]*data.Role{
				"root": &data.Role{
					KeyIDs:    []string{t.keys[0].ID()},
					Threshold: 1,
				},
			}
		}
		if t.mut != nil {
			t.mut(&t)
		}

		db := keys.NewDB()
		for _, k := range t.keys {
			err := db.AddKey(k.ID(), k)
			c.Assert(err, IsNil)
		}
		for n, r := range t.roles {
			err := db.AddRole(n, r)
			c.Assert(err, IsNil)
		}

		err := Verify(t.s, t.role, minVer, db)
		if e, ok := t.err.(ErrExpired); ok {
			assertErrExpired(c, err, e)
		} else {
			c.Assert(err, DeepEquals, t.err, Commentf("name = %s", t.name))
		}
	}
}