mirror of https://github.com/docker/docs.git
commit
cab1006568
|
@ -47,7 +47,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/endophage/gotuf",
|
||||
"Rev": "88765abdd5ec33be6be1efa18c71d7f43c7c4983"
|
||||
"Rev": "af7152a51a0663dc47768e591ffdfa1f60e5308a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-sql-driver/mysql",
|
||||
|
|
|
@ -57,12 +57,12 @@ func (c *Client) Update() error {
|
|||
func (c *Client) update() error {
|
||||
err := c.downloadTimestamp()
|
||||
if err != nil {
|
||||
logrus.Errorf("Client Update (Timestamp): ", err.Error())
|
||||
logrus.Errorf("Client Update (Timestamp): %s", err.Error())
|
||||
return err
|
||||
}
|
||||
err = c.downloadSnapshot()
|
||||
if err != nil {
|
||||
logrus.Errorf("Client Update (Snapshot): ", err.Error())
|
||||
logrus.Errorf("Client Update (Snapshot): %s", err.Error())
|
||||
return err
|
||||
}
|
||||
err = c.checkRoot()
|
||||
|
@ -71,7 +71,7 @@ func (c *Client) update() error {
|
|||
}
|
||||
err = c.downloadTargets("targets")
|
||||
if err != nil {
|
||||
logrus.Errorf("Client Update (Targets): ", err.Error())
|
||||
logrus.Errorf("Client Update (Targets): %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
tuf "github.com/endophage/gotuf"
|
||||
"github.com/endophage/gotuf/data"
|
||||
"github.com/endophage/gotuf/keys"
|
||||
"github.com/endophage/gotuf/store"
|
||||
)
|
||||
|
||||
func TestClientUpdate(t *testing.T) {
|
||||
pypiRoot := `{
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "92db731bf30e31c13e775360453f0adc8bfd3107f5000b99431c4bdbcebb31ed",
|
||||
"method": "PyCrypto-PKCS#1 PSS",
|
||||
"sig": "31d1fa4712eaf591b367740f69ba7577fb5565863639d7e89145abe159f047d5f848e7696fbaf16f5c4214e1f2295d14e3078f5c0a6e2cbc015c13f8557836a039208970b436bb13b921f86f3e4d4518ce2f731bd7a55083d45634f206dc92e886daeb15e65a513f6451575811e9e44b5573d6999d4b69f86a27f01d0d9a868a535a1f0f6534bd9e555d4df95f019ea6859c83fca30e95e0d1c2ce1dcb2b19c91facd98a7cae9f4c81b5ff4c12980f333e38eac99f4561a8f9e5342382443f165cf0af840d5c61b62698b27413d7f5e1bdba714b98759bcfc7c3d65c567459ce093c66c88ebae836665bcdf2efc1e6921bd792406c0529dab2678a922e5fa6ef39e92f89d3072a22bd755a49b2e2e2c801ce73006fd8a7f56595fae01af3e2a49a3bce4ce9fcaec43e1aae5b0c0fc807bc4caca9fae7c34ff026a417262b5435cfd6cbf17b70aae041eae30a6bd6a857db88566c89f2c02171674b9195f22a84ec5839a4e46e2e63fbb5d4821ae66237ea261846c7d5a341d5f4ab2e12412d4e"
|
||||
}
|
||||
],
|
||||
"signed": {
|
||||
"_type": "Root",
|
||||
"expires": "2014-08-31 00:49:33 UTC",
|
||||
"keys": {
|
||||
"07f12f6c470e60d49fe6a60cd893dfba870db387083d50fe4fc43c6171a0be59": {
|
||||
"keytype": "rsa",
|
||||
"keyval": {
|
||||
"private": "",
|
||||
"public": "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAtb4vuMJF1kOc1deExdqV\nZ3o9W6zulfRDX6u8Exd3NEL0/9bCYluqpshFzgmDYpCsuS79Ve5S8WgXAnEXyWOf\nHL/FnAVqFSnmgmYr52waMYV57BsNMY8pXxOnJm1opUbt0PdnF2D2yfLLY8IgZ/0m\niJ+gWojwEBMRlTOnHFx+l/UVvZAhpVsua6C8C2ThFLrXlmmtkg5BAIm1kWPsZ0nB\n3Cczcwh8zE0l2ytVi458AuRGKwi1TMIGXl064ekjsWexH1zCuoEcv/CKob0BkL4c\nLFUKe6WD6XlEp/xnMh6lNG8LT+UKzSb1hPkTtt23RntFB4Qx7UUT8LoO79bv6coE\njeEqHltmeohHpVmTLWsbTdaX7W3clWPUErGh5kAO0SJu1EM94p5nGWlZ+kwASxtO\nz1qR8AqQ02HBBQU+cY24CNnOwKDq/Kgsg1Aw7bqglvtUwBUQkuuCuisjHI0bSMFr\ntGIhlswxItfQ709/OMrN44Vw/H/Z50UzGFtRlu1h07/vAgMBAAE=\n-----END PUBLIC KEY-----"
|
||||
}
|
||||
},
|
||||
"2d9f41a1b79429e9d950a687fe00da0bb4fd751da98aeade1524b8d28968eb89": {
|
||||
"keytype": "rsa",
|
||||
"keyval": {
|
||||
"private": "",
|
||||
"public": "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAmjt8CIbohZxZQ1+I8CQn\nvugLsGXq1G2OiMZvbN281q1/E1futll3+EnfxPLP0SBlyYxixma/ozoMj94lPyOX\nBbiF/U1WJ0Wp5D1kpT0Jzt9Ar0bkRxWoPhubeJ7D4k8Br2m7aG+wchfozdbMmUwK\n/MiAZ1fmpKQAr1ek3/hJiN/dURw+mQEdgXwgA4raDy4Ty3AkG7SDCG1cYoYYMJa3\nKg82AWISQQEHUO1MwRVBon2B5d2UriUEzsYYi+2whDOekchjgyd2xdcRvdCBbdGv\nJBCtzVZpd52lCwqAMJUyDGre6Mb6NmKC2nuk+TYEujqRQK97LnjmPwI42b4cBHqv\nDtg7Z8K3rEQIyD+VvrcWlu+1cE8drjh3y+r7oTtjRPr1M8xaCWn/dh8huSJmaFlk\nmWKDX9KI3/5pxFjgpry20eBRYkZHJWwByc9GVvwhRsIF61QdKvA6uGqkFHy9YQBW\nnzWTPo/4UTUwcpfjneoyMOVKx2K05ZePa5UNAgJVDgFfAgMBAAE=\n-----END PUBLIC KEY-----"
|
||||
}
|
||||
},
|
||||
"92db731bf30e31c13e775360453f0adc8bfd3107f5000b99431c4bdbcebb31ed": {
|
||||
"keytype": "rsa",
|
||||
"keyval": {
|
||||
"private": "",
|
||||
"public": "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEArvqUPYb6JJROPJQglPTj\n5uDrsxQKl34Mo+3pSlBVuD6puE4lDnG649a2YksJy+C8ZIPJgokn5w+C3alh+dMe\nzbdWHHxrY1h9CLpYz5cbMlE16303ubkt1rvwDqEezG0HDBzPaKj4oP9YJ9x7wbsq\ndvFcy+Qc3wWd7UWcieo6E0ihbJkYcY8chRXVLg1rL7EfZ+e3bq5+ojA2ECM5JqzZ\nzgDpqCv5hTCYYZp72MZcG7dfSPAHrcSGIrwg7whzz2UsEtCOpsJTuCl96FPN7kAu\n4w/WyM3+SPzzr4/RQXuY1SrLCFD8ebM2zHt/3ATLhPnGmyG5I0RGYoegFaZ2AViw\nlqZDOYnBtgDvKP0zakMtFMbkh2XuNBUBO7Sjs0YcZMjLkh9gYUHL1yWS3Aqus1Lw\nlI0gHS22oyGObVBWkZEgk/Foy08sECLGao+5VvhmGpfVuiz9OKFUmtPVjWzRE4ng\niekEu4drSxpH41inLGSvdByDWLpcTvWQI9nkgclh3AT/AgMBAAE=\n-----END PUBLIC KEY-----"
|
||||
}
|
||||
},
|
||||
"e1ccde549849bb6aa548412e79c407c93f303f3a3ca0ab1e5923ff7d5c4de769": {
|
||||
"keytype": "rsa",
|
||||
"keyval": {
|
||||
"private": "",
|
||||
"public": "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAqnNAzjIb73u2Nk+r2AdU\nnK+xvKDcZgIzjSzRVjtRJgu3MVffzPcGIsjv2RS8/LLl8nSf48V+tWZf/PnTzkMn\n1iJhbdOQTt6bABiizm5dLP9Jm/AIMTTUpbu+fpFbV8vNH+qM5/Z0WNOptQnOEfNs\n84MNh919lJjHc5VPTw86h68Mkn7W5RChZqnwEv75M1XfWdAnUGeLfZh6BKxFMnaB\nciYxieUvc1bnCtqsdaDE2Ab86WXM7cmNCqyLAh4JkTV+RcMzqEnZCAm68TkO6gM/\n5g4A7fbnn9Jc4O3fJvu80fYOg63nS6hAFldmN74oYu2h5PV75xyTIEERoXqJbSaj\n1Agj/98khIZGsSVjoQ5Mi7ETcSbsH7rqWdHFIu+dbKw8vlnqWnEQYjXA8CIOY3X7\nB6/u5FBS5AdxjO6AR/MuaqpWdDTZwXwgZ9c4wqO4Re4z73sGM1PugUK4dbXIGwVe\nRtzv7cSFOB7OPmj53miJWt2ILACb+Dpnxt9h6TzT1C0JAgMBAAE=\n-----END PUBLIC KEY-----"
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"release": {
|
||||
"keyids": [
|
||||
"e1ccde549849bb6aa548412e79c407c93f303f3a3ca0ab1e5923ff7d5c4de769"
|
||||
],
|
||||
"threshold": 1
|
||||
},
|
||||
"root": {
|
||||
"keyids": [
|
||||
"92db731bf30e31c13e775360453f0adc8bfd3107f5000b99431c4bdbcebb31ed"
|
||||
],
|
||||
"threshold": 1
|
||||
},
|
||||
"targets": {
|
||||
"keyids": [
|
||||
"07f12f6c470e60d49fe6a60cd893dfba870db387083d50fe4fc43c6171a0be59"
|
||||
],
|
||||
"threshold": 1
|
||||
},
|
||||
"timestamp": {
|
||||
"keyids": [
|
||||
"2d9f41a1b79429e9d950a687fe00da0bb4fd751da98aeade1524b8d28968eb89"
|
||||
],
|
||||
"threshold": 1
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
}`
|
||||
|
||||
data.SetTUFTypes(
|
||||
map[string]string{
|
||||
"snapshot": "Release",
|
||||
},
|
||||
)
|
||||
data.SetValidRoles(
|
||||
map[string]string{
|
||||
"snapshot": "release",
|
||||
},
|
||||
)
|
||||
|
||||
s := &data.Signed{}
|
||||
err := json.Unmarshal([]byte(pypiRoot), s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kdb := keys.NewDB()
|
||||
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
|
||||
// Being able to set the second argument, signer, to nil is a great
|
||||
// test as we shouldn't need to instantiate a signer just for reading
|
||||
// a repo.
|
||||
repo := tuf.NewTufRepo(kdb, nil)
|
||||
repo.SetRoot(s)
|
||||
remote, err := store.NewHTTPStore(
|
||||
"http://mirror1.poly.edu/test-pypi/",
|
||||
"metadata",
|
||||
"txt",
|
||||
"targets",
|
||||
)
|
||||
cached := store.NewFileCacheStore(remote, "/tmp/tuf")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
client := Client{
|
||||
local: repo,
|
||||
remote: cached,
|
||||
keysDB: kdb,
|
||||
}
|
||||
|
||||
err = client.Update()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testTarget := "packages/2.3/T/TracHTTPAuth/TracHTTPAuth-1.0.1-py2.3.egg"
|
||||
expectedHash := "dbcaa6dc0035a636234f9b457d24bf1aeecac0a29b4da97a3b32692f2729f9db"
|
||||
expectedSize := int64(8140)
|
||||
m := client.TargetMeta(testTarget)
|
||||
if m == nil {
|
||||
t.Fatal("Failed to find existing target")
|
||||
}
|
||||
if m.Hashes["sha256"].String() != expectedHash {
|
||||
t.Fatal("Target hash incorrect.\nExpected:", expectedHash, "\nReceived:", m.Hashes["sha256"].String())
|
||||
}
|
||||
if m.Length != expectedSize {
|
||||
t.Fatal("Target size incorrect.\nExpected:", expectedSize, "\nReceived:", m.Length)
|
||||
}
|
||||
err = client.DownloadTarget(ioutil.Discard, testTarget, m)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
45
Godeps/_workspace/src/github.com/endophage/gotuf/data/types_test.go
generated
vendored
Normal file
45
Godeps/_workspace/src/github.com/endophage/gotuf/data/types_test.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package data
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
type TypesSuite struct{}
|
||||
|
||||
var _ = Suite(&TypesSuite{})
|
||||
|
||||
func (TypesSuite) TestGenerateFileMetaDefault(c *C) {
|
||||
// default is sha512
|
||||
r := bytes.NewReader([]byte("foo"))
|
||||
meta, err := NewFileMeta(r, "sha512")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(meta.Length, Equals, int64(3))
|
||||
hashes := meta.Hashes
|
||||
c.Assert(hashes, HasLen, 1)
|
||||
hash, ok := hashes["sha512"]
|
||||
if !ok {
|
||||
c.Fatal("missing sha512 hash")
|
||||
}
|
||||
c.Assert(hash.String(), DeepEquals, "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7")
|
||||
}
|
||||
|
||||
func (TypesSuite) TestGenerateFileMetaExplicit(c *C) {
|
||||
r := bytes.NewReader([]byte("foo"))
|
||||
meta, err := NewFileMeta(r, "sha256", "sha512")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(meta.Length, Equals, int64(3))
|
||||
hashes := meta.Hashes
|
||||
c.Assert(hashes, HasLen, 2)
|
||||
for name, val := range map[string]string{
|
||||
"sha256": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
|
||||
"sha512": "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7",
|
||||
} {
|
||||
hash, ok := hashes[name]
|
||||
if !ok {
|
||||
c.Fatalf("missing %s hash", name)
|
||||
}
|
||||
c.Assert(hash.String(), DeepEquals, val)
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ func (trust *Ed25519) Sign(keyIDs []string, toSign []byte) ([]data.Signature, er
|
|||
sig := ed25519.Sign(&priv, toSign)
|
||||
signatures = append(signatures, data.Signature{
|
||||
KeyID: kID,
|
||||
Method: "ed25519",
|
||||
Method: "ED25519",
|
||||
Signature: sig[:],
|
||||
})
|
||||
}
|
||||
|
@ -50,8 +50,8 @@ func (trust *Ed25519) Create(role string) (*data.PublicKey, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
public := data.NewPublicKey("ed25519", pub[:])
|
||||
private := data.NewPrivateKey("ed25519", pub[:], priv[:])
|
||||
public := data.NewPublicKey("ED25519", pub[:])
|
||||
private := data.NewPrivateKey("ED25519", pub[:], priv[:])
|
||||
trust.addKey(private)
|
||||
return public, nil
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ var _ CryptoService = &MockCryptoService{}
|
|||
// Test signing and ensure the expected signature is added
|
||||
func TestBasicSign(t *testing.T) {
|
||||
testKey, _ := pem.Decode([]byte(testKeyPEM1))
|
||||
k := data.NewPublicKey("rsa", testKey.Bytes)
|
||||
k := data.NewPublicKey("RSA", testKey.Bytes)
|
||||
signer := Signer{&MockCryptoService{
|
||||
testKey: *k,
|
||||
}}
|
||||
|
@ -68,7 +68,7 @@ func TestBasicSign(t *testing.T) {
|
|||
// should be cleaning previous signatures by the KeyID when asked to sign again)
|
||||
func TestReSign(t *testing.T) {
|
||||
testKey, _ := pem.Decode([]byte(testKeyPEM1))
|
||||
k := data.NewPublicKey("rsa", testKey.Bytes)
|
||||
k := data.NewPublicKey("RSA", testKey.Bytes)
|
||||
signer := Signer{&MockCryptoService{
|
||||
testKey: *k,
|
||||
}}
|
||||
|
@ -92,11 +92,11 @@ func TestMultiSign(t *testing.T) {
|
|||
testData := data.Signed{}
|
||||
|
||||
testKey, _ := pem.Decode([]byte(testKeyPEM1))
|
||||
key := data.NewPublicKey("rsa", testKey.Bytes)
|
||||
key := data.NewPublicKey("RSA", testKey.Bytes)
|
||||
signer.Sign(&testData, key)
|
||||
|
||||
testKey, _ = pem.Decode([]byte(testKeyPEM2))
|
||||
key = data.NewPublicKey("rsa", testKey.Bytes)
|
||||
key = data.NewPublicKey("RSA", testKey.Bytes)
|
||||
signer.Sign(&testData, key)
|
||||
|
||||
if len(testData.Signatures) != 2 {
|
||||
|
@ -114,7 +114,7 @@ func TestMultiSign(t *testing.T) {
|
|||
|
||||
func TestCreate(t *testing.T) {
|
||||
testKey, _ := pem.Decode([]byte(testKeyPEM1))
|
||||
k := data.NewPublicKey("rsa", testKey.Bytes)
|
||||
k := data.NewPublicKey("RSA", testKey.Bytes)
|
||||
signer := Signer{&MockCryptoService{
|
||||
testKey: *k,
|
||||
}}
|
||||
|
|
|
@ -17,10 +17,10 @@ import (
|
|||
// can be injected into a verificationService. For testing and configuration
|
||||
// purposes, it will not be used by default.
|
||||
var Verifiers = map[string]Verifier{
|
||||
"ed25519": Ed25519Verifier{},
|
||||
"rsa": RSAVerifier{},
|
||||
"rsassa-pkcs1-v1_5-sign": RSAPemVerifier{}, // RSASSA-PKCS1-V1_5-SIGN
|
||||
"pycrypto-pkcs#1 pss": RSAPSSVerifier{},
|
||||
"ed25519": Ed25519Verifier{},
|
||||
"rsassa-pss": RSAPSSVerifier{},
|
||||
"rsassa-pss-x509": RSAPSSX509Verifier{},
|
||||
"pycrypto-pkcs#1 pss": RSAPyCryptoVerifier{},
|
||||
}
|
||||
|
||||
// RegisterVerifier provides a convenience function for init() functions
|
||||
|
@ -61,83 +61,79 @@ func (v Ed25519Verifier) Verify(key data.Key, sig []byte, msg []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type RSAVerifier struct{}
|
||||
|
||||
func (v RSAVerifier) Verify(key data.Key, sig []byte, msg []byte) error {
|
||||
digest := sha256.Sum256(msg)
|
||||
//keyReader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(key.Public()))
|
||||
//keyBytes, _ := ioutil.ReadAll(keyReader)
|
||||
//pub, err := x509.ParsePKIXPublicKey(keyBytes)
|
||||
pub, err := x509.ParsePKIXPublicKey(key.Public())
|
||||
if err != nil {
|
||||
logrus.Infof("Failed to parse public key: %s\n", err)
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
rsaPub, ok := pub.(*rsa.PublicKey)
|
||||
func verifyPSS(key interface{}, digest, sig []byte) error {
|
||||
rsaPub, ok := key.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
logrus.Infof("Value returned from ParsePKIXPublicKey was not an RSA public key")
|
||||
logrus.Infof("Value was not an RSA public key")
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
if err = rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, digest[:], sig); err != nil {
|
||||
opts := rsa.PSSOptions{SaltLength: sha256.Size, Hash: crypto.SHA256}
|
||||
if err := rsa.VerifyPSS(rsaPub, crypto.SHA256, digest[:], sig, &opts); err != nil {
|
||||
logrus.Infof("Failed verification: %s", err)
|
||||
return ErrInvalid
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RSAPemVerifier struct{}
|
||||
|
||||
func (v RSAPemVerifier) Verify(key data.Key, sig []byte, msg []byte) error {
|
||||
digest := sha256.Sum256(msg)
|
||||
|
||||
k, _ := pem.Decode([]byte(key.Public()))
|
||||
cert, err := x509.ParseCertificate(k.Bytes)
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to parse public key: %s\n", err.Error())
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
rsaPub, ok := cert.PublicKey.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
logrus.Infof("Value returned from ParsePKIXPublicKey was not an RSA public key")
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
if err = rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, digest[:], sig); err != nil {
|
||||
logrus.Errorf("Failed verification: %s", err.Error())
|
||||
return ErrInvalid
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RSAPSSVerifier checks RSASSA-PSS signatures
|
||||
type RSAPSSVerifier struct{}
|
||||
|
||||
// Verify does the actual check.
|
||||
// N.B. We have not been able to make this work in a way that is compatible
|
||||
// with PyCrypto.
|
||||
func (v RSAPSSVerifier) Verify(key data.Key, sig []byte, msg []byte) error {
|
||||
digest := sha256.Sum256(msg)
|
||||
|
||||
pub, err := x509.ParsePKIXPublicKey(key.Public())
|
||||
if err != nil {
|
||||
logrus.Infof("Failed to parse public key: %s\n", err)
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
return verifyPSS(pub, digest[:], sig)
|
||||
}
|
||||
|
||||
// RSAPSSVerifier checks RSASSA-PSS signatures
|
||||
type RSAPyCryptoVerifier struct{}
|
||||
|
||||
// Verify does the actual check.
|
||||
// N.B. We have not been able to make this work in a way that is compatible
|
||||
// with PyCrypto.
|
||||
func (v RSAPyCryptoVerifier) Verify(key data.Key, sig []byte, msg []byte) error {
|
||||
digest := sha256.Sum256(msg)
|
||||
|
||||
k, _ := pem.Decode([]byte(key.Public()))
|
||||
if k == nil {
|
||||
logrus.Infof("Failed to decode PEM-encoded x509 certificate")
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
pub, err := x509.ParsePKIXPublicKey(k.Bytes)
|
||||
if err != nil {
|
||||
logrus.Infof("Failed to parse public key: %s\n", err)
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
rsaPub, ok := pub.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
logrus.Infof("Value returned from ParsePKIXPublicKey was not an RSA public key")
|
||||
return verifyPSS(pub, digest[:], sig)
|
||||
}
|
||||
|
||||
// RSAPSSPEMVerifier checks RSASSA-PSS signatures, extracting the public key
|
||||
// from an X509 certificate.
|
||||
type RSAPSSX509Verifier struct{}
|
||||
|
||||
// Verify does the actual check.
|
||||
func (v RSAPSSX509Verifier) Verify(key data.Key, sig []byte, msg []byte) error {
|
||||
digest := sha256.Sum256(msg)
|
||||
|
||||
k, _ := pem.Decode([]byte(key.Public()))
|
||||
if k == nil {
|
||||
logrus.Infof("Failed to decode PEM-encoded x509 certificate")
|
||||
return ErrInvalid
|
||||
}
|
||||
cert, err := x509.ParseCertificate(k.Bytes)
|
||||
if err != nil {
|
||||
logrus.Infof("Failed to parse x509 certificate: %s\n", err)
|
||||
return ErrInvalid
|
||||
}
|
||||
|
||||
opts := rsa.PSSOptions{SaltLength: sha256.Size, Hash: crypto.SHA256}
|
||||
if err = rsa.VerifyPSS(rsaPub, crypto.SHA256, digest[:], sig, &opts); err != nil {
|
||||
logrus.Infof("Failed verification: %s", err)
|
||||
return ErrInvalid
|
||||
}
|
||||
return nil
|
||||
return verifyPSS(cert.PublicKey, digest[:], sig)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package store
|
|||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -27,7 +26,7 @@ func TestGetMeta(t *testing.T) {
|
|||
"txt",
|
||||
"targets",
|
||||
"key",
|
||||
&TestRoundTripper{},
|
||||
&http.Transport{},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -42,8 +41,7 @@ func TestGetMeta(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
rootPem := "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEArvqUPYb6JJROPJQglPTj\n5uDrsxQKl34Mo+3pSlBVuD6puE4lDnG649a2YksJy+C8ZIPJgokn5w+C3alh+dMe\nzbdWHHxrY1h9CLpYz5cbMlE16303ubkt1rvwDqEezG0HDBzPaKj4oP9YJ9x7wbsq\ndvFcy+Qc3wWd7UWcieo6E0ihbJkYcY8chRXVLg1rL7EfZ+e3bq5+ojA2ECM5JqzZ\nzgDpqCv5hTCYYZp72MZcG7dfSPAHrcSGIrwg7whzz2UsEtCOpsJTuCl96FPN7kAu\n4w/WyM3+SPzzr4/RQXuY1SrLCFD8ebM2zHt/3ATLhPnGmyG5I0RGYoegFaZ2AViw\nlqZDOYnBtgDvKP0zakMtFMbkh2XuNBUBO7Sjs0YcZMjLkh9gYUHL1yWS3Aqus1Lw\nlI0gHS22oyGObVBWkZEgk/Foy08sECLGao+5VvhmGpfVuiz9OKFUmtPVjWzRE4ng\niekEu4drSxpH41inLGSvdByDWLpcTvWQI9nkgclh3AT/AgMBAAE=\n-----END PUBLIC KEY-----"
|
||||
testKey, _ := pem.Decode([]byte(rootPem))
|
||||
k := data.NewPublicKey("rsa", testKey.Bytes)
|
||||
k := data.NewPublicKey("RSA", []byte(rootPem))
|
||||
|
||||
sigBytes, err := hex.DecodeString(p.Signatures[0].Signature.String())
|
||||
if err != nil {
|
||||
|
@ -70,8 +68,7 @@ func TestPyCryptoRSAPSSCompat(t *testing.T) {
|
|||
//privPem := "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----"
|
||||
testStr := "The quick brown fox jumps over the lazy dog."
|
||||
sigHex := "4e05ee9e435653549ac4eddbc43e1a6868636e8ea6dbec2564435afcb0de47e0824cddbd88776ddb20728c53ecc90b5d543d5c37575fda8bd0317025fc07de62ee8084b1a75203b1a23d1ef4ac285da3d1fc63317d5b2cf1aafa3e522acedd366ccd5fe4a7f02a42922237426ca3dc154c57408638b9bfaf0d0213855d4e9ee621db204151bcb13d4dbb18f930ec601469c992c84b14e9e0b6f91ac9517bb3b749dd117e1cbac2e4acb0e549f44558a2005898a226d5b6c8b9291d7abae0d9e0a16858b89662a085f74a202deb867acab792bdbd2c36731217caea8b17bd210c29b890472f11e5afdd1dd7b69004db070e04201778f2c49f5758643881403d45a58d08f51b5c63910c6185892f0b590f191d760b669eff2464456f130239bba94acf54a0cb98f6939ff84ae26a37f9b890be259d9b5d636f6eb367b53e895227d7d79a3a88afd6d28c198ee80f6527437c5fbf63accb81709925c4e03d1c9eaee86f58e4bd1c669d6af042dbd412de0d13b98b1111e2fadbe34b45de52125e9a"
|
||||
testKey, _ := pem.Decode([]byte(pubPem))
|
||||
k := data.NewPublicKey("rsa", testKey.Bytes)
|
||||
k := data.NewPublicKey("RSA", []byte(pubPem))
|
||||
|
||||
sigBytes, err := hex.DecodeString(sigHex)
|
||||
if err != nil {
|
||||
|
@ -91,11 +88,11 @@ func TestPyNaCled25519Compat(t *testing.T) {
|
|||
sigHex := "166e7013e48f26dccb4e68fe4cf558d1cd3af902f8395534336a7f8b4c56588694aa3ac671767246298a59d5ef4224f02c854f41bfcfe70241db4be1546d6a00"
|
||||
|
||||
pub, _ := hex.DecodeString(pubHex)
|
||||
k := data.NewPublicKey("ed25519", pub)
|
||||
k := data.NewPublicKey("ED25519", pub)
|
||||
|
||||
sigBytes, _ := hex.DecodeString(sigHex)
|
||||
|
||||
err := signed.Verifiers["ed25519"].Verify(k, sigBytes, []byte(testStr))
|
||||
err := signed.Verifiers["ED25519"].Verify(k, sigBytes, []byte(testStr))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package store
|
||||
|
||||
import "bytes"
|
||||
import "reflect"
|
||||
import "testing"
|
||||
|
||||
func testMeta(t *testing.T, s *MetadataStore) {
|
||||
storeName := reflect.TypeOf(s).Name()
|
||||
testData := []byte{}
|
||||
err := s.SetMeta(testName, testData)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, err := s.GetMeta(testName, len(testData))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if bytes.Compare(testData, out) != 0 {
|
||||
t.Fatalf("%s mangled data", storeName)
|
||||
}
|
||||
}
|
|
@ -23,12 +23,16 @@ func SampleMeta() data.FileMeta {
|
|||
}
|
||||
|
||||
func GetSqliteDB() *sql.DB {
|
||||
os.Mkdir("/tmp/sqlite", 0755)
|
||||
conn, err := sql.Open("sqlite3", fmt.Sprintf("/tmp/sqlite/file%d.db", counter))
|
||||
if err != nil {
|
||||
panic("can't connect to db")
|
||||
}
|
||||
counter++
|
||||
tx, _ := conn.Begin()
|
||||
tx, err := conn.Begin()
|
||||
if err != nil {
|
||||
panic("can't begin db transaction")
|
||||
}
|
||||
tx.Exec("CREATE TABLE keys (id int auto_increment, namespace varchar(255) not null, role varchar(255) not null, key text not null, primary key (id));")
|
||||
tx.Exec("CREATE TABLE filehashes(namespace varchar(255) not null, path varchar(255) not null, alg varchar(10) not null, hash varchar(128) not null, primary key (namespace, path, alg));")
|
||||
tx.Exec("CREATE TABLE filemeta(namespace varchar(255) not null, path varchar(255) not null, size int not null, custom text default null, primary key (namespace, path));")
|
||||
|
|
|
@ -177,16 +177,13 @@ func (tr *TufRepo) UpdateDelegations(role *data.Role, keys []data.Key, before st
|
|||
// also relies on the keysDB having already been populated with the keys and
|
||||
// roles.
|
||||
func (tr *TufRepo) InitRepo(consistent bool) error {
|
||||
err := tr.InitRoot(consistent)
|
||||
if err != nil {
|
||||
if err := tr.InitRoot(consistent); err != nil {
|
||||
return err
|
||||
}
|
||||
tr.InitTargets()
|
||||
if err != nil {
|
||||
if err := tr.InitTargets(); err != nil {
|
||||
return err
|
||||
}
|
||||
tr.InitSnapshot()
|
||||
if err != nil {
|
||||
if err := tr.InitSnapshot(); err != nil {
|
||||
return err
|
||||
}
|
||||
return tr.InitTimestamp()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
|
@ -16,40 +15,6 @@ type UtilSuite struct{}
|
|||
|
||||
var _ = Suite(&UtilSuite{})
|
||||
|
||||
func (UtilSuite) TestGenerateFileMetaDefault(c *C) {
|
||||
// default is sha512
|
||||
r := bytes.NewReader([]byte("foo"))
|
||||
meta, err := GenerateFileMeta(r)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(meta.Length, Equals, int64(3))
|
||||
hashes := meta.Hashes
|
||||
c.Assert(hashes, HasLen, 1)
|
||||
hash, ok := hashes["sha512"]
|
||||
if !ok {
|
||||
c.Fatal("missing sha512 hash")
|
||||
}
|
||||
c.Assert(hash.String(), DeepEquals, "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7")
|
||||
}
|
||||
|
||||
func (UtilSuite) TestGenerateFileMetaExplicit(c *C) {
|
||||
r := bytes.NewReader([]byte("foo"))
|
||||
meta, err := GenerateFileMeta(r, "sha256", "sha512")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(meta.Length, Equals, int64(3))
|
||||
hashes := meta.Hashes
|
||||
c.Assert(hashes, HasLen, 2)
|
||||
for name, val := range map[string]string{
|
||||
"sha256": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
|
||||
"sha512": "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7",
|
||||
} {
|
||||
hash, ok := hashes[name]
|
||||
if !ok {
|
||||
c.Fatalf("missing %s hash", name)
|
||||
}
|
||||
c.Assert(hash.String(), DeepEquals, val)
|
||||
}
|
||||
}
|
||||
|
||||
func (UtilSuite) TestFileMetaEqual(c *C) {
|
||||
type test struct {
|
||||
name string
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/notary/trustmanager"
|
||||
"github.com/endophage/gotuf/data"
|
||||
|
@ -17,16 +17,9 @@ import (
|
|||
// CryptoService implements Sign and Create, holding a specific GUN and keystore to
|
||||
// operate on
|
||||
type CryptoService struct {
|
||||
gun string
|
||||
keyStore *trustmanager.KeyFileStore
|
||||
}
|
||||
|
||||
// RootCryptoService implements Sign and Create and operates on a rootKeyStore,
|
||||
// taking in a passphrase and calling decrypt when signing.
|
||||
type RootCryptoService struct {
|
||||
// TODO(diogo): support multiple passphrases per key
|
||||
passphrase string
|
||||
rootKeyStore *trustmanager.KeyFileStore
|
||||
gun string
|
||||
passphrase string
|
||||
keyStore *trustmanager.KeyFileStore
|
||||
}
|
||||
|
||||
// NewCryptoService returns an instance of CryptoService
|
||||
|
@ -34,11 +27,6 @@ func NewCryptoService(gun string, keyStore *trustmanager.KeyFileStore) *CryptoSe
|
|||
return &CryptoService{gun: gun, keyStore: keyStore}
|
||||
}
|
||||
|
||||
// NewRootCryptoService returns an instance of CryptoService
|
||||
func NewRootCryptoService(rootKeyStore *trustmanager.KeyFileStore, passphrase string) *RootCryptoService {
|
||||
return &RootCryptoService{rootKeyStore: rootKeyStore, passphrase: passphrase}
|
||||
}
|
||||
|
||||
// Create is used to generate keys for targets, snapshots and timestamps
|
||||
func (ccs *CryptoService) Create(role string) (*data.PublicKey, error) {
|
||||
privKey, err := trustmanager.GenerateRSAKey(rand.Reader, rsaKeySize)
|
||||
|
@ -52,7 +40,14 @@ func (ccs *CryptoService) Create(role string) (*data.PublicKey, error) {
|
|||
return data.PublicKeyFromPrivate(*privKey), nil
|
||||
}
|
||||
|
||||
// Sign returns the signatures for data with the given keyIDs
|
||||
// SetPassphrase tells the cryptoservice the passphrase. Use only if the key needs
|
||||
// to be decrypted.
|
||||
func (ccs *CryptoService) SetPassphrase(passphrase string) {
|
||||
ccs.passphrase = passphrase
|
||||
}
|
||||
|
||||
// Sign returns the signatures for data with the given root Key ID, falling back
|
||||
// if not rootKeyID is found
|
||||
func (ccs *CryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signature, error) {
|
||||
// Create hasher and hash data
|
||||
hash := crypto.SHA256
|
||||
|
@ -60,11 +55,27 @@ func (ccs *CryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signatur
|
|||
|
||||
signatures := make([]data.Signature, 0, len(keyIDs))
|
||||
for _, fingerprint := range keyIDs {
|
||||
// Get the PrivateKey filename
|
||||
privKeyFilename := filepath.Join(ccs.gun, fingerprint)
|
||||
// ccs.gun will be empty if this is the root key
|
||||
keyName := filepath.Join(ccs.gun, fingerprint)
|
||||
|
||||
var privKey *data.PrivateKey
|
||||
var err error
|
||||
var method string
|
||||
|
||||
// Read PrivateKey from file
|
||||
privKey, err := ccs.keyStore.GetKey(privKeyFilename)
|
||||
if ccs.passphrase != "" {
|
||||
// This is a root key
|
||||
privKey, err = ccs.keyStore.GetDecryptedKey(keyName, ccs.passphrase)
|
||||
method = "RSASSA-PSS-X509"
|
||||
} else {
|
||||
privKey, err = ccs.keyStore.GetKey(keyName)
|
||||
method = "RSASSA-PSS"
|
||||
}
|
||||
if err != nil {
|
||||
// Note that GetDecryptedKey always fails on InitRepo.
|
||||
// InitRepo gets a signer that doesn't have access to
|
||||
// the root keys. Continuing here is safe because we
|
||||
// end up not returning any signatures.
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -76,44 +87,7 @@ func (ccs *CryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signatur
|
|||
// Append signatures to result array
|
||||
signatures = append(signatures, data.Signature{
|
||||
KeyID: fingerprint,
|
||||
Method: "RSA",
|
||||
Signature: sig[:],
|
||||
})
|
||||
}
|
||||
return signatures, nil
|
||||
}
|
||||
|
||||
// Create in a root crypto service is not implemented
|
||||
func (rcs *RootCryptoService) Create(role string) (*data.PublicKey, error) {
|
||||
return nil, errors.New("create on a root key filestore is not implemented")
|
||||
}
|
||||
|
||||
// Sign returns the signatures for data with the given root Key ID, falling back
|
||||
// if not rootKeyID is found
|
||||
// TODO(diogo): This code has 1 line change from the Sign from Crypto service. DRY it up.
|
||||
func (rcs *RootCryptoService) Sign(keyIDs []string, payload []byte) ([]data.Signature, error) {
|
||||
// Create hasher and hash data
|
||||
hash := crypto.SHA256
|
||||
hashed := sha256.Sum256(payload)
|
||||
|
||||
signatures := make([]data.Signature, 0, len(keyIDs))
|
||||
for _, fingerprint := range keyIDs {
|
||||
// Read PrivateKey from file
|
||||
privKey, err := rcs.rootKeyStore.GetDecryptedKey(fingerprint, rcs.passphrase)
|
||||
if err != nil {
|
||||
// TODO(diogo): This error should be returned to the user in someway
|
||||
continue
|
||||
}
|
||||
|
||||
sig, err := sign(privKey, hash, hashed[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Append signatures to result array
|
||||
signatures = append(signatures, data.Signature{
|
||||
KeyID: fingerprint,
|
||||
Method: "RSASSA-PKCS1-V1_5-SIGN",
|
||||
Method: method,
|
||||
Signature: sig[:],
|
||||
})
|
||||
}
|
||||
|
@ -123,7 +97,7 @@ func (rcs *RootCryptoService) Sign(keyIDs []string, payload []byte) ([]data.Sign
|
|||
|
||||
func sign(privKey *data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
|
||||
// TODO(diogo): Implement support for ECDSA.
|
||||
if privKey.Cipher() != "RSA" {
|
||||
if strings.ToLower(privKey.Cipher()) != "rsa" {
|
||||
return nil, fmt.Errorf("private key type not supported: %s", privKey.Cipher())
|
||||
}
|
||||
|
||||
|
@ -134,7 +108,7 @@ func sign(privKey *data.PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, er
|
|||
}
|
||||
|
||||
// Use the RSA key to sign the data
|
||||
sig, err := rsa.SignPKCS1v15(rand.Reader, rsaPrivKey, hash, hashed[:])
|
||||
sig, err := rsa.SignPSS(rand.Reader, rsaPrivKey, hash, hashed[:], &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ type UnlockedSigner struct {
|
|||
// repository.
|
||||
type NotaryRepository struct {
|
||||
baseDir string
|
||||
Gun string
|
||||
gun string
|
||||
baseURL string
|
||||
tufRepoPath string
|
||||
caStore trustmanager.X509Store
|
||||
|
@ -111,10 +111,11 @@ func NewNotaryRepository(baseDir, gun, baseURL string, rt http.RoundTripper) (*N
|
|||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("creating non-root cryptoservice")
|
||||
signer := signed.NewSigner(NewCryptoService(gun, privKeyStore))
|
||||
|
||||
nRepo := &NotaryRepository{
|
||||
Gun: gun,
|
||||
gun: gun,
|
||||
baseDir: baseDir,
|
||||
baseURL: baseURL,
|
||||
tufRepoPath: filepath.Join(baseDir, tufDir, gun),
|
||||
|
@ -133,7 +134,7 @@ func NewNotaryRepository(baseDir, gun, baseURL string, rt http.RoundTripper) (*N
|
|||
// Initialize creates a new repository by using rootKey as the root Key for the
|
||||
// TUF repository.
|
||||
func (r *NotaryRepository) Initialize(uSigner *UnlockedSigner) error {
|
||||
rootCert, err := uSigner.GenerateCertificate(r.Gun)
|
||||
rootCert, err := uSigner.GenerateCertificate(r.gun)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -144,7 +145,7 @@ func (r *NotaryRepository) Initialize(uSigner *UnlockedSigner) error {
|
|||
return err
|
||||
}
|
||||
|
||||
remote, err := getRemoteStore(r.baseURL, r.Gun, r.roundTrip)
|
||||
remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip)
|
||||
rawTSKey, err := remote.GetKey("timestamp")
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -377,7 +378,7 @@ func (r *NotaryRepository) Publish(getPass passwordRetriever) error {
|
|||
return err
|
||||
}
|
||||
|
||||
remote, err := getRemoteStore(r.baseURL, r.Gun, r.roundTrip)
|
||||
remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -554,14 +555,14 @@ func (r *NotaryRepository) validateRoot(root *data.Signed) error {
|
|||
// Cert.Raw. It's included to prevent breaking logic with changes of how the
|
||||
// ID gets computed.
|
||||
_, err = r.certificateStore.GetCertificateByFingerprint(leafID)
|
||||
if err == nil && leafCert.Subject.CommonName == r.Gun {
|
||||
if err == nil && leafCert.Subject.CommonName == r.gun {
|
||||
certs[fingerprint] = rootSigned.Keys[fingerprint]
|
||||
}
|
||||
|
||||
// Check to see if this leafCertificate has a chain to one of the Root CAs
|
||||
// of our CA Store.
|
||||
certList := []*x509.Certificate{leafCert}
|
||||
err = trustmanager.Verify(r.caStore, r.Gun, certList)
|
||||
err = trustmanager.Verify(r.caStore, r.gun, certList)
|
||||
if err == nil {
|
||||
certs[fingerprint] = rootSigned.Keys[fingerprint]
|
||||
}
|
||||
|
@ -577,7 +578,7 @@ func (r *NotaryRepository) validateRoot(root *data.Signed) error {
|
|||
}
|
||||
|
||||
func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) {
|
||||
remote, err := getRemoteStore(r.baseURL, r.Gun, r.roundTrip)
|
||||
remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -638,7 +639,12 @@ func (r *NotaryRepository) GetRootSigner(rootKeyID, passphrase string) (*Unlocke
|
|||
|
||||
// This signer will be used for all of the normal TUF operations, except for
|
||||
// when a root key is needed.
|
||||
signer := signed.NewSigner(NewRootCryptoService(r.rootKeyStore, passphrase))
|
||||
|
||||
// Passing an empty GUN because root keys aren't associated with a GUN.
|
||||
fmt.Println("creating root cryptoservice with passphrase", passphrase)
|
||||
ccs := NewCryptoService("", r.rootKeyStore)
|
||||
ccs.SetPassphrase(passphrase)
|
||||
signer := signed.NewSigner(ccs)
|
||||
|
||||
return &UnlockedSigner{
|
||||
privKey: privKey,
|
||||
|
|
|
@ -46,23 +46,23 @@ func TestGetTimestampKey(t *testing.T) {
|
|||
//_, _, err := s.GetTimestampKey("gun")
|
||||
//assert.IsType(t, &ErrNoKey{}, err, "Expected err to be ErrNoKey")
|
||||
|
||||
s.SetTimestampKey("gun", "rsa", []byte("test"))
|
||||
s.SetTimestampKey("gun", "RSA", []byte("test"))
|
||||
|
||||
c, k, err := s.GetTimestampKey("gun")
|
||||
assert.Nil(t, err, "Expected error to be nil")
|
||||
assert.Equal(t, "rsa", c, "Expected cipher rsa, received %s", c)
|
||||
assert.Equal(t, "RSA", c, "Expected cipher rsa, received %s", c)
|
||||
assert.Equal(t, []byte("test"), k, "Key data was wrong")
|
||||
}
|
||||
|
||||
func TestSetTimestampKey(t *testing.T) {
|
||||
s := NewMemStorage()
|
||||
s.SetTimestampKey("gun", "rsa", []byte("test"))
|
||||
s.SetTimestampKey("gun", "RSA", []byte("test"))
|
||||
|
||||
err := s.SetTimestampKey("gun", "rsa", []byte("test2"))
|
||||
err := s.SetTimestampKey("gun", "RSA", []byte("test2"))
|
||||
assert.IsType(t, &ErrTimestampKeyExists{}, err, "Expected err to be ErrTimestampKeyExists")
|
||||
|
||||
k := s.tsKeys["gun"]
|
||||
assert.Equal(t, "rsa", k.cipher, "Expected cipher to be rsa, received %s", k.cipher)
|
||||
assert.Equal(t, "RSA", k.cipher, "Expected cipher to be rsa, received %s", k.cipher)
|
||||
assert.Equal(t, []byte("test"), k.public, "Public key did not match expected")
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue