gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/asserts/account_key_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2015-2021 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package asserts_test
    21  
    22  import (
    23  	"encoding/base64"
    24  	"fmt"
    25  	"path/filepath"
    26  	"strings"
    27  	"time"
    28  
    29  	. "gopkg.in/check.v1"
    30  
    31  	"github.com/snapcore/snapd/asserts"
    32  	"github.com/snapcore/snapd/asserts/assertstest"
    33  )
    34  
    35  type accountKeySuite struct {
    36  	privKey              asserts.PrivateKey
    37  	pubKeyBody           string
    38  	keyID                string
    39  	since, until         time.Time
    40  	sinceLine, untilLine string
    41  }
    42  
    43  var _ = Suite(&accountKeySuite{})
    44  
    45  func (aks *accountKeySuite) SetUpSuite(c *C) {
    46  	cfg1 := &asserts.DatabaseConfig{}
    47  	accDb, err := asserts.OpenDatabase(cfg1)
    48  	c.Assert(err, IsNil)
    49  	aks.privKey = testPrivKey1
    50  	err = accDb.ImportKey(aks.privKey)
    51  	c.Assert(err, IsNil)
    52  	aks.keyID = aks.privKey.PublicKey().ID()
    53  
    54  	pubKey, err := accDb.PublicKey(aks.keyID)
    55  	c.Assert(err, IsNil)
    56  	pubKeyEncoded, err := asserts.EncodePublicKey(pubKey)
    57  	c.Assert(err, IsNil)
    58  	aks.pubKeyBody = string(pubKeyEncoded)
    59  
    60  	aks.since, err = time.Parse(time.RFC822, "16 Nov 15 15:04 UTC")
    61  	c.Assert(err, IsNil)
    62  	aks.until = aks.since.AddDate(1, 0, 0)
    63  	aks.sinceLine = "since: " + aks.since.Format(time.RFC3339) + "\n"
    64  	aks.untilLine = "until: " + aks.until.Format(time.RFC3339) + "\n"
    65  }
    66  
    67  func (aks *accountKeySuite) TestDecodeOK(c *C) {
    68  	encoded := "type: account-key\n" +
    69  		"authority-id: canonical\n" +
    70  		"account-id: acc-id1\n" +
    71  		"name: default\n" +
    72  		"public-key-sha3-384: " + aks.keyID + "\n" +
    73  		aks.sinceLine +
    74  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
    75  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
    76  		aks.pubKeyBody + "\n\n" +
    77  		"AXNpZw=="
    78  	a, err := asserts.Decode([]byte(encoded))
    79  	c.Assert(err, IsNil)
    80  	c.Check(a.Type(), Equals, asserts.AccountKeyType)
    81  	accKey := a.(*asserts.AccountKey)
    82  	c.Check(accKey.AccountID(), Equals, "acc-id1")
    83  	c.Check(accKey.Name(), Equals, "default")
    84  	c.Check(accKey.PublicKeyID(), Equals, aks.keyID)
    85  	c.Check(accKey.Since(), Equals, aks.since)
    86  }
    87  
    88  func (aks *accountKeySuite) TestDecodeNoName(c *C) {
    89  	// XXX: remove this test once name is mandatory
    90  	encoded := "type: account-key\n" +
    91  		"authority-id: canonical\n" +
    92  		"account-id: acc-id1\n" +
    93  		"public-key-sha3-384: " + aks.keyID + "\n" +
    94  		aks.sinceLine +
    95  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
    96  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
    97  		aks.pubKeyBody + "\n\n" +
    98  		"AXNpZw=="
    99  	a, err := asserts.Decode([]byte(encoded))
   100  	c.Assert(err, IsNil)
   101  	c.Check(a.Type(), Equals, asserts.AccountKeyType)
   102  	accKey := a.(*asserts.AccountKey)
   103  	c.Check(accKey.AccountID(), Equals, "acc-id1")
   104  	c.Check(accKey.Name(), Equals, "")
   105  	c.Check(accKey.PublicKeyID(), Equals, aks.keyID)
   106  	c.Check(accKey.Since(), Equals, aks.since)
   107  }
   108  
   109  func (aks *accountKeySuite) TestUntil(c *C) {
   110  
   111  	untilSinceLine := "until: " + aks.since.Format(time.RFC3339) + "\n"
   112  
   113  	tests := []struct {
   114  		untilLine string
   115  		until     time.Time
   116  	}{
   117  		{"", time.Time{}},           // zero time default
   118  		{aks.untilLine, aks.until},  // in the future
   119  		{untilSinceLine, aks.since}, // same as since
   120  	}
   121  
   122  	for _, test := range tests {
   123  		c.Log(test)
   124  		encoded := "type: account-key\n" +
   125  			"authority-id: canonical\n" +
   126  			"account-id: acc-id1\n" +
   127  			"name: default\n" +
   128  			"public-key-sha3-384: " + aks.keyID + "\n" +
   129  			aks.sinceLine +
   130  			test.untilLine +
   131  			fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   132  			"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   133  			aks.pubKeyBody + "\n\n" +
   134  			"openpgp c2ln"
   135  		a, err := asserts.Decode([]byte(encoded))
   136  		c.Assert(err, IsNil)
   137  		accKey := a.(*asserts.AccountKey)
   138  		c.Check(accKey.Until(), Equals, test.until)
   139  	}
   140  }
   141  
   142  const (
   143  	accKeyErrPrefix    = "assertion account-key: "
   144  	accKeyReqErrPrefix = "assertion account-key-request: "
   145  )
   146  
   147  func (aks *accountKeySuite) TestDecodeInvalidHeaders(c *C) {
   148  
   149  	encoded := "type: account-key\n" +
   150  		"authority-id: canonical\n" +
   151  		"account-id: acc-id1\n" +
   152  		"name: default\n" +
   153  		"public-key-sha3-384: " + aks.keyID + "\n" +
   154  		aks.sinceLine +
   155  		aks.untilLine +
   156  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   157  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   158  		aks.pubKeyBody + "\n\n" +
   159  		"AXNpZw=="
   160  
   161  	untilPast := aks.since.AddDate(-1, 0, 0)
   162  	untilPastLine := "until: " + untilPast.Format(time.RFC3339) + "\n"
   163  
   164  	invalidHeaderTests := []struct{ original, invalid, expectedErr string }{
   165  		{"account-id: acc-id1\n", "", `"account-id" header is mandatory`},
   166  		{"account-id: acc-id1\n", "account-id: \n", `"account-id" header should not be empty`},
   167  		// XXX: enable this once name is mandatory
   168  		// {"name: default\n", "", `"name" header is mandatory`},
   169  		{"name: default\n", "name: \n", `"name" header should not be empty`},
   170  		{"name: default\n", "name: a b\n", `"name" header contains invalid characters: "a b"`},
   171  		{"name: default\n", "name: -default\n", `"name" header contains invalid characters: "-default"`},
   172  		{"name: default\n", "name: foo:bar\n", `"name" header contains invalid characters: "foo:bar"`},
   173  		{"name: default\n", "name: a--b\n", `"name" header contains invalid characters: "a--b"`},
   174  		{"name: default\n", "name: 42\n", `"name" header contains invalid characters: "42"`},
   175  		{"public-key-sha3-384: " + aks.keyID + "\n", "", `"public-key-sha3-384" header is mandatory`},
   176  		{"public-key-sha3-384: " + aks.keyID + "\n", "public-key-sha3-384: \n", `"public-key-sha3-384" header should not be empty`},
   177  		{aks.sinceLine, "", `"since" header is mandatory`},
   178  		{aks.sinceLine, "since: \n", `"since" header should not be empty`},
   179  		{aks.sinceLine, "since: 12:30\n", `"since" header is not a RFC3339 date: .*`},
   180  		{aks.sinceLine, "since: \n", `"since" header should not be empty`},
   181  		{aks.untilLine, "until: \n", `"until" header is not a RFC3339 date: .*`},
   182  		{aks.untilLine, "until: 12:30\n", `"until" header is not a RFC3339 date: .*`},
   183  		{aks.untilLine, untilPastLine, `'until' time cannot be before 'since' time`},
   184  	}
   185  
   186  	for _, test := range invalidHeaderTests {
   187  		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
   188  		_, err := asserts.Decode([]byte(invalid))
   189  		c.Check(err, ErrorMatches, accKeyErrPrefix+test.expectedErr)
   190  	}
   191  }
   192  
   193  func (aks *accountKeySuite) TestDecodeInvalidPublicKey(c *C) {
   194  	headers := "type: account-key\n" +
   195  		"authority-id: canonical\n" +
   196  		"account-id: acc-id1\n" +
   197  		"name: default\n" +
   198  		"public-key-sha3-384: " + aks.keyID + "\n" +
   199  		aks.sinceLine +
   200  		aks.untilLine
   201  
   202  	raw, err := base64.StdEncoding.DecodeString(aks.pubKeyBody)
   203  	c.Assert(err, IsNil)
   204  	spurious := base64.StdEncoding.EncodeToString(append(raw, "gorp"...))
   205  
   206  	invalidPublicKeyTests := []struct{ body, expectedErr string }{
   207  		{"", "cannot decode public key: no data"},
   208  		{"==", "cannot decode public key: .*"},
   209  		{"stuff", "cannot decode public key: .*"},
   210  		{"AnNpZw==", "unsupported public key format version: 2"},
   211  		{"AUJST0tFTg==", "cannot decode public key: .*"},
   212  		{spurious, "public key has spurious trailing data"},
   213  	}
   214  
   215  	for _, test := range invalidPublicKeyTests {
   216  		invalid := headers +
   217  			fmt.Sprintf("body-length: %v", len(test.body)) + "\n" +
   218  			"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   219  			test.body + "\n\n" +
   220  			"AXNpZw=="
   221  
   222  		_, err := asserts.Decode([]byte(invalid))
   223  		c.Check(err, ErrorMatches, accKeyErrPrefix+test.expectedErr)
   224  	}
   225  }
   226  
   227  func (aks *accountKeySuite) TestDecodeKeyIDMismatch(c *C) {
   228  	invalid := "type: account-key\n" +
   229  		"authority-id: canonical\n" +
   230  		"account-id: acc-id1\n" +
   231  		"name: default\n" +
   232  		"public-key-sha3-384: aa\n" +
   233  		aks.sinceLine +
   234  		aks.untilLine +
   235  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   236  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   237  		aks.pubKeyBody + "\n\n" +
   238  		"AXNpZw=="
   239  
   240  	_, err := asserts.Decode([]byte(invalid))
   241  	c.Check(err, ErrorMatches, accKeyErrPrefix+"public key does not match provided key id")
   242  }
   243  
   244  func (aks *accountKeySuite) openDB(c *C) *asserts.Database {
   245  	trustedKey := testPrivKey0
   246  
   247  	topDir := filepath.Join(c.MkDir(), "asserts-db")
   248  	bs, err := asserts.OpenFSBackstore(topDir)
   249  	c.Assert(err, IsNil)
   250  	cfg := &asserts.DatabaseConfig{
   251  		Backstore: bs,
   252  		Trusted: []asserts.Assertion{
   253  			asserts.BootstrapAccountForTest("canonical"),
   254  			asserts.BootstrapAccountKeyForTest("canonical", trustedKey.PublicKey()),
   255  		},
   256  	}
   257  	db, err := asserts.OpenDatabase(cfg)
   258  	c.Assert(err, IsNil)
   259  	return db
   260  }
   261  
   262  func (aks *accountKeySuite) prereqAccount(c *C, db *asserts.Database) {
   263  	trustedKey := testPrivKey0
   264  
   265  	headers := map[string]interface{}{
   266  		"authority-id": "canonical",
   267  		"display-name": "Acct1",
   268  		"account-id":   "acc-id1",
   269  		"username":     "acc-id1",
   270  		"validation":   "unproven",
   271  		"timestamp":    aks.since.Format(time.RFC3339),
   272  	}
   273  	acct1, err := asserts.AssembleAndSignInTest(asserts.AccountType, headers, nil, trustedKey)
   274  	c.Assert(err, IsNil)
   275  
   276  	// prereq
   277  	db.Add(acct1)
   278  }
   279  
   280  func (aks *accountKeySuite) TestAccountKeyCheck(c *C) {
   281  	trustedKey := testPrivKey0
   282  
   283  	headers := map[string]interface{}{
   284  		"authority-id":        "canonical",
   285  		"account-id":          "acc-id1",
   286  		"name":                "default",
   287  		"public-key-sha3-384": aks.keyID,
   288  		"since":               aks.since.Format(time.RFC3339),
   289  		"until":               aks.until.Format(time.RFC3339),
   290  	}
   291  	accKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), trustedKey)
   292  	c.Assert(err, IsNil)
   293  
   294  	db := aks.openDB(c)
   295  
   296  	aks.prereqAccount(c, db)
   297  
   298  	err = db.Check(accKey)
   299  	c.Assert(err, IsNil)
   300  }
   301  
   302  func (aks *accountKeySuite) TestAccountKeyCheckNoAccount(c *C) {
   303  	trustedKey := testPrivKey0
   304  
   305  	headers := map[string]interface{}{
   306  		"authority-id":        "canonical",
   307  		"account-id":          "acc-id1",
   308  		"name":                "default",
   309  		"public-key-sha3-384": aks.keyID,
   310  		"since":               aks.since.Format(time.RFC3339),
   311  		"until":               aks.until.Format(time.RFC3339),
   312  	}
   313  	accKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), trustedKey)
   314  	c.Assert(err, IsNil)
   315  
   316  	db := aks.openDB(c)
   317  
   318  	err = db.Check(accKey)
   319  	c.Assert(err, ErrorMatches, `account-key assertion for "acc-id1" does not have a matching account assertion`)
   320  }
   321  
   322  func (aks *accountKeySuite) TestAccountKeyCheckUntrustedAuthority(c *C) {
   323  	trustedKey := testPrivKey0
   324  
   325  	db := aks.openDB(c)
   326  	storeDB := assertstest.NewSigningDB("canonical", trustedKey)
   327  	otherDB := setup3rdPartySigning(c, "other", storeDB, db)
   328  
   329  	headers := map[string]interface{}{
   330  		"account-id":          "acc-id1",
   331  		"name":                "default",
   332  		"public-key-sha3-384": aks.keyID,
   333  		"since":               aks.since.Format(time.RFC3339),
   334  		"until":               aks.until.Format(time.RFC3339),
   335  	}
   336  	accKey, err := otherDB.Sign(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), "")
   337  	c.Assert(err, IsNil)
   338  
   339  	err = db.Check(accKey)
   340  	c.Assert(err, ErrorMatches, `account-key assertion for "acc-id1" is not signed by a directly trusted authority:.*`)
   341  }
   342  
   343  func (aks *accountKeySuite) TestAccountKeyCheckSameNameAndNewRevision(c *C) {
   344  	trustedKey := testPrivKey0
   345  
   346  	headers := map[string]interface{}{
   347  		"authority-id":        "canonical",
   348  		"account-id":          "acc-id1",
   349  		"name":                "default",
   350  		"public-key-sha3-384": aks.keyID,
   351  		"since":               aks.since.Format(time.RFC3339),
   352  		"until":               aks.until.Format(time.RFC3339),
   353  	}
   354  	accKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), trustedKey)
   355  	c.Assert(err, IsNil)
   356  
   357  	db := aks.openDB(c)
   358  	aks.prereqAccount(c, db)
   359  
   360  	err = db.Add(accKey)
   361  	c.Assert(err, IsNil)
   362  
   363  	headers["revision"] = "1"
   364  	newAccKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), trustedKey)
   365  	c.Assert(err, IsNil)
   366  
   367  	err = db.Check(newAccKey)
   368  	c.Assert(err, IsNil)
   369  }
   370  
   371  func (aks *accountKeySuite) TestAccountKeyCheckSameAccountAndDifferentName(c *C) {
   372  	trustedKey := testPrivKey0
   373  
   374  	headers := map[string]interface{}{
   375  		"authority-id":        "canonical",
   376  		"account-id":          "acc-id1",
   377  		"name":                "default",
   378  		"public-key-sha3-384": aks.keyID,
   379  		"since":               aks.since.Format(time.RFC3339),
   380  		"until":               aks.until.Format(time.RFC3339),
   381  	}
   382  	accKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), trustedKey)
   383  	c.Assert(err, IsNil)
   384  
   385  	db := aks.openDB(c)
   386  	aks.prereqAccount(c, db)
   387  
   388  	err = db.Add(accKey)
   389  	c.Assert(err, IsNil)
   390  
   391  	newPrivKey, _ := assertstest.GenerateKey(752)
   392  	err = db.ImportKey(newPrivKey)
   393  	c.Assert(err, IsNil)
   394  	newPubKey, err := db.PublicKey(newPrivKey.PublicKey().ID())
   395  	c.Assert(err, IsNil)
   396  	newPubKeyEncoded, err := asserts.EncodePublicKey(newPubKey)
   397  	c.Assert(err, IsNil)
   398  
   399  	headers["name"] = "another"
   400  	headers["public-key-sha3-384"] = newPubKey.ID()
   401  	newAccKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, newPubKeyEncoded, trustedKey)
   402  	c.Assert(err, IsNil)
   403  
   404  	err = db.Check(newAccKey)
   405  	c.Assert(err, IsNil)
   406  }
   407  
   408  func (aks *accountKeySuite) TestAccountKeyCheckSameNameAndDifferentAccount(c *C) {
   409  	trustedKey := testPrivKey0
   410  
   411  	headers := map[string]interface{}{
   412  		"authority-id":        "canonical",
   413  		"account-id":          "acc-id1",
   414  		"name":                "default",
   415  		"public-key-sha3-384": aks.keyID,
   416  		"since":               aks.since.Format(time.RFC3339),
   417  		"until":               aks.until.Format(time.RFC3339),
   418  	}
   419  	accKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), trustedKey)
   420  	c.Assert(err, IsNil)
   421  
   422  	db := aks.openDB(c)
   423  	err = db.ImportKey(trustedKey)
   424  	c.Assert(err, IsNil)
   425  	aks.prereqAccount(c, db)
   426  
   427  	err = db.Add(accKey)
   428  	c.Assert(err, IsNil)
   429  
   430  	newPrivKey, _ := assertstest.GenerateKey(752)
   431  	err = db.ImportKey(newPrivKey)
   432  	c.Assert(err, IsNil)
   433  	newPubKey, err := db.PublicKey(newPrivKey.PublicKey().ID())
   434  	c.Assert(err, IsNil)
   435  	newPubKeyEncoded, err := asserts.EncodePublicKey(newPubKey)
   436  	c.Assert(err, IsNil)
   437  
   438  	acct2 := assertstest.NewAccount(db, "acc-id2", map[string]interface{}{
   439  		"authority-id": "canonical",
   440  		"account-id":   "acc-id2",
   441  	}, trustedKey.PublicKey().ID())
   442  	db.Add(acct2)
   443  
   444  	headers["account-id"] = "acc-id2"
   445  	headers["public-key-sha3-384"] = newPubKey.ID()
   446  	headers["revision"] = "1"
   447  	newAccKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, newPubKeyEncoded, trustedKey)
   448  	c.Assert(err, IsNil)
   449  
   450  	err = db.Check(newAccKey)
   451  	c.Assert(err, IsNil)
   452  }
   453  
   454  func (aks *accountKeySuite) TestAccountKeyCheckNameClash(c *C) {
   455  	trustedKey := testPrivKey0
   456  
   457  	headers := map[string]interface{}{
   458  		"authority-id":        "canonical",
   459  		"account-id":          "acc-id1",
   460  		"name":                "default",
   461  		"public-key-sha3-384": aks.keyID,
   462  		"since":               aks.since.Format(time.RFC3339),
   463  		"until":               aks.until.Format(time.RFC3339),
   464  	}
   465  	accKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), trustedKey)
   466  	c.Assert(err, IsNil)
   467  
   468  	db := aks.openDB(c)
   469  	aks.prereqAccount(c, db)
   470  
   471  	err = db.Add(accKey)
   472  	c.Assert(err, IsNil)
   473  
   474  	newPrivKey, _ := assertstest.GenerateKey(752)
   475  	err = db.ImportKey(newPrivKey)
   476  	c.Assert(err, IsNil)
   477  	newPubKey, err := db.PublicKey(newPrivKey.PublicKey().ID())
   478  	c.Assert(err, IsNil)
   479  	newPubKeyEncoded, err := asserts.EncodePublicKey(newPubKey)
   480  	c.Assert(err, IsNil)
   481  
   482  	headers["public-key-sha3-384"] = newPubKey.ID()
   483  	headers["revision"] = "1"
   484  	newAccKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, newPubKeyEncoded, trustedKey)
   485  	c.Assert(err, IsNil)
   486  
   487  	err = db.Check(newAccKey)
   488  	c.Assert(err, ErrorMatches, fmt.Sprintf(`account-key assertion for "acc-id1" with ID %q has the same name "default" as existing ID %q`, newPubKey.ID(), aks.keyID))
   489  }
   490  
   491  func (aks *accountKeySuite) TestAccountKeyAddAndFind(c *C) {
   492  	trustedKey := testPrivKey0
   493  
   494  	headers := map[string]interface{}{
   495  		"authority-id":        "canonical",
   496  		"account-id":          "acc-id1",
   497  		"name":                "default",
   498  		"public-key-sha3-384": aks.keyID,
   499  		"since":               aks.since.Format(time.RFC3339),
   500  		"until":               aks.until.Format(time.RFC3339),
   501  	}
   502  	accKey, err := asserts.AssembleAndSignInTest(asserts.AccountKeyType, headers, []byte(aks.pubKeyBody), trustedKey)
   503  	c.Assert(err, IsNil)
   504  
   505  	db := aks.openDB(c)
   506  
   507  	aks.prereqAccount(c, db)
   508  
   509  	err = db.Add(accKey)
   510  	c.Assert(err, IsNil)
   511  
   512  	found, err := db.Find(asserts.AccountKeyType, map[string]string{
   513  		"account-id":          "acc-id1",
   514  		"public-key-sha3-384": aks.keyID,
   515  	})
   516  	c.Assert(err, IsNil)
   517  	c.Assert(found, NotNil)
   518  	c.Check(found.Body(), DeepEquals, []byte(aks.pubKeyBody))
   519  }
   520  
   521  func (aks *accountKeySuite) TestPublicKeyIsValidAt(c *C) {
   522  	// With since and until, i.e. signing account-key expires.
   523  	encoded := "type: account-key\n" +
   524  		"authority-id: canonical\n" +
   525  		"account-id: acc-id1\n" +
   526  		"name: default\n" +
   527  		"public-key-sha3-384: " + aks.keyID + "\n" +
   528  		aks.sinceLine +
   529  		aks.untilLine +
   530  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   531  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   532  		aks.pubKeyBody + "\n\n" +
   533  		"AXNpZw=="
   534  	a, err := asserts.Decode([]byte(encoded))
   535  	c.Assert(err, IsNil)
   536  
   537  	accKey := a.(*asserts.AccountKey)
   538  
   539  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since), Equals, true)
   540  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since.AddDate(0, 0, -1)), Equals, false)
   541  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since.AddDate(0, 0, 1)), Equals, true)
   542  
   543  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.until), Equals, false)
   544  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.until.AddDate(0, -1, 0)), Equals, true)
   545  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.until.AddDate(0, 1, 0)), Equals, false)
   546  
   547  	// With no until, i.e. signing account-key never expires.
   548  	encoded = "type: account-key\n" +
   549  		"authority-id: canonical\n" +
   550  		"account-id: acc-id1\n" +
   551  		"name: default\n" +
   552  		"public-key-sha3-384: " + aks.keyID + "\n" +
   553  		aks.sinceLine +
   554  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   555  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   556  		aks.pubKeyBody + "\n\n" +
   557  		"openpgp c2ln"
   558  	a, err = asserts.Decode([]byte(encoded))
   559  	c.Assert(err, IsNil)
   560  
   561  	accKey = a.(*asserts.AccountKey)
   562  
   563  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since), Equals, true)
   564  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since.AddDate(0, 0, -1)), Equals, false)
   565  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since.AddDate(0, 0, 1)), Equals, true)
   566  
   567  	// With since == until, i.e. signing account-key has been revoked.
   568  	encoded = "type: account-key\n" +
   569  		"authority-id: canonical\n" +
   570  		"account-id: acc-id1\n" +
   571  		"name: default\n" +
   572  		"public-key-sha3-384: " + aks.keyID + "\n" +
   573  		aks.sinceLine +
   574  		"until: " + aks.since.Format(time.RFC3339) + "\n" +
   575  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   576  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   577  		aks.pubKeyBody + "\n\n" +
   578  		"openpgp c2ln"
   579  	a, err = asserts.Decode([]byte(encoded))
   580  	c.Assert(err, IsNil)
   581  
   582  	accKey = a.(*asserts.AccountKey)
   583  
   584  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since), Equals, false)
   585  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since.AddDate(0, 0, -1)), Equals, false)
   586  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.since.AddDate(0, 0, 1)), Equals, false)
   587  
   588  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.until), Equals, false)
   589  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.until.AddDate(0, -1, 0)), Equals, false)
   590  	c.Check(asserts.AccountKeyIsKeyValidAt(accKey, aks.until.AddDate(0, 1, 0)), Equals, false)
   591  }
   592  
   593  func (aks *accountKeySuite) TestPublicKeyIsValidAssumingCurTimeWithinWithUntilPunctual(c *C) {
   594  	// With since and until, i.e. signing account-key expires.
   595  	// Key is valid over [since, until)
   596  	encoded := "type: account-key\n" +
   597  		"authority-id: canonical\n" +
   598  		"account-id: acc-id1\n" +
   599  		"name: default\n" +
   600  		"public-key-sha3-384: " + aks.keyID + "\n" +
   601  		aks.sinceLine +
   602  		aks.untilLine +
   603  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   604  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   605  		aks.pubKeyBody + "\n\n" +
   606  		"AXNpZw=="
   607  	a, err := asserts.Decode([]byte(encoded))
   608  	c.Assert(err, IsNil)
   609  
   610  	accKey := a.(*asserts.AccountKey)
   611  
   612  	tests := []struct {
   613  		timePt time.Time
   614  		valid  bool
   615  	}{
   616  		{aks.since, true},
   617  		{aks.since.AddDate(0, 3, 0), true},
   618  		{aks.since.AddDate(0, -2, 0), false},
   619  		{aks.until, false},
   620  		{aks.until.AddDate(0, 3, 0), false},
   621  		{aks.until.AddDate(0, -2, 0), true},
   622  	}
   623  
   624  	for _, t := range tests {
   625  		c.Check(asserts.AccountKeyIsKeyValidAssumingCurTimeWithin(accKey, t.timePt, t.timePt), Equals, t.valid)
   626  	}
   627  }
   628  
   629  func (aks *accountKeySuite) TestPublicKeyIsValidAssumingCurTimeWithinNoUntilPunctual(c *C) {
   630  	// With since but no until, i.e. signing account-key never expires.
   631  	// Key is valid for time >= since.
   632  	encoded := "type: account-key\n" +
   633  		"authority-id: canonical\n" +
   634  		"account-id: acc-id1\n" +
   635  		"name: default\n" +
   636  		"public-key-sha3-384: " + aks.keyID + "\n" +
   637  		aks.sinceLine +
   638  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   639  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   640  		aks.pubKeyBody + "\n\n" +
   641  		"AXNpZw=="
   642  	a, err := asserts.Decode([]byte(encoded))
   643  	c.Assert(err, IsNil)
   644  
   645  	accKey := a.(*asserts.AccountKey)
   646  
   647  	later := aks.until
   648  	tests := []struct {
   649  		timePt time.Time
   650  		valid  bool
   651  	}{
   652  		{aks.since, true},
   653  		{aks.since.AddDate(0, 3, 0), true},
   654  		{aks.since.AddDate(0, -2, 0), false},
   655  		{later, true},
   656  		{later.AddDate(0, 3, 0), true},
   657  	}
   658  
   659  	for _, t := range tests {
   660  		c.Check(asserts.AccountKeyIsKeyValidAssumingCurTimeWithin(accKey, t.timePt, t.timePt), Equals, t.valid)
   661  	}
   662  }
   663  
   664  func (aks *accountKeySuite) TestPublicKeyIsValidAssumingCurTimeWithinWithUntilInterval(c *C) {
   665  	// With since and until, i.e. signing account-key expires.
   666  	// Key is valid over [since, until)
   667  	encoded := "type: account-key\n" +
   668  		"authority-id: canonical\n" +
   669  		"account-id: acc-id1\n" +
   670  		"name: default\n" +
   671  		"public-key-sha3-384: " + aks.keyID + "\n" +
   672  		aks.sinceLine +
   673  		aks.untilLine +
   674  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   675  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   676  		aks.pubKeyBody + "\n\n" +
   677  		"AXNpZw=="
   678  	a, err := asserts.Decode([]byte(encoded))
   679  	c.Assert(err, IsNil)
   680  
   681  	accKey := a.(*asserts.AccountKey)
   682  
   683  	z := time.Time{}
   684  
   685  	tests := []struct {
   686  		earliest time.Time
   687  		latest   time.Time
   688  		valid    bool
   689  	}{
   690  		{aks.since, aks.until, true},
   691  		{aks.since, aks.since.AddDate(0, 3, 0), true},
   692  		{aks.since.AddDate(0, 1, 0), aks.since.AddDate(0, 3, 0), true},
   693  		{aks.since.AddDate(0, 1, 0), aks.until, true},
   694  		{aks.until, aks.until.AddDate(0, 3, 0), false},
   695  		{aks.until.AddDate(0, 2, 0), aks.until.AddDate(0, 3, 0), false},
   696  		{aks.since.AddDate(0, -1, 0), aks.since, true},
   697  		{aks.since.AddDate(0, -1, 0), aks.since.AddDate(0, 1, 0), true},
   698  		{aks.since.AddDate(0, -2, 0), aks.since.AddDate(0, -2, 0), false},
   699  		{aks.until.AddDate(0, -1, 0), aks.until.AddDate(0, 1, 0), true},
   700  		{aks.since, z, true},
   701  		{aks.since.AddDate(0, 1, 0), z, true},
   702  		{aks.since.AddDate(0, -3, 0), z, true},
   703  		{aks.until, z, false},
   704  		{aks.until.AddDate(0, 1, 0), z, false},
   705  		// with earliest set to time.Time zero
   706  		{z, aks.since, true},
   707  		{z, aks.since.AddDate(0, 1, 0), true},
   708  		{z, aks.since.AddDate(0, -2, 0), false},
   709  		{z, aks.until.AddDate(0, 1, 0), true},
   710  		{z, z, true},
   711  	}
   712  
   713  	for _, t := range tests {
   714  		c.Check(asserts.AccountKeyIsKeyValidAssumingCurTimeWithin(accKey, t.earliest, t.latest), Equals, t.valid)
   715  	}
   716  
   717  }
   718  
   719  func (aks *accountKeySuite) TestPublicKeyIsValidAssumingCurTimeWithinNoUntilInterval(c *C) {
   720  	// With since but no until, i.e. signing account-key never expires.
   721  	// Key is valid for time >= since.
   722  	encoded := "type: account-key\n" +
   723  		"authority-id: canonical\n" +
   724  		"account-id: acc-id1\n" +
   725  		"name: default\n" +
   726  		"public-key-sha3-384: " + aks.keyID + "\n" +
   727  		aks.sinceLine +
   728  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   729  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   730  		aks.pubKeyBody + "\n\n" +
   731  		"AXNpZw=="
   732  	a, err := asserts.Decode([]byte(encoded))
   733  	c.Assert(err, IsNil)
   734  
   735  	accKey := a.(*asserts.AccountKey)
   736  
   737  	z := time.Time{}
   738  	later := aks.until
   739  
   740  	tests := []struct {
   741  		earliest time.Time
   742  		latest   time.Time
   743  		valid    bool
   744  	}{
   745  		{aks.since, later, true},
   746  		{aks.since, aks.since.AddDate(0, 3, 0), true},
   747  		{aks.since.AddDate(0, 1, 0), aks.since.AddDate(0, 3, 0), true},
   748  		{aks.since.AddDate(0, 1, 0), later, true},
   749  		{later, later.AddDate(0, 3, 0), true},
   750  		{later.AddDate(0, 2, 0), later.AddDate(0, 3, 0), true},
   751  		{aks.since.AddDate(0, -1, 0), aks.since, true},
   752  		{aks.since.AddDate(0, -1, 0), aks.since.AddDate(0, 1, 0), true},
   753  		{aks.since.AddDate(0, -2, 0), aks.since.AddDate(0, -2, 0), false},
   754  		{later.AddDate(0, -1, 0), later.AddDate(0, 1, 0), true},
   755  		{aks.since, z, true},
   756  		{aks.since.AddDate(0, 1, 0), z, true},
   757  		{aks.since.AddDate(0, -3, 0), z, true},
   758  		{later, z, true},
   759  		{later.AddDate(0, 1, 0), z, true},
   760  		// with earliest set to time.Time zero
   761  		{z, aks.since, true},
   762  		{z, aks.since.AddDate(0, 1, 0), true},
   763  		{z, aks.since.AddDate(0, -2, 0), false},
   764  		{z, later.AddDate(0, 1, 0), true},
   765  		{z, z, true},
   766  	}
   767  
   768  	for _, t := range tests {
   769  		c.Check(asserts.AccountKeyIsKeyValidAssumingCurTimeWithin(accKey, t.earliest, t.latest), Equals, t.valid)
   770  	}
   771  
   772  }
   773  
   774  func (aks *accountKeySuite) TestPrerequisites(c *C) {
   775  	encoded := "type: account-key\n" +
   776  		"authority-id: canonical\n" +
   777  		"account-id: acc-id1\n" +
   778  		"name: default\n" +
   779  		"public-key-sha3-384: " + aks.keyID + "\n" +
   780  		aks.sinceLine +
   781  		aks.untilLine +
   782  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   783  		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
   784  		aks.pubKeyBody + "\n\n" +
   785  		"AXNpZw=="
   786  	a, err := asserts.Decode([]byte(encoded))
   787  	c.Assert(err, IsNil)
   788  
   789  	prereqs := a.Prerequisites()
   790  	c.Assert(prereqs, HasLen, 1)
   791  	c.Check(prereqs[0], DeepEquals, &asserts.Ref{
   792  		Type:       asserts.AccountType,
   793  		PrimaryKey: []string{"acc-id1"},
   794  	})
   795  }
   796  
   797  func (aks *accountKeySuite) TestAccountKeyRequestHappy(c *C) {
   798  	akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType,
   799  		map[string]interface{}{
   800  			"account-id":          "acc-id1",
   801  			"name":                "default",
   802  			"public-key-sha3-384": aks.keyID,
   803  			"since":               aks.since.Format(time.RFC3339),
   804  		}, []byte(aks.pubKeyBody), aks.privKey)
   805  	c.Assert(err, IsNil)
   806  
   807  	// roundtrip
   808  	a, err := asserts.Decode(asserts.Encode(akr))
   809  	c.Assert(err, IsNil)
   810  
   811  	akr2, ok := a.(*asserts.AccountKeyRequest)
   812  	c.Assert(ok, Equals, true)
   813  
   814  	db := aks.openDB(c)
   815  	aks.prereqAccount(c, db)
   816  
   817  	err = db.Check(akr2)
   818  	c.Check(err, IsNil)
   819  
   820  	c.Check(akr2.AccountID(), Equals, "acc-id1")
   821  	c.Check(akr2.Name(), Equals, "default")
   822  	c.Check(akr2.PublicKeyID(), Equals, aks.keyID)
   823  	c.Check(akr2.Since(), Equals, aks.since)
   824  }
   825  
   826  func (aks *accountKeySuite) TestAccountKeyRequestUntil(c *C) {
   827  	db := aks.openDB(c)
   828  	aks.prereqAccount(c, db)
   829  
   830  	tests := []struct {
   831  		untilHeader string
   832  		until       time.Time
   833  	}{
   834  		{"", time.Time{}}, // zero time default
   835  		{aks.until.Format(time.RFC3339), aks.until}, // in the future
   836  		{aks.since.Format(time.RFC3339), aks.since}, // same as since
   837  	}
   838  
   839  	for _, test := range tests {
   840  		c.Log(test)
   841  		headers := map[string]interface{}{
   842  			"account-id":          "acc-id1",
   843  			"name":                "default",
   844  			"public-key-sha3-384": aks.keyID,
   845  			"since":               aks.since.Format(time.RFC3339),
   846  		}
   847  		if test.untilHeader != "" {
   848  			headers["until"] = test.untilHeader
   849  		}
   850  		akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType, headers, []byte(aks.pubKeyBody), aks.privKey)
   851  		c.Assert(err, IsNil)
   852  		a, err := asserts.Decode(asserts.Encode(akr))
   853  		c.Assert(err, IsNil)
   854  		akr2 := a.(*asserts.AccountKeyRequest)
   855  		c.Check(akr2.Until(), Equals, test.until)
   856  		err = db.Check(akr2)
   857  		c.Check(err, IsNil)
   858  	}
   859  }
   860  
   861  func (aks *accountKeySuite) TestAccountKeyRequestAddAndFind(c *C) {
   862  	akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType,
   863  		map[string]interface{}{
   864  			"account-id":          "acc-id1",
   865  			"name":                "default",
   866  			"public-key-sha3-384": aks.keyID,
   867  			"since":               aks.since.Format(time.RFC3339),
   868  		}, []byte(aks.pubKeyBody), aks.privKey)
   869  	c.Assert(err, IsNil)
   870  
   871  	db := aks.openDB(c)
   872  	aks.prereqAccount(c, db)
   873  
   874  	err = db.Add(akr)
   875  	c.Assert(err, IsNil)
   876  
   877  	found, err := db.Find(asserts.AccountKeyRequestType, map[string]string{
   878  		"account-id":          "acc-id1",
   879  		"public-key-sha3-384": aks.keyID,
   880  	})
   881  	c.Assert(err, IsNil)
   882  	c.Assert(found, NotNil)
   883  	c.Check(found.Body(), DeepEquals, []byte(aks.pubKeyBody))
   884  }
   885  
   886  func (aks *accountKeySuite) TestAccountKeyRequestDecodeInvalid(c *C) {
   887  	encoded := "type: account-key-request\n" +
   888  		"account-id: acc-id1\n" +
   889  		"name: default\n" +
   890  		"public-key-sha3-384: " + aks.keyID + "\n" +
   891  		aks.sinceLine +
   892  		aks.untilLine +
   893  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   894  		"sign-key-sha3-384: " + aks.privKey.PublicKey().ID() + "\n\n" +
   895  		aks.pubKeyBody + "\n\n" +
   896  		"AXNpZw=="
   897  
   898  	untilPast := aks.since.AddDate(-1, 0, 0)
   899  	untilPastLine := "until: " + untilPast.Format(time.RFC3339) + "\n"
   900  
   901  	invalidTests := []struct{ original, invalid, expectedErr string }{
   902  		{"account-id: acc-id1\n", "", `"account-id" header is mandatory`},
   903  		{"account-id: acc-id1\n", "account-id: \n", `"account-id" header should not be empty`},
   904  		{"name: default\n", "", `"name" header is mandatory`},
   905  		{"name: default\n", "name: \n", `"name" header should not be empty`},
   906  		{"name: default\n", "name: a b\n", `"name" header contains invalid characters: "a b"`},
   907  		{"name: default\n", "name: -default\n", `"name" header contains invalid characters: "-default"`},
   908  		{"name: default\n", "name: foo:bar\n", `"name" header contains invalid characters: "foo:bar"`},
   909  		{"public-key-sha3-384: " + aks.keyID + "\n", "", `"public-key-sha3-384" header is mandatory`},
   910  		{"public-key-sha3-384: " + aks.keyID + "\n", "public-key-sha3-384: \n", `"public-key-sha3-384" header should not be empty`},
   911  		{aks.sinceLine, "", `"since" header is mandatory`},
   912  		{aks.sinceLine, "since: \n", `"since" header should not be empty`},
   913  		{aks.sinceLine, "since: 12:30\n", `"since" header is not a RFC3339 date: .*`},
   914  		{aks.sinceLine, "since: \n", `"since" header should not be empty`},
   915  		{aks.untilLine, "until: \n", `"until" header is not a RFC3339 date: .*`},
   916  		{aks.untilLine, "until: 12:30\n", `"until" header is not a RFC3339 date: .*`},
   917  		{aks.untilLine, untilPastLine, `'until' time cannot be before 'since' time`},
   918  	}
   919  
   920  	for _, test := range invalidTests {
   921  		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
   922  		_, err := asserts.Decode([]byte(invalid))
   923  		c.Check(err, ErrorMatches, accKeyReqErrPrefix+test.expectedErr)
   924  	}
   925  }
   926  
   927  func (aks *accountKeySuite) TestAccountKeyRequestDecodeInvalidPublicKey(c *C) {
   928  	headers := "type: account-key-request\n" +
   929  		"account-id: acc-id1\n" +
   930  		"name: default\n" +
   931  		"public-key-sha3-384: " + aks.keyID + "\n" +
   932  		aks.sinceLine +
   933  		aks.untilLine
   934  
   935  	raw, err := base64.StdEncoding.DecodeString(aks.pubKeyBody)
   936  	c.Assert(err, IsNil)
   937  	spurious := base64.StdEncoding.EncodeToString(append(raw, "gorp"...))
   938  
   939  	invalidPublicKeyTests := []struct{ body, expectedErr string }{
   940  		{"", "cannot decode public key: no data"},
   941  		{"==", "cannot decode public key: .*"},
   942  		{"stuff", "cannot decode public key: .*"},
   943  		{"AnNpZw==", "unsupported public key format version: 2"},
   944  		{"AUJST0tFTg==", "cannot decode public key: .*"},
   945  		{spurious, "public key has spurious trailing data"},
   946  	}
   947  
   948  	for _, test := range invalidPublicKeyTests {
   949  		invalid := headers +
   950  			fmt.Sprintf("body-length: %v", len(test.body)) + "\n" +
   951  			"sign-key-sha3-384: " + aks.privKey.PublicKey().ID() + "\n\n" +
   952  			test.body + "\n\n" +
   953  			"AXNpZw=="
   954  
   955  		_, err := asserts.Decode([]byte(invalid))
   956  		c.Check(err, ErrorMatches, accKeyReqErrPrefix+test.expectedErr)
   957  	}
   958  }
   959  
   960  func (aks *accountKeySuite) TestAccountKeyRequestDecodeKeyIDMismatch(c *C) {
   961  	invalid := "type: account-key-request\n" +
   962  		"account-id: acc-id1\n" +
   963  		"name: default\n" +
   964  		"public-key-sha3-384: aa\n" +
   965  		aks.sinceLine +
   966  		aks.untilLine +
   967  		fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
   968  		"sign-key-sha3-384: " + aks.privKey.PublicKey().ID() + "\n\n" +
   969  		aks.pubKeyBody + "\n\n" +
   970  		"AXNpZw=="
   971  
   972  	_, err := asserts.Decode([]byte(invalid))
   973  	c.Check(err, ErrorMatches, "assertion account-key-request: public key does not match provided key id")
   974  }
   975  
   976  func (aks *accountKeySuite) TestAccountKeyRequestNoAccount(c *C) {
   977  	headers := map[string]interface{}{
   978  		"account-id":          "acc-id1",
   979  		"name":                "default",
   980  		"public-key-sha3-384": aks.keyID,
   981  		"since":               aks.since.Format(time.RFC3339),
   982  	}
   983  	akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType, headers, []byte(aks.pubKeyBody), aks.privKey)
   984  	c.Assert(err, IsNil)
   985  
   986  	db := aks.openDB(c)
   987  
   988  	err = db.Check(akr)
   989  	c.Assert(err, ErrorMatches, `account-key-request assertion for "acc-id1" does not have a matching account assertion`)
   990  }