Fixing Godeps

This commit is contained in:
Diogo Monica 2015-06-17 11:48:25 -07:00
parent 6805f290f0
commit 26f694196e
172 changed files with 4036 additions and 4879 deletions

66
Godeps/Godeps.json generated
View File

@ -2,8 +2,7 @@
"ImportPath": "github.com/docker/vetinari",
"GoVersion": "go1.4.2",
"Packages": [
"github.com/docker/vetinari/cmd/notary",
"github.com/docker/vetinari/cmd/vetinari-server"
"./..."
],
"Deps": [
{
@ -11,10 +10,6 @@
"Comment": "null-15",
"Rev": "35bc42037350f0078e3c974c6ea690f1926603ab"
},
{
"ImportPath": "github.com/Sirupsen/logrus",
"Rev": "55eb11d21d2a31a3cc93838241d04800f52e823d"
},
{
"ImportPath": "github.com/BurntSushi/toml",
"Rev": "bd2bdf7f18f849530ef7a1c29a4290217cab32a1"
@ -34,18 +29,13 @@
},
{
"ImportPath": "github.com/docker/distribution/context",
"Comment": "v2.0.0-228-gb230183",
"Rev": "b230183b0fe8b8ed3c9ae2898c47c8c8618dc80f"
"Comment": "v2.0.0-rc.3-2-g75919b7",
"Rev": "75919b7dcc5d53894d7e8f1584e91ae148335f3a"
},
{
"ImportPath": "github.com/docker/distribution/registry/auth",
"Comment": "v2.0.0-228-gb230183",
"Rev": "b230183b0fe8b8ed3c9ae2898c47c8c8618dc80f"
},
{
"ImportPath": "github.com/docker/distribution/uuid",
"Comment": "v2.0.0-228-gb230183",
"Rev": "b230183b0fe8b8ed3c9ae2898c47c8c8618dc80f"
"Comment": "v2.0.0-rc.3-2-g75919b7",
"Rev": "75919b7dcc5d53894d7e8f1584e91ae148335f3a"
},
{
"ImportPath": "github.com/docker/libtrust",
@ -56,12 +46,25 @@
"Rev": "61b53384b24bfa83e8e0a5f11f28ae83457fd80c"
},
{
"ImportPath": "github.com/endophage/gotuf/data",
"Rev": "930a4e1cc71f866a412aea60c960ee4345f0c76a"
"ImportPath": "github.com/endophage/gotuf",
"Rev": "c7154b63cf6e8485ea4af4c7f299ccbea6731d43"
},
{
"ImportPath": "github.com/endophage/gotuf/errors",
"Rev": "930a4e1cc71f866a412aea60c960ee4345f0c76a"
"ImportPath": "github.com/go-sql-driver/mysql",
"Comment": "v1.2-97-g0cc29e9",
"Rev": "0cc29e9fe8e25c2c58cf47bcab566e029bbaa88b"
},
{
"ImportPath": "github.com/golang/protobuf/proto",
"Rev": "655cdfa588ea190e901bc5590e65d5621688847c"
},
{
"ImportPath": "github.com/gorilla/context",
"Rev": "14f550f51af52180c2eefed15e5fd18d63c0a64a"
},
{
"ImportPath": "github.com/gorilla/mux",
"Rev": "e444e69cbd2e2e3e0749a2f3c717cec491552bbf"
},
{
"ImportPath": "github.com/inconshreveable/mousetrap",
@ -105,31 +108,6 @@
"ImportPath": "github.com/spf13/viper",
"Rev": "be5ff3e4840cf692388bde7a057595a474ef379e"
},
{
"ImportPath": "github.com/endophage/gotuf/keys",
"Rev": "930a4e1cc71f866a412aea60c960ee4345f0c76a"
},
{
"ImportPath": "github.com/endophage/gotuf/signed",
"Rev": "930a4e1cc71f866a412aea60c960ee4345f0c76a"
},
{
"ImportPath": "github.com/go-sql-driver/mysql",
"Comment": "v1.2-108-g66b7d5c",
"Rev": "66b7d5c4956096efd4c945494d64ad73f1d9ec39"
},
{
"ImportPath": "github.com/golang/protobuf/proto",
"Rev": "655cdfa588ea190e901bc5590e65d5621688847c"
},
{
"ImportPath": "github.com/gorilla/context",
"Rev": "14f550f51af52180c2eefed15e5fd18d63c0a64a"
},
{
"ImportPath": "github.com/gorilla/mux",
"Rev": "e444e69cbd2e2e3e0749a2f3c717cec491552bbf"
},
{
"ImportPath": "github.com/tent/canonical-json-go",
"Rev": "96e4ba3a7613a1216cbd1badca4efe382adea337"

View File

@ -1,7 +1,7 @@
package context
import (
"github.com/docker/distribution/uuid"
"code.google.com/p/go-uuid/uuid"
"golang.org/x/net/context"
)
@ -27,7 +27,7 @@ func (ic *instanceContext) Value(key interface{}) interface{} {
var background = &instanceContext{
Context: context.Background(),
id: uuid.Generate().String(),
id: uuid.New(),
}
// Background returns a non-nil, empty Context. The background context

View File

@ -8,15 +8,14 @@ import (
"sync"
"time"
"code.google.com/p/go-uuid/uuid"
log "github.com/Sirupsen/logrus"
"github.com/docker/distribution/uuid"
"github.com/gorilla/mux"
)
// Common errors used with this package.
var (
ErrNoRequestContext = errors.New("no http request in context")
ErrNoResponseWriterContext = errors.New("no http response in context")
ErrNoRequestContext = errors.New("no http request in context")
)
func parseIP(ipStr string) net.IP {
@ -79,7 +78,7 @@ func WithRequest(ctx Context, r *http.Request) Context {
return &httpRequestContext{
Context: ctx,
startedAt: time.Now(),
id: uuid.Generate().String(),
id: uuid.New(), // assign the request a unique.
r: r,
}
}
@ -111,20 +110,6 @@ func WithResponseWriter(ctx Context, w http.ResponseWriter) (Context, http.Respo
return irw, irw
}
// GetResponseWriter returns the http.ResponseWriter from the provided
// context. If not present, ErrNoResponseWriterContext is returned. The
// returned instance provides instrumentation in the context.
func GetResponseWriter(ctx Context) (http.ResponseWriter, error) {
v := ctx.Value("http.response")
rw, ok := v.(http.ResponseWriter)
if !ok || rw == nil {
return nil, ErrNoResponseWriterContext
}
return rw, nil
}
// getVarsFromRequest let's us change request vars implementation for testing
// and maybe future changes.
var getVarsFromRequest = mux.Vars
@ -302,7 +287,7 @@ func (irw *instrumentedResponseWriter) Flush() {
func (irw *instrumentedResponseWriter) Value(key interface{}) interface{} {
if keyStr, ok := key.(string); ok {
if keyStr == "http.response" {
return irw
return irw.ResponseWriter
}
if !strings.HasPrefix(keyStr, "http.response.") {
@ -322,7 +307,9 @@ func (irw *instrumentedResponseWriter) Value(key interface{}) interface{} {
case "written":
return irw.written
case "status":
return irw.status
if irw.status != 0 {
return irw.status
}
case "contenttype":
contentType := irw.Header().Get("Content-Type")
if contentType != "" {

View File

@ -132,21 +132,8 @@ func TestWithResponseWriter(t *testing.T) {
trw := testResponseWriter{}
ctx, rw := WithResponseWriter(Background(), &trw)
if ctx.Value("http.response") != rw {
t.Fatalf("response not available in context: %v != %v", ctx.Value("http.response"), rw)
}
grw, err := GetResponseWriter(ctx)
if err != nil {
t.Fatalf("error getting response writer: %v", err)
}
if grw != rw {
t.Fatalf("unexpected response writer returned: %#v != %#v", grw, rw)
}
if ctx.Value("http.response.status") != 0 {
t.Fatalf("response status should always be a number and should be zero here: %v != 0", ctx.Value("http.response.status"))
if ctx.Value("http.response") != &trw {
t.Fatalf("response not available in context: %v != %v", ctx.Value("http.response"), &trw)
}
if n, err := rw.Write(make([]byte, 1024)); err != nil {

View File

@ -3,8 +3,6 @@ package context
import (
"fmt"
"github.com/docker/distribution/uuid"
"github.com/Sirupsen/logrus"
)
@ -101,8 +99,3 @@ func getLogrusLogger(ctx Context, keys ...interface{}) *logrus.Entry {
return logger.WithFields(fields)
}
func init() {
// inject a logger into the uuid library.
uuid.Loggerf = GetLogger(Background()).Warnf
}

View File

@ -4,7 +4,7 @@ import (
"runtime"
"time"
"github.com/docker/distribution/uuid"
"code.google.com/p/go-uuid/uuid"
)
// WithTrace allocates a traced timing span in a new context. This allows a
@ -45,7 +45,7 @@ func WithTrace(ctx Context) (Context, func(format string, a ...interface{})) {
f := runtime.FuncForPC(pc)
ctx = &traced{
Context: ctx,
id: uuid.Generate().String(),
id: uuid.New(),
start: time.Now(),
parent: GetStringValue(ctx, "trace.id"),
fnname: f.Name(),
@ -54,14 +54,9 @@ func WithTrace(ctx Context) (Context, func(format string, a ...interface{})) {
}
return ctx, func(format string, a ...interface{}) {
GetLogger(ctx,
"trace.duration",
"trace.id",
"trace.parent.id",
"trace.func",
"trace.file",
"trace.line").
Debugf(format, a...)
GetLogger(ctx, "trace.duration", "trace.id", "trace.parent.id",
"trace.func", "trace.file", "trace.line").
Infof(format, a...) // info may be too chatty.
}
}

View File

@ -3,7 +3,7 @@
// An access controller has a simple interface with a single `Authorized`
// method which checks that a given request is authorized to perform one or
// more actions on one or more resources. This method should return a non-nil
// error if the request is not authorized.
// error if the requset is not authorized.
//
// An implementation registers its access controller by name with a constructor
// which accepts an options map for configuring the access controller.
@ -50,7 +50,7 @@ type Resource struct {
}
// Access describes a specific action that is
// requested or allowed for a given resource.
// requested or allowed for a given recource.
type Access struct {
Resource
Action string

View File

@ -66,7 +66,7 @@ func (ac *accessController) Authorized(ctx context.Context, accessRecords ...aut
return nil, &challenge
}
return auth.WithUser(ctx, auth.UserInfo{Name: "silly"}), nil
return context.WithValue(ctx, "auth.user", auth.UserInfo{Name: "silly"}), nil
}
type challenge struct {

View File

@ -7,7 +7,7 @@ import (
)
// joseBase64UrlEncode encodes the given data using the standard base64 url
// encoding format but with all trailing '=' characters omitted in accordance
// encoding format but with all trailing '=' characters ommitted in accordance
// with the jose specification.
// http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-2
func joseBase64UrlEncode(b []byte) string {

View File

@ -1,112 +0,0 @@
// Package uuid provides simple UUID generation. Only version 4 style UUIDs
// can be generated.
//
// Please see http://tools.ietf.org/html/rfc4122 for details on UUIDs.
package uuid
import (
"crypto/rand"
"fmt"
"io"
"log"
"syscall"
"time"
)
const (
// Bits is the number of bits in a UUID
Bits = 128
// Size is the number of bytes in a UUID
Size = Bits / 8
format = "%08x-%04x-%04x-%04x-%012x"
)
var (
// ErrUUIDInvalid indicates a parsed string is not a valid uuid.
ErrUUIDInvalid = fmt.Errorf("invalid uuid")
// Loggerf can be used to override the default logging destination. Such
// log messages in this library should be logged at warning or higher.
Loggerf = log.Printf
)
// UUID represents a UUID value. UUIDs can be compared and set to other values
// and accessed by byte.
type UUID [Size]byte
// Generate creates a new, version 4 uuid.
func Generate() (u UUID) {
const (
// ensures we backoff for less than 450ms total. Use the following to
// select new value, in units of 10ms:
// n*(n+1)/2 = d -> n^2 + n - 2d -> n = (sqrt(8d + 1) - 1)/2
maxretries = 9
backoff = time.Millisecond * 10
)
var (
totalBackoff time.Duration
retries int
)
for {
// This should never block but the read may fail. Because of this,
// we just try to read the random number generator until we get
// something. This is a very rare condition but may happen.
b := time.Duration(retries) * backoff
time.Sleep(b)
totalBackoff += b
_, err := io.ReadFull(rand.Reader, u[:])
if err != nil {
if err == syscall.EPERM {
// EPERM represents an entropy pool exhaustion, a condition under
// which we backoff and retry.
if retries < maxretries {
retries++
Loggerf("error generating version 4 uuid, retrying: %v", err)
continue
}
}
// Any other errors represent a system problem. What did someone
// do to /dev/urandom?
panic(fmt.Errorf("error reading random number generator, retried for %v: %v", totalBackoff, err))
}
break
}
u[6] = (u[6] & 0x0f) | 0x40 // set version byte
u[8] = (u[8] & 0x3f) | 0x80 // set high order byte 0b10{8,9,a,b}
return u
}
// Parse attempts to extract a uuid from the string or returns an error.
func Parse(s string) (u UUID, err error) {
if len(s) != 36 {
return UUID{}, ErrUUIDInvalid
}
// create stack addresses for each section of the uuid.
p := make([][]byte, 5)
if _, err := fmt.Sscanf(s, format, &p[0], &p[1], &p[2], &p[3], &p[4]); err != nil {
return u, err
}
copy(u[0:4], p[0])
copy(u[4:6], p[1])
copy(u[6:8], p[2])
copy(u[8:10], p[3])
copy(u[10:16], p[4])
return
}
func (u UUID) String() string {
return fmt.Sprintf(format, u[:4], u[4:6], u[6:8], u[8:10], u[10:])
}

View File

@ -1,48 +0,0 @@
package uuid
import (
"testing"
)
const iterations = 1000
func TestUUID4Generation(t *testing.T) {
for i := 0; i < iterations; i++ {
u := Generate()
if u[6]&0xf0 != 0x40 {
t.Fatalf("version byte not correctly set: %v, %08b %08b", u, u[6], u[6]&0xf0)
}
if u[8]&0xc0 != 0x80 {
t.Fatalf("top order 8th byte not correctly set: %v, %b", u, u[8])
}
}
}
func TestParseAndEquality(t *testing.T) {
for i := 0; i < iterations; i++ {
u := Generate()
parsed, err := Parse(u.String())
if err != nil {
t.Fatalf("error parsing uuid %v: %v", u, err)
}
if parsed != u {
t.Fatalf("parsing round trip failed: %v != %v", parsed, u)
}
}
for _, c := range []string{
"bad",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", // correct length, incorrect format
" 20cc7775-2671-43c7-8742-51d1cfa23258", // leading space
"20cc7775-2671-43c7-8742-51d1cfa23258 ", // trailing space
"00000000-0000-0000-0000-x00000000000", // out of range character
} {
if _, err := Parse(c); err == nil {
t.Fatalf("parsing %q should have failed", c)
}
}
}

View File

@ -1,560 +0,0 @@
This describes the protocol used by OpenSSH's ssh-agent.
OpenSSH's agent supports managing keys for the standard SSH protocol
2 as well as the legacy SSH protocol 1. Support for these key types
is almost completely disjoint - in all but a few cases, operations on
protocol 2 keys cannot see or affect protocol 1 keys and vice-versa.
Protocol 1 and protocol 2 keys are separated because of the differing
cryptographic usage: protocol 1 private RSA keys are used to decrypt
challenges that were encrypted with the corresponding public key,
whereas protocol 2 RSA private keys are used to sign challenges with
a private key for verification with the corresponding public key. It
is considered unsound practice to use the same key for signing and
encryption.
With a couple of exceptions, the protocol message names used in this
document indicate which type of key the message relates to. SSH_*
messages refer to protocol 1 keys only. SSH2_* messages refer to
protocol 2 keys. Furthermore, the names also indicate whether the
message is a request to the agent (*_AGENTC_*) or a reply from the
agent (*_AGENT_*). Section 3 below contains the mapping of the
protocol message names to their integer values.
1. Data types
Because of support for legacy SSH protocol 1 keys, OpenSSH's agent
protocol makes use of some data types not defined in RFC 4251.
1.1 uint16
The "uint16" data type is a simple MSB-first 16 bit unsigned integer
encoded in two bytes.
1.2 mpint1
The "mpint1" type represents an arbitrary precision integer (bignum).
Its format is as follows:
uint16 bits
byte[(bits + 7) / 8] bignum
"bignum" contains an unsigned arbitrary precision integer encoded as
eight bits per byte in big-endian (MSB first) format.
Note the difference between the "mpint1" encoding and the "mpint"
encoding defined in RFC 4251. Also note that the length of the encoded
integer is specified in bits, not bytes and that the byte length of
the integer must be calculated by rounding up the number of bits to the
nearest eight.
2. Protocol Messages
All protocol messages are prefixed with their length in bytes, encoded
as a 32 bit unsigned integer. Specifically:
uint32 message_length
byte[message_length] message
The following message descriptions refer only to the content the
"message" field.
2.1 Generic server responses
The following generic messages may be sent by the server in response to
requests from the client. On success the agent may reply either with:
byte SSH_AGENT_SUCCESS
or a request-specific success message.
On failure, the agent may reply with:
byte SSH_AGENT_FAILURE
SSH_AGENT_FAILURE messages are also sent in reply to unknown request
types.
2.2 Adding keys to the agent
Keys are added to the agent using the SSH_AGENTC_ADD_RSA_IDENTITY and
SSH2_AGENTC_ADD_IDENTITY requests for protocol 1 and protocol 2 keys
respectively.
Two variants of these requests are SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
and SSH2_AGENTC_ADD_ID_CONSTRAINED - these add keys with optional
"constraints" on their usage.
OpenSSH may be built with support for keys hosted on a smartcard
or other hardware security module. These keys may be added
to the agent using the SSH_AGENTC_ADD_SMARTCARD_KEY and
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests.
2.2.1 Key constraints
The OpenSSH agent supports some basic optional constraints on key usage.
At present there are two constraints defined.
The first constraint limits the validity duration of a key. It is
encoded as:
byte SSH_AGENT_CONSTRAIN_LIFETIME
uint32 seconds
Where "seconds" contains the number of seconds that the key shall remain
valid measured from the moment that the agent receives it. After the
validity period has expired, OpenSSH's agent will erase these keys from
memory.
The second constraint requires the agent to seek explicit user
confirmation before performing private key operations with the loaded
key. This constraint is encoded as:
byte SSH_AGENT_CONSTRAIN_CONFIRM
Zero or more constraints may be specified when adding a key with one
of the *_CONSTRAINED requests. Multiple constraints are appended
consecutively to the end of the request:
byte constraint1_type
.... constraint1_data
byte constraint2_type
.... constraint2_data
....
byte constraintN_type
.... constraintN_data
Such a sequence of zero or more constraints will be referred to below
as "constraint[]". Agents may determine whether there are constraints
by checking whether additional data exists in the "add key" request
after the key data itself. OpenSSH will refuse to add a key if it
contains unknown constraints.
2.2.2 Add protocol 1 key
A client may add a protocol 1 key to an agent with the following
request:
byte SSH_AGENTC_ADD_RSA_IDENTITY or
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
uint32 ignored
mpint1 rsa_n
mpint1 rsa_e
mpint1 rsa_d
mpint1 rsa_iqmp
mpint1 rsa_q
mpint1 rsa_p
string key_comment
constraint[] key_constraints
Note that there is some redundancy in the key parameters; a key could be
fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra
computation.
"key_constraints" may only be present if the request type is
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED.
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
successfully added or a SSH_AGENT_FAILURE if an error occurred.
2.2.3 Add protocol 2 key
The OpenSSH agent supports DSA, ECDSA and RSA keys for protocol 2. DSA
keys may be added using the following request
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ssh-dss"
mpint dsa_p
mpint dsa_q
mpint dsa_g
mpint dsa_public_key
mpint dsa_private_key
string key_comment
constraint[] key_constraints
DSA certificates may be added with:
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ssh-dss-cert-v00@openssh.com"
string certificate
mpint dsa_private_key
string key_comment
constraint[] key_constraints
ECDSA keys may be added using the following request
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ecdsa-sha2-nistp256" |
"ecdsa-sha2-nistp384" |
"ecdsa-sha2-nistp521"
string ecdsa_curve_name
string ecdsa_public_key
mpint ecdsa_private
string key_comment
constraint[] key_constraints
ECDSA certificates may be added with:
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ecdsa-sha2-nistp256-cert-v01@openssh.com" |
"ecdsa-sha2-nistp384-cert-v01@openssh.com" |
"ecdsa-sha2-nistp521-cert-v01@openssh.com"
string certificate
mpint ecdsa_private_key
string key_comment
constraint[] key_constraints
RSA keys may be added with this request:
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ssh-rsa"
mpint rsa_n
mpint rsa_e
mpint rsa_d
mpint rsa_iqmp
mpint rsa_p
mpint rsa_q
string key_comment
constraint[] key_constraints
RSA certificates may be added with this request:
byte SSH2_AGENTC_ADD_IDENTITY or
SSH2_AGENTC_ADD_ID_CONSTRAINED
string "ssh-rsa-cert-v00@openssh.com"
string certificate
mpint rsa_d
mpint rsa_iqmp
mpint rsa_p
mpint rsa_q
string key_comment
constraint[] key_constraints
Note that the 'rsa_p' and 'rsa_q' parameters are sent in the reverse
order to the protocol 1 add keys message. As with the corresponding
protocol 1 "add key" request, the private key is overspecified to avoid
redundant processing.
For DSA, ECDSA and RSA key add requests, "key_constraints" may only be
present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED.
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
successfully added or a SSH_AGENT_FAILURE if an error occurred.
2.2.4 Loading keys from a smartcard
The OpenSSH agent may have optional smartcard support built in to it. If
so, it supports an operation to load keys from a smartcard. Technically,
only the public components of the keys are loaded into the agent so
this operation really arranges for future private key operations to be
delegated to the smartcard.
byte SSH_AGENTC_ADD_SMARTCARD_KEY or
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
string reader_id
string pin
constraint[] key_constraints
"reader_id" is an identifier to a smartcard reader and "pin"
is a PIN or passphrase used to unlock the private key(s) on the
device. "key_constraints" may only be present if the request type is
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED.
This operation may load all SSH keys that are unlocked using the
"pin" on the specified reader. The type of key loaded (protocol 1
or protocol 2) will be specified by the smartcard itself, it is not
client-specified.
The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
been successfully loaded or a SSH_AGENT_FAILURE if an error occurred.
The agent will also return SSH_AGENT_FAILURE if it does not support
smartcards.
2.3 Removing multiple keys
A client may request that an agent delete all protocol 1 keys using the
following request:
byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
This message requests the deletion of all protocol 2 keys:
byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES
On success, the agent will delete all keys of the requested type and
reply with a SSH_AGENT_SUCCESS message. If an error occurred, the agent
will reply with SSH_AGENT_FAILURE.
Note that, to delete all keys (both protocol 1 and 2), a client
must send both a SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES and a
SSH2_AGENTC_REMOVE_ALL_IDENTITIES request.
2.4 Removing specific keys
2.4.1 Removing a protocol 1 key
Removal of a protocol 1 key may be requested with the following message:
byte SSH_AGENTC_REMOVE_RSA_IDENTITY
uint32 key_bits
mpint1 rsa_e
mpint1 rsa_n
Note that key_bits is strictly redundant, as it may be inferred by the
length of rsa_n.
The agent will delete any private key matching the specified public key
and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
return SSH_AGENT_FAILURE.
2.4.2 Removing a protocol 2 key
Protocol 2 keys may be removed with the following request:
byte SSH2_AGENTC_REMOVE_IDENTITY
string key_blob
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for any of the supported protocol 2 key types.
The agent will delete any private key matching the specified public key
and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
return SSH_AGENT_FAILURE.
2.4.3 Removing keys loaded from a smartcard
A client may request that a server remove one or more smartcard-hosted
keys using this message:
byte SSH_AGENTC_REMOVE_SMARTCARD_KEY
string reader_id
string pin
"reader_id" the an identifier to a smartcard reader and "pin" is a PIN
or passphrase used to unlock the private key(s) on the device.
When this message is received, and if the agent supports
smartcard-hosted keys, it will delete all keys that are hosted on the
specified smartcard that may be accessed with the given "pin".
The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
been successfully removed or a SSH_AGENT_FAILURE if an error occurred.
The agent will also return SSH_AGENT_FAILURE if it does not support
smartcards.
2.5 Requesting a list of known keys
An agent may be requested to list which keys it holds. Different
requests exist for protocol 1 and protocol 2 keys.
2.5.1 Requesting a list of protocol 1 keys
To request a list of protocol 1 keys that are held in the agent, a
client may send the following message:
byte SSH_AGENTC_REQUEST_RSA_IDENTITIES
The agent will reply with the following message:
byte SSH_AGENT_RSA_IDENTITIES_ANSWER
uint32 num_keys
Followed by zero or more consecutive keys, encoded as:
uint32 bits
mpint1 rsa_e
mpint1 rsa_n
string key_comment
2.5.2 Requesting a list of protocol 2 keys
A client may send the following message to request a list of
protocol 2 keys that are stored in the agent:
byte SSH2_AGENTC_REQUEST_IDENTITIES
The agent will reply with the following message header:
byte SSH2_AGENT_IDENTITIES_ANSWER
uint32 num_keys
Followed by zero or more consecutive keys, encoded as:
string key_blob
string key_comment
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for any of the supported protocol 2 key types.
2.6 Private key operations
The purpose of the agent is to perform private key operations, such as
signing and encryption without requiring a passphrase to unlock the
key and without allowing the private key itself to be exposed. There
are separate requests for the protocol 1 and protocol 2 private key
operations.
2.6.1 Protocol 1 private key challenge
The private key operation used in version 1 of the SSH protocol is
decrypting a challenge that has been encrypted with a public key.
It may be requested using this message:
byte SSH_AGENTC_RSA_CHALLENGE
uint32 ignored
mpint1 rsa_e
mpint1 rsa_n
mpint1 encrypted_challenge
byte[16] session_id
uint32 response_type /* must be 1 */
"rsa_e" and "rsa_n" are used to identify which private key to use.
"encrypted_challenge" is a challenge blob that has (presumably)
been encrypted with the public key and must be in the range
1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1
session ID (computed from the server host key, the server semi-ephemeral
key and the session cookie).
"ignored" and "response_type" exist for compatibility with legacy
implementations. "response_type" must be equal to 1; other response
types are not supported.
On receiving this request, the server decrypts the "encrypted_challenge"
using the private key matching the supplied (rsa_e, rsa_n) values. For
the response derivation, the decrypted challenge is represented as an
unsigned, big-endian integer encoded in a 32 byte buffer (i.e. values
smaller than 2^248 will have leading 0 bytes).
The response value is then calculated as:
response = MD5(decrypted_challenge || session_id)
and returned in the following message
byte SSH_AGENT_RSA_RESPONSE
byte[16] response
If the agent cannot find the key specified by the supplied (rsa_e,
rsa_n) then it will return SSH_AGENT_FAILURE.
2.6.2 Protocol 2 private key signature request
A client may use the following message to request signing of data using
a protocol 2 key:
byte SSH2_AGENTC_SIGN_REQUEST
string key_blob
string data
uint32 flags
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for any of the supported protocol 2 key types. "flags" is
a bit-mask, but at present only one possible value is defined (see below
for its meaning):
SSH_AGENT_OLD_SIGNATURE 1
Upon receiving this request, the agent will look up the private key that
corresponds to the public key contained in key_blob. It will use this
private key to sign the "data" and produce a signature blob using the
key type-specific method described in RFC 4253 section 6.6 "Public Key
Algorithms".
An exception to this is for "ssh-dss" keys where the "flags" word
contains the value SSH_AGENT_OLD_SIGNATURE. In this case, a legacy
signature encoding is used in lieu of the standard one. In this case,
the DSA signature blob is encoded as:
byte[40] signature
The signature will be returned in the response message:
byte SSH2_AGENT_SIGN_RESPONSE
string signature_blob
If the agent cannot find the key specified by the supplied key_blob then
it will return SSH_AGENT_FAILURE.
2.7 Locking or unlocking an agent
The agent supports temporary locking with a passphrase to suspend
processing of sensitive operations until it has been unlocked with the
same passphrase. To lock an agent, a client send the following request:
byte SSH_AGENTC_LOCK
string passphrase
Upon receipt of this message and if the agent is not already locked,
it will suspend processing requests and return a SSH_AGENT_SUCCESS
reply. If the agent is already locked, it will return SSH_AGENT_FAILURE.
While locked, the agent will refuse all requests except
SSH_AGENTC_UNLOCK, SSH_AGENTC_REQUEST_RSA_IDENTITIES and
SSH2_AGENTC_REQUEST_IDENTITIES. The "request identities" requests are
treated specially by a locked agent: it will always return an empty list
of keys.
To unlock an agent, a client may request:
byte SSH_AGENTC_UNLOCK
string passphrase
If the passphrase matches and the agent is locked, then it will resume
processing all requests and return SSH_AGENT_SUCCESS. If the agent
is not locked or the passphrase does not match then it will return
SSH_AGENT_FAILURE.
Locking and unlocking affects both protocol 1 and protocol 2 keys.
3. Protocol message numbers
3.1 Requests from client to agent for protocol 1 key operations
SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
SSH_AGENTC_RSA_CHALLENGE 3
SSH_AGENTC_ADD_RSA_IDENTITY 7
SSH_AGENTC_REMOVE_RSA_IDENTITY 8
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
3.2 Requests from client to agent for protocol 2 key operations
SSH2_AGENTC_REQUEST_IDENTITIES 11
SSH2_AGENTC_SIGN_REQUEST 13
SSH2_AGENTC_ADD_IDENTITY 17
SSH2_AGENTC_REMOVE_IDENTITY 18
SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
SSH2_AGENTC_ADD_ID_CONSTRAINED 25
3.3 Key-type independent requests from client to agent
SSH_AGENTC_ADD_SMARTCARD_KEY 20
SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
SSH_AGENTC_LOCK 22
SSH_AGENTC_UNLOCK 23
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
3.4 Generic replies from agent to client
SSH_AGENT_FAILURE 5
SSH_AGENT_SUCCESS 6
3.5 Replies from agent to client for protocol 1 key operations
SSH_AGENT_RSA_IDENTITIES_ANSWER 2
SSH_AGENT_RSA_RESPONSE 4
3.6 Replies from agent to client for protocol 2 key operations
SSH2_AGENT_IDENTITIES_ANSWER 12
SSH2_AGENT_SIGN_RESPONSE 14
3.7 Key constraint identifiers
SSH_AGENT_CONSTRAIN_LIFETIME 1
SSH_AGENT_CONSTRAIN_CONFIRM 2
$OpenBSD: PROTOCOL.agent,v 1.7 2013/01/02 00:33:49 djm Exp $

Binary file not shown.

View File

@ -1,31 +0,0 @@
package main
import (
"code.google.com/p/go.crypto/ssh/agent"
"log"
"net"
"os"
)
func main() {
c, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
if err != nil {
log.Fatal(err)
}
defer c.Close()
agent := agent.NewClient(c)
log.Println("Listing agent keys")
log.Println("SSH")
keys, err := agent.List()
if err != nil {
log.Fatalf("Error listing keys: %s", err)
}
for _, k := range keys {
log.Printf("Key: %s", k.String())
log.Printf("Type: %s", k.Type())
}
}

Binary file not shown.

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAttE00a4G72DrFCOUhxlfxpTGCoIapwXlaTD3xUqNsjEPIkBg
4egRWIfLNThA89SaFoe0nAHzpvmVzDzLqiV1dlQZG9NQjudmAu/lRBTp26MLQgT9
yl7xFthyTOmkkysTwyS300DXrMjew9rjd7hc4qqxTorLI47lZtZPxdGh+jProOKW
KnVJfXw3hfRkp9Y3TAarhcV8brRdlzoroWgxPEiZETRrAkGD+o4DmJozOPoL6L05
ZAQ6PIY5IQ+oy0h9rkZ7hwAyUdqzod4EogD9mIAp4UrMQemYgMkxPGwSKHN/1KjU
70AcKDayNti8/sGbBig8w35Ju7YuJKWPDBiEFQIDAQABAoIBAAGZ53qGqazjDmwI
u75LLJmSqAFjjlQ0KwQ215S0yHTtFRLZuX+BBtXdqpv2uCrqi8byvVQ4eCfYO8Wk
Kqx804CL0AR8X1JBGJWiAEIOZNX1oZ2caZSiLD5k+utNiJF5aRzmb228PadXwwu4
GRHtXXLmx9LGSG0xTTUPX3d+FIsacYTuukgp73JF2YhNl1N1ThwCZINcYjyfOBHK
geDisw8yLIKLb5QCrMKWl1kS3Z6104JfBq00sjm3Yi7JjPfObepP9HXvUB8p0J6d
QYeHnqqqr2AkUiUBNXSt6GaxW0Mc5E/mnVzPa+jrKlIe2bmmQZt/lHJZsLT6F4Q0
OUdA2cECgYEAz6R7/B0VTLX4PdZ15vU4ao5bSxu3Gxe3IxVB1+PQLJklpBCc6npk
akrrt3STYgiWG+Dcz3cD3SKVs9oei5t8s2Db83XVfsBRNFFf9GIVncNc1ia+cJ7/
PDcLmmY1U0oByJr4xoyA4wYARuxS5MP3PljFoDCeaU4APX8GQgBgc7kCgYEA4WSn
LNUVPAR8CMf3926LQsnu7z3y6HkgmX/txUspb7ji3X1+eL/yKhIKsDFPppAUc/Tn
+W6ef7RtcZPFhA1HAiqvwvzAh6YUvnQ6NVzXqb1X73Ub1wf/kBK4pbuP9trOvR2f
b95iIq6qt22uDYaeGBqR6VDOdRe5Sbavlmv++T0CgYEAjE2NRWZ1bPcMPOR7mEqc
C0wTneWlTRYyNe94JSOXF3uH9psPHFUFItlq+vQ3XieFHmNLcJfvsW1cEEHTH+w5
T4+kL5awYswaUqqllqDsEETgpwdY6QpWVl6vZW2onJXGLMGiVa68rCny5/lpbZCI
sMUVDE+tymPdP7BkDxboFWkCgYEAwmf9pba41QaNMUnBgGKRrW7dLu+A57EqRBvK
qwR0Xg/bZe2LO31b05uyKlyt9d2KNqYDu+oEveOTDobFs2t8VssYxJcbPSUr+UXo
uwQ0ZAyTn0+kTqlwbgUnzJNlzibWcNnvHh9zB7UePI5WtQXqsKGiPtra6LYotALl
mlnWF4UCgYEAjFJG9KRuIUe9IzXI2XxA22/seaji9qy7/ojHHlo9iwQeb/OPJyp4
sCHS/qiMAfMU6r7OyOfnI51TsP3gr92/VKo/RoXn3mxCjFUXe3sIxsArOZ8f38DM
ww46KDGHFemUCeycnbjoZcnqO1V8Vdj6FFENPuq0UxS7NW+4dcxlfJE=
-----END RSA PRIVATE KEY-----

View File

@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC1jCCAcCgAwIBAgIRAOH/6qnnXARR27iWmrzfGAAwCwYJKoZIhvcNAQEFMBYx
FDASBgNVBAoTC0Jvb3QyRG9ja2VyMB4XDTE0MDgwNTA3MDc1NFoXDTE3MDcyMDA3
MDc1NFowFjEUMBIGA1UEChMLQm9vdDJEb2NrZXIwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQC20TTRrgbvYOsUI5SHGV/GlMYKghqnBeVpMPfFSo2yMQ8i
QGDh6BFYh8s1OEDz1JoWh7ScAfOm+ZXMPMuqJXV2VBkb01CO52YC7+VEFOnbowtC
BP3KXvEW2HJM6aSTKxPDJLfTQNesyN7D2uN3uFziqrFOissjjuVm1k/F0aH6M+ug
4pYqdUl9fDeF9GSn1jdMBquFxXxutF2XOiuhaDE8SJkRNGsCQYP6jgOYmjM4+gvo
vTlkBDo8hjkhD6jLSH2uRnuHADJR2rOh3gSiAP2YgCnhSsxB6ZiAyTE8bBIoc3/U
qNTvQBwoNrI22Lz+wZsGKDzDfkm7ti4kpY8MGIQVAgMBAAGjIzAhMA4GA1UdDwEB
/wQEAwIApDAPBgNVHRMBAf8EBTADAQH/MAsGCSqGSIb3DQEBBQOCAQEAqtoYLEuU
unbLo48zOHVSit3tIAnZ775HDy1WWK7zL1AzbB0WwT1nrB+SzR8lGzYmmPJB8sCH
rHBPpCF8MNqpZI8NOkS4ZcLF+WJhcZRnIsSz64lzFQThu2rAK7fhheAo3ONZYAYJ
DkZZrF7IMH3vMaQGZESBKuYiTstz+xMRTXxDQdgdpKZ1q2XB9wBeHLu6HRSh0cR4
0Ehs+NCFj50JkgzrxdXgSOlrSk2Icztb1MH89CuRPZNEbJbd1cU/kekxtkLzDtmX
Kai2FoHdonB1m5IfBJ7n2h5sexs73Qymohc4W81OZivdB/I+OixMjbc3Pn65KmWA
foD/K4Atw1090w==
-----END CERTIFICATE-----

View File

@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC+DCCAeKgAwIBAgIQHxTMkfKCDjxUR1lji0Hs/TALBgkqhkiG9w0BAQUwFjEU
MBIGA1UEChMLQm9vdDJEb2NrZXIwHhcNMTQwODA1MDYwMTU0WhcNMTcwNzIwMDYw
MTU0WjAWMRQwEgYDVQQKEwtCb290MkRvY2tlcjCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBALgW92LOxgrH59EoMJTsBDuKp2w2vOaY+WT4UduqxWTtPaQv
aeGmK4/1T562prRIG/dH9IR/wYR3fYXKUkcHP6FaPTUnGEhUcnjg8vFMwoYnGLUo
nCBK0HiZMPKkjnWzkiVJgdpQt3pLIRAomT0ehtP6LfMsrJoof8MCI+anu450hV/6
VATtmxy8FnivfiLFlroolPXKp5kQck7nJBhsIOY4BDT8qgehGXtpJuqZaBrhCY2S
7sAzIZtemWYFQNvwJDsMmsMNBMur4SwA/kST0kTlczH2vI423CeTa2PsrZmoFQvt
whohfdLTH1Ul3bbtCPnDD2StkqUs9/JTigyEaj8CAwEAAaNGMEQwDgYDVR0PAQH/
BAQDAgCgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDwYDVR0R
BAgwBocEfwAAATALBgkqhkiG9w0BAQUDggEBAISM38fkqTAg5lP/fpgW6vmNNW+U
VeQ/ZlXwQxzu+gmIli+PgPy/QM98xxs+SR3NwWTlh5yHDKHYPbmc1FRV5q8U1zvf
DqDmyDEQTMCwWMOBRKwfGcmzV4WlZvxR96XQEpo0zfP61eMo7ditRraDD1PMBNGv
4QqGJADKKHfqm53eS1tzd0MSBteah59OYLzF0hjXT/NL9P00XaotRznFmsjmura6
0Xs6EKrudPTAdfCWBwundclq7d9BofU8/kBKwE8J7zCI6KA3fpGMutMojVIopIFO
Bowka1TKV+2+8Nt1gqIvpvlX4E119BemIA/m9uZiSdYahffHniKBFiXsr8Y=
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAvv7GjStV0fiOc1wf1hm2B3YGwTp6W0gCpYpOqEotetVOBf5c
/9qbn4ihOZJK2GY69z6SchttmAL87EfhzFQjDifv0skjKHJkspyi80OJYeM+Tlj8
4kHI3WXkD9K9UPO3JGkeNrTjOKIXbcQDOgYkDl6wYW6bdSIEyjxQ4+0jTZX0wYD4
anSNJJXYA9UWq8B0GiwIrRF1378AjZzGyOuBhw1nj6AfAgsgVmNPu+Dh/5nteKEe
HVz+iUOsiUmzZQ/4y+XxyFqe00+6gzF7dN18cRLatj9ifIsiSyEZUeF0vsqKyzG4
HVG9o2R5uZoBOvyNMpUlxv9dVaSqCjHB3rELmwIDAQABAoIBAQCS6072lug8TXPe
v3Xp7vs8QAkwKHiosPsANiUNhYn4nA6Zw7HsSlA95w8GR0d1sSYYvLRQPFMQhPPk
GeNSl0IkCIqN3ZVC7sQRNTaP5FrQxspN4Fwe+7W0wUUu+tAQbnlp88Z/FKRZEy7s
i8RjpQelWidZu4iwEMwYeU9MFUV7ztK5U+9NScu8d4svVbqZuBDrZiofBD++MYN4
SvIzXCku+r67W2nN1a94/87MWGTUr8oGWbkvRIJ/23ifnvL7cQeqJ08VPr8BIj5w
4su14xpITXEH02WpgTruEDrk2DO6wfoqAGJ/fZHRkDVIFSXd5miwurKQmL1Iursk
FU98mPsBAoGBAOldZ9HDFX69+XGW4u80qkkaCHGrrKRDSHA1HfNEOu1nhyMD1vXW
8xwOJ5H8yBrEMTSP2N8bdeEp8m/aKuleUpzIjxNyIbiw0m4v3p+lpbgEVKfC8L/B
umU4HtRYgujvOfUFWEnvonQh9k1J/N5Ym93xXgs4WXzRG2ABeEmlsjGBAoGBANGF
Ti2MdQYXf51Hgsw9oADiyEimbw6wEsLvK1sSA+lscTCyBdZyD+5PntnC5jcUtg1p
moVFxHkyatVE3TffchTwjPgKAv0zKh3e6w9mJhRd1c9vNaTiIqPr0MyaftrZ1tSH
DnAK8Lisd3zODaVawbPyOBPFfUnqWzYqIsPpWVMbAoGBAJOuWr8yV+4HR06NEDwU
9hag9OsKm4ywT61C0Btc+HW46JpOGcEmMF92za/jarcVpZX/2l0GwcimhRgn1rQs
ztcNTQ4fUhvROrokbRxW9dLIWtJ32WdgsBbSNyBmiyHiEqluonrXvdUEkRxEUFRd
evYvgzZSiL8mjc5p37ertmMBAoGAWAuAsrtXYdv2EI3AdTtgRX8HUyA9gxqSh8Ah
o/+KDUk4t5HXyincb/SdeDziqTrW1gQOnvqWeaeqJTzvCU+ojQwY8RKj9urNRAgt
FyeB0QUtmCHPlR5CGEg8Uf6KWEU6dczbUFIInlI7VALy0Q22YHvk/Mn8wFbvRW+n
dFRW6QkCgYEAtOoFUZSlJkU6LleX+M7dS6Jbd44SbCb+acirbl6eHKxEDLL2+MRM
qZui45SqnCFnyWo8cgW4xqFeJVGoeTDFZK65Qup1IsBlrPODmTes5cSMPGdZ3brG
BVCVcmuygGkMC/tGOmydVStZx0Spt0va96p/Na2x4akdscZKVTCCap4=
-----END RSA PRIVATE KEY-----

View File

@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC4DCCAcqgAwIBAgIRAJ6X6zjqpxM03GqlIXCYtpIwCwYJKoZIhvcNAQEFMBYx
FDASBgNVBAoTC0Jvb3QyRG9ja2VyMB4XDTE0MDgwNTA3MDc1OFoXDTE3MDcyMDA3
MDc1OFowFjEUMBIGA1UEChMLQm9vdDJEb2NrZXIwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQC+/saNK1XR+I5zXB/WGbYHdgbBOnpbSAKlik6oSi161U4F
/lz/2pufiKE5kkrYZjr3PpJyG22YAvzsR+HMVCMOJ+/SySMocmSynKLzQ4lh4z5O
WPziQcjdZeQP0r1Q87ckaR42tOM4ohdtxAM6BiQOXrBhbpt1IgTKPFDj7SNNlfTB
gPhqdI0kldgD1RarwHQaLAitEXXfvwCNnMbI64GHDWePoB8CCyBWY0+74OH/me14
oR4dXP6JQ6yJSbNlD/jL5fHIWp7TT7qDMXt03XxxEtq2P2J8iyJLIRlR4XS+yorL
MbgdUb2jZHm5mgE6/I0ylSXG/11VpKoKMcHesQubAgMBAAGjLTArMA4GA1UdDwEB
/wQEAwIAoDAMBgNVHRMBAf8EAjAAMAsGA1UdEQQEMAKCADALBgkqhkiG9w0BAQUD
ggEBAKXqTtDj/F2AJj55trGsk/fc3LtYTOeq0I9JB45hNOjpixpBdsS1VxkxdTM5
3wgUVEUyjQzBWtSBO5jRrDjOHsXqtqh83+Jh+GwUAf3mncGSss7JJ78kYe4zBxSi
tgMc3KUi82ppoeiB0xsaEXfBRf6U+wJNVATpabJPeveMhaRVAd9gE5aLWrkZ09+b
wR5y4YXZ0LncqWYnq03BAPn0eTDWgzJvXaSSyE9wFF847T9XRicwzsgTNXzqb4PU
5s23GHfkIIv6PQzOUSpYTyCVWBdOk2qnhyUkeYCX+ZfwvJlb2NIwQjMwaysX6ZdJ
T2q+prcDXnzOhwpsqUbTOD8RxOM=
-----END CERTIFICATE-----

View File

@ -1,173 +0,0 @@
// Usage:
// Generate CA
// ./generate_cert --cert ca.pem --key ca-key.pem
// Generate signed certificate
// ./generate_cert --host 127.0.0.1 --cert cert.pem --key key.pem --ca ca.pem --ca-key ca-key.pem
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"log"
"math/big"
"net"
"os"
"strings"
"time"
)
var (
host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
certFile = flag.String("cert", "", "Output file for certificate")
keyFile = flag.String("key", "", "Output file for key")
ca = flag.String("ca", "", "Certificate authority file to sign with")
caKey = flag.String("ca-key", "", "Certificate authority key file to sign with")
)
const (
RSABITS = 2048
VALIDFOR = 1080 * 24 * time.Hour
ORG = "Boot2Docker"
)
func main() {
flag.Parse()
if *certFile == "" {
log.Fatalf("Missing required parameter: --cert")
}
if *keyFile == "" {
log.Fatalf("Missing required parameter: --key")
}
if *ca == "" {
if *caKey != "" {
log.Fatalf("Must provide both --ca and --ca-key")
}
if err := GenerateCA(*certFile, *keyFile); err != nil {
log.Fatalf("Failured to generate CA: %s", err)
}
} else {
if err := GenerateCert(strings.Split(*host, ","), *certFile, *keyFile, *ca, *caKey); err != nil {
log.Fatalf("Failured to generate cert: %s", err)
}
}
}
// newCertificate creates a new template
func newCertificate() *x509.Certificate {
notBefore := time.Now()
notAfter := notBefore.Add(time.Hour * 24 * 1080)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
log.Fatalf("failed to generate serial number: %s", err)
}
return &x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{ORG},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
//ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
}
// GenerateCA generates a new certificate authority
// and stores the resulting certificate and key file
// in the arguments.
func GenerateCA(certFile, keyFile string) error {
template := newCertificate()
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign
priv, err := rsa.GenerateKey(rand.Reader, RSABITS)
if err != nil {
return err
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv)
if err != nil {
return err
}
certOut, err := os.Create(certFile)
if err != nil {
return err
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close()
return nil
}
// GenerateCert generates a new certificate signed using the provided
// certificate authority files and stores the result in the certificate
// file and key provided. The provided host names are set to the
// appropriate certificate fields.
func GenerateCert(hosts []string, certFile, keyFile, caFile, caKeyFile string) error {
template := newCertificate()
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, h)
}
}
tlsCert, err := tls.LoadX509KeyPair(caFile, caKeyFile)
if err != nil {
return err
}
priv, err := rsa.GenerateKey(rand.Reader, RSABITS)
if err != nil {
return err
}
x509Cert, err := x509.ParseCertificate(tlsCert.Certificate[0])
if err != nil {
return err
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, x509Cert, &priv.PublicKey, tlsCert.PrivateKey)
if err != nil {
return err
}
certOut, err := os.Create(certFile)
if err != nil {
return err
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close()
return nil
}

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAuBb3Ys7GCsfn0SgwlOwEO4qnbDa85pj5ZPhR26rFZO09pC9p
4aYrj/VPnramtEgb90f0hH/BhHd9hcpSRwc/oVo9NScYSFRyeODy8UzChicYtSic
IErQeJkw8qSOdbOSJUmB2lC3ekshECiZPR6G0/ot8yysmih/wwIj5qe7jnSFX/pU
BO2bHLwWeK9+IsWWuiiU9cqnmRByTuckGGwg5jgENPyqB6EZe2km6ploGuEJjZLu
wDMhm16ZZgVA2/AkOwyaww0Ey6vhLAD+RJPSROVzMfa8jjbcJ5NrY+ytmagVC+3C
GiF90tMfVSXdtu0I+cMPZK2SpSz38lOKDIRqPwIDAQABAoIBAC6B9tvqm1Pr7yAD
RErLWcJlJCkNpymm6hLdPWj+usHlwdXx+JD+dzD2a7gQMwuG0DHn5tl2oUBDI94i
ICk7ppKwBpigGN1lIEpzokzd9KMJy48xBEiQPhzJrvkOI8OOq1RqPrkV/VSTGHZJ
m3U6ehuhr+wolC6aHrT4nHNQWu0BCqnLqbiwo1cDfH8bgKD+EF6uRZHuZOITFkY2
rMhhI/gkVwVjDbyyJhIDALUkV3ovpZ4L+P9+8XJd7s6Y8gZjI9Ti2z8X2sUny4NS
zbLuWYOaeHdFuGzTvFf48YNnB1sf8R/f/n3DkgDos+FkPLmTO0MNnXPmBB3R+B6R
KzuLdikCgYEA85rRBuUsp3rNxxck4rNYIVg4/TcGUcQ959MrSadnB8QOJdBGUash
XitPzHaAMYwsFAyb36qdhGtmqTQHtjYIl6alehN5g1g/clFceFu4riocdd/KKvVe
qe6GagJx8BVDR8Oon61CRbi4/0LhYYfbf4ezN1PKbxlkfa5WMDtoH3MCgYEAwXTo
7RH8ue9J5cSmtImX9Q3YVZy4gooYp4/teFX+da7cT2RbAsDoxFMY9Ka0ORHOFl1c
74UIlqB2VdUhitgLWuqLhcaFFPyTbsJsuKi8RcP7sAA1YviweOsehBq7zpmaR7oF
Ldb8It2W37PjIt1C2M5muyztd5FRLP63c5CnvwUCgYAK17g4C1lKdw/TrbcJlBv3
F/spYhqY5xguSlrh416VnOdYTYXjuq84hsr9ecTI78lCdzE06l4qd7FRFKzHMm59
eYBiB53f97yTNQXdoY99yQgNQxG3icZV3/UBoOw7WGbvOck2mjqZ6dfqHKr1cVuW
uI6Ehuk6urGbWnghm3NN+wKBgQCkuSJYMleqDnkyvsZftUUBcP+CrkZhSKsDikbe
jwJzPCf1JfNkndPUzxjRwFx2t5Vub6Lhg7ozX4BDR44fBiRtDocsqkPJAeObjMs8
VNiy4tSdISBUHINPAoxiWc0OdrXqWxdr18GrAlkkM6y0lAgGSYEp4XB1vfOLx3t3
WHWs7QKBgQCkTGUse1vFTfCzA5rTFzBWJM7bdaUCIymU2BQPbRFSgdx3kKbmnrab
fOLOaVxMWAOAJ7PF1LlOyUlesLEJzqO+pYgRgnG3d6qz99Ytz3sk7uzVr3n/Ic68
TwYlXLHGQmP7OyR2tMPVI0rSb5g5lbRdCOqMbHN+6ce10KcibdBF/g==
-----END RSA PRIVATE KEY-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqS5MaKMuR9OWhPbGw/tc1JmJgtEtNp5dSx5hlPEkSY8dsi5Z
uFZvCqYK7uaNUlap4/ytlFDIozOnZs+MrgcM5Ek/nPNtol+pts777H3Xo3oChRnc
X1/JXQ1tdVTT//LvUJmtkg6V6+iORuMnTMpia+Sl+7cgdW3EElfzPMY8J9RIUPBE
NyedJyp3K+RM/m+KOzmYqkHcrKhhblbjLOr5a0zu+D8ilCG87QDAUUf1gbXOUi/S
CYH/9v20sUbPqHr8Z1wuJLeNvKPFrdC2+mtJyhqyMaH7tgsyKOmqeHxQlkNbril2
tvZRAzqaTDDYMfJDKAwEk345CJW1avkk6GBc2wIDAQABAoIBAHJGn74eW2iQ958g
weono/DHNSdz+8Jk/kd7YhalPAmj7j8pJ9loKOFcfw4YFWWEvIUPbIA+gQgcH/tG
PpRelsqs35c4ptmDHLQq4+g+qKX4CDO34C9cGDwOkd0rS3gbtKMQ6zk5OPN8xn4D
ecxY+FpAvA1nCTnIxyRM3DQ1AvUzSe+UpLtdc/vliCJiFVpAtpok6fVo/Cxevf51
dU1BIgZcJjsmro2/GR7e7l4c0C+ZHV0Perkdfw1fqZvpj0u3ca1dfwuWUVGc7VYf
v7D5aFH8tw5bGHdM2ajPn3mpgJ+BNuIOdG1ipiUmrv4NoWNmyd2on9+Jy+2tILOx
dcPKqwECgYEAz5/Y6qUuhp+23t4hynbD1YCX4RZtwtuqUef7BxeaRSocQrK15zlZ
iOYeZe7/F6b/ueuN9q64lQBy8HvtWphNifhaXAW7SVwrzNDnbZWFVaQB7+Srj53u
/sOgEKDgi5LoEUH4aQV1prMyajWNGkBX0lmdGELkyisTvvsu/BN8S/sCgYEA0Jlp
lO0rT5xUsM0EsQvPmgSz3/+bGEgmmNoBt2Fnp7JuVsfJQDujFUvi2tQ2seDbVupc
+LSbPudIUIdPch450IGQSZFLiN7fAePMXIUdUuZ6amHEz6+dtdl+kjlzUmmE7/VP
M/o8A0F0Qkn3LoU6yH8fesJ9p6JCzIpJSJuFfKECgYA0v32Sj4i0dxs0n+ah026J
bXQooVQdb0VkLbWe5aYx8DLh1xlTt0RB/YS3jPKOBcVubKPSii0m3chVxIZWv97j
MI90VZhxWNNf46sIMjZ/vX0of0X+5Lb1Tqn5z4V8sEP5LnN36wUq5tfmF9jTVIl7
TX0Vztjla/BGUvZq4GBxxQKBgEyXN5QN7OwjK1lrPYDAJG6ZsW3ajRjCTSGsUhsB
8aw6MJc+bd9exkdogJf2eUqglAh6rr5GmgXjp8KhnAL7pCCxocfRSFmt81XfTUbf
PWAV7fanhTr4cUC25elMnNIymjP87yLXizdqzgQU4mQ7WNULEATj6n0lb79oOvYk
3ENhAoGBAKjsl7MDi7WokpshGkEIPTxccefWPPx6wtdvDw1Yy6nrc/4KapsIvRZc
u9r9GBEodxOFbuPKFqsTehpMuSMaWuPhHs6txP3/q1q58rpeqmXD29zcdDTuHJoS
ZKqBPsot328/q38DwqavP9PZsuLQ/M95uXwYR4tnNnbbQwDqn61B
-----END RSA PRIVATE KEY-----

View File

@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC5DCCAc6gAwIBAgIRAL3D43hlFPxMmrICmKJjxn4wCwYJKoZIhvcNAQEFMBYx
FDASBgNVBAoTC0Jvb3QyRG9ja2VyMB4XDTE0MDgwNTA3MTAwM1oXDTE3MDcyMDA3
MTAwM1owFjEUMBIGA1UEChMLQm9vdDJEb2NrZXIwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCpLkxooy5H05aE9sbD+1zUmYmC0S02nl1LHmGU8SRJjx2y
Llm4Vm8Kpgru5o1SVqnj/K2UUMijM6dmz4yuBwzkST+c822iX6m2zvvsfdejegKF
GdxfX8ldDW11VNP/8u9Qma2SDpXr6I5G4ydMymJr5KX7tyB1bcQSV/M8xjwn1EhQ
8EQ3J50nKncr5Ez+b4o7OZiqQdysqGFuVuMs6vlrTO74PyKUIbztAMBRR/WBtc5S
L9IJgf/2/bSxRs+oevxnXC4kt428o8Wt0Lb6a0nKGrIxofu2CzIo6ap4fFCWQ1uu
KXa29lEDOppMMNgx8kMoDASTfjkIlbVq+SToYFzbAgMBAAGjMTAvMA4GA1UdDwEB
/wQEAwIAoDAMBgNVHRMBAf8EAjAAMA8GA1UdEQQIMAaHBMCoO2gwCwYJKoZIhvcN
AQEFA4IBAQC0ttuFbfSrzGdDcO/442nfpzQdO9wN0nee5OazHHTZlA+SaQ4VyZoS
LeCdP+rRPIX0qmJ0Bf95nvkL7Mideg6IQsTTWz3e2pfcIdSZ1Gc9Bzx4cGf2yWWt
mwi2uLAbAOKznNh8Ndc45zG614QYo3Cli/p91y+zJyDhS3ucERGCwC9ru+ngHBp4
KrAfH4AUNRi5JRt0vHn3MXbl8Xmymt5FHeOtEM9iXCFBMtejYcngceOz8bRPXke2
86TExl86jIHjAItEqydANhG7wNIylNOdXGCgQ4yQX1ImNiY2I4n7FeLh8vu8nCbR
zwPv/s2m4xsr4ilA6xLq9Ur8K7FK4Q4a
-----END CERTIFICATE-----

View File

@ -1,9 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBNTCB3KADAgECAgEAMAoGCCqGSM49BAMCMBIxEDAOBgNVBAMTB0NBIFJvb3Qw
HhcNMTQwOTIyMTYzNzU4WhcNMTQwOTI5MTYzNzU5WjASMRAwDgYDVQQDEwdDQSBS
b290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaS6UJn72kZaD1U1+9wXVFtk/
lqSOzq+snB6qslXpLE2C+6N1NjDoivZ87CPzJt6VYgeS+iZ63+AlH5Uiz+q1SKMj
MCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwID
SAAwRQIhALxyd72Aev/IAvXZpx7TLbLrGMrZGTEMjXMi1Gda9MAFAiA82SUmu3dR
9d0VWY74lOlHsojsoi3keb4PeOMyyFFFaQ==
-----END CERTIFICATE-----

View File

@ -1,10 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBPTCB5KADAgECAgEAMAoGCCqGSM49BAMCMBcxFTATBgNVBAMTDEludGVybWVk
aWF0ZTAeFw0xNDA5MjIxNjM3NThaFw0xNDA5MjkxNjM3NTlaMBUxEzARBgNVBAMT
ClRydXN0IENlcnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASR+jpYA6SPRkq+
2B9FH23Qrqgsn2ScgfiU73PN9Kgn0xyStp2RHoDhyKoQKU5T1TPOdWxVan3+ljUx
/O/1pKdSoyMwITAOBgNVHQ8BAf8EBAMCAIAwDwYDVR0TAQH/BAUwAwEB/zAKBggq
hkjOPQQDAgNIADBFAiEA2NpSs22EiYwbZlkjcVuAryJlBbnRzYvX7IIkk9fSRYQC
IH4YfZC3tvUWFxc4Spvic2uCHazAu+0Fzjs53OJxwirZ
-----END CERTIFICATE-----
---

View File

@ -1,45 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBPzCB5qADAgECAgEAMAoGCCqGSM49BAMCMBcxFTATBgNVBAMTDEludGVybWVk
aWF0ZTAeFw0xNDA5MjIxNjM3NThaFw0xNDA5MjkxNjM3NTlaMBcxFTATBgNVBAMT
DEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMac+uvHxGGH
xCisqvN5+ZO6w9Q3BlPXu5r2GVXmo07DX15Dj894S4ByNMo8iluDyqK/8JS/1cq1
S+Q0CE6yRw6jIzAhMA4GA1UdDwEB/wQEAwIABjAPBgNVHRMBAf8EBTADAQH/MAoG
CCqGSM49BAMCA0gAMEUCIDHx2NPcyo4JiBKFRdCZiLTyncBDJIlWzOhprFbmm914
AiEAjbxeVHWiO+Q/7nzQXpGzsnszaMdmL1LLSQuTf9MX+bc=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBPzCB5qADAgECAgEAMAoGCCqGSM49BAMCMBcxFTATBgNVBAMTDEludGVybWVk
aWF0ZTAeFw0xNDA5MjIxNjM3NThaFw0xNDA5MjkxNjM3NTlaMBcxFTATBgNVBAMT
DEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJJo+KFt18Og
0hbUmxnxBTBHg0FIxlWJMac1iNnqlH6hnPZf1a1uJJm/iNZNPxd+jHh+ZjInvTmU
Fg7DiDXiyuOjIzAhMA4GA1UdDwEB/wQEAwIABjAPBgNVHRMBAf8EBTADAQH/MAoG
CCqGSM49BAMCA0gAMEUCIHGyXQESb6pph5gz4ppgfD4br9F5TYM2/Fap+IK1Jhm1
AiEAxamUnj4AWIHut2T5R3Xg2tn0q5JDtsB3drZ/MXoMepI=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBPzCB5qADAgECAgEAMAoGCCqGSM49BAMCMBcxFTATBgNVBAMTDEludGVybWVk
aWF0ZTAeFw0xNDA5MjIxNjM3NThaFw0xNDA5MjkxNjM3NTlaMBcxFTATBgNVBAMT
DEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNIvT/bkf6rm
RYNE5e53izqdm9HHSBXlSFQGWShDrmYmlJbJrzE7gdd6dWMaTi3TzUGJzVcvASNJ
/tkZZW2uMaKjIzAhMA4GA1UdDwEB/wQEAwIABjAPBgNVHRMBAf8EBTADAQH/MAoG
CCqGSM49BAMCA0gAMEUCIQCYu0lvqmvj+99qiyOc/vJWhT/oIKUu+h8dIU3bULt1
AwIgKiMptAa9IJfXa+VvleIdWpdldJa5g1OvRaP+ANQ/MGA=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBPjCB5qADAgECAgEAMAoGCCqGSM49BAMCMBcxFTATBgNVBAMTDEludGVybWVk
aWF0ZTAeFw0xNDA5MjIxNjM3NThaFw0xNDA5MjkxNjM3NTlaMBcxFTATBgNVBAMT
DEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKx0nRr6QlXX
xYLe1+BmJkI3moUdYxJr/6xfhnqJTPhk7UR8/h69BlAX7PE5Cp1j7q4bCoAAdARN
csjpOKn1tpOjIzAhMA4GA1UdDwEB/wQEAwIABjAPBgNVHRMBAf8EBTADAQH/MAoG
CCqGSM49BAMCA0cAMEQCIConoQP4XuaCoobZD3v0t0/WROD/wVDUBu5xILa8sSKe
AiBJCWa8cXi2U6z6cc/RKcRaDOTmL+1Cs38aRUiU/+VCPw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBOjCB4aADAgECAgEAMAoGCCqGSM49BAMCMBIxEDAOBgNVBAMTB0NBIFJvb3Qw
HhcNMTQwOTIyMTYzNzU4WhcNMTQwOTI5MTYzNzU5WjAXMRUwEwYDVQQDEwxJbnRl
cm1lZGlhdGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQsGtLo05ztLyhrzzMu
bziiYR7Y1qxhm6DlV9kaa7DHyuLpNOsEKNkW6gx/9g1AxVfDv2dcuoqnCErawdab
+jgDoyMwITAOBgNVHQ8BAf8EBAMCAAYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjO
PQQDAgNIADBFAiEAy+WumOj7I8iIhQNf+NQfV+LNBBoy4ufeeyaPGcRG3hICIFMW
th+PDs1HgdeQvG1tPP9d7TBfMu7k1lVlCf7KcvKN
-----END CERTIFICATE-----

View File

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIDmjTNf5Q5kuGCFrfsa60qLUKZDoSuIgS+GKOb9vRWFJoAoGCCqGSM49
AwEHoUQDQgAEkfo6WAOkj0ZKvtgfRR9t0K6oLJ9knIH4lO9zzfSoJ9MckradkR6A
4ciqEClOU9UzznVsVWp9/pY1Mfzv9aSnUg==
-----END EC PRIVATE KEY-----

View File

@ -1,161 +0,0 @@
package main
import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"log"
"math/big"
"os"
"time"
"github.com/docker/libtrust"
)
func generateTrustCA() (libtrust.PrivateKey, *x509.Certificate) {
key, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
panic(err)
}
cert := &x509.Certificate{
SerialNumber: big.NewInt(0),
Subject: pkix.Name{
CommonName: "CA Root",
},
NotBefore: time.Now().Add(-time.Second),
NotAfter: time.Now().Add(24 * 7 * time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
}
certDER, err := x509.CreateCertificate(
rand.Reader, cert, cert,
key.CryptoPublicKey(), key.CryptoPrivateKey(),
)
if err != nil {
panic(err)
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
panic(err)
}
return key, cert
}
func generateIntermediate(key libtrust.PublicKey, parentKey libtrust.PrivateKey, parent *x509.Certificate) *x509.Certificate {
cert := &x509.Certificate{
SerialNumber: big.NewInt(0),
Subject: pkix.Name{
CommonName: "Intermediate",
},
NotBefore: time.Now().Add(-time.Second),
NotAfter: time.Now().Add(24 * 7 * time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
}
certDER, err := x509.CreateCertificate(
rand.Reader, cert, parent,
key.CryptoPublicKey(), parentKey.CryptoPrivateKey(),
)
if err != nil {
panic(err)
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
panic(err)
}
return cert
}
func generateTrustCert(key libtrust.PublicKey, parentKey libtrust.PrivateKey, parent *x509.Certificate) *x509.Certificate {
cert := &x509.Certificate{
SerialNumber: big.NewInt(0),
Subject: pkix.Name{
CommonName: "Trust Cert",
},
NotBefore: time.Now().Add(-time.Second),
NotAfter: time.Now().Add(24 * 7 * time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
certDER, err := x509.CreateCertificate(
rand.Reader, cert, parent,
key.CryptoPublicKey(), parentKey.CryptoPrivateKey(),
)
if err != nil {
panic(err)
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
panic(err)
}
return cert
}
func generateTrustChain(key libtrust.PrivateKey, ca *x509.Certificate) (libtrust.PrivateKey, []*x509.Certificate) {
parent := ca
parentKey := key
chain := make([]*x509.Certificate, 6)
for i := 5; i > 0; i-- {
intermediatekey, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
panic(err)
}
chain[i] = generateIntermediate(intermediatekey, parentKey, parent)
parent = chain[i]
parentKey = intermediatekey
}
trustKey, err := libtrust.GenerateECP256PrivateKey()
if err != nil {
panic(err)
}
chain[0] = generateTrustCert(trustKey, parentKey, parent)
return trustKey, chain
}
func main() {
caKey, caCert := generateTrustCA()
key, chain := generateTrustChain(caKey, caCert)
caf, err := os.OpenFile("ca.pem", os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
log.Fatalf("Error opening ca.pem: %s", err)
}
defer caf.Close()
pem.Encode(caf, &pem.Block{Type: "CERTIFICATE", Bytes: caCert.Raw})
chainf, err := os.OpenFile("chain.pem", os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
log.Fatalf("Error opening ca.pem: %s", err)
}
defer chainf.Close()
for _, c := range chain[1:] {
pem.Encode(chainf, &pem.Block{Type: "CERTIFICATE", Bytes: c.Raw})
}
certf, err := os.OpenFile("cert.pem", os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
log.Fatalf("Error opening ca.pem: %s", err)
}
defer certf.Close()
pem.Encode(certf, &pem.Block{Type: "CERTIFICATE", Bytes: chain[0].Raw})
err = libtrust.SaveKey("key.pem", key)
if err != nil {
log.Fatalf("Error saving key: %s", err)
}
}

View File

@ -1 +0,0 @@
LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL derek

View File

@ -1,184 +0,0 @@
package main
import (
"bufio"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"flag"
"io/ioutil"
"log"
"os"
"strings"
"github.com/docker/libtrust"
)
var ca string
var chain string
var cert string
var signKey string
var validKeys string
func init() {
flag.StringVar(&ca, "ca", "", "Certificate authorities (pem file)")
flag.StringVar(&chain, "chain", "", "Certificate chain to include (pem file)")
flag.StringVar(&cert, "cert", "", "Certificate used to sign")
flag.StringVar(&signKey, "k", "", "Private key to use for signing (pem or JWS file)")
flag.StringVar(&validKeys, "keys", "", "File containing list of valid keys and namespaces")
}
func LoadValidKeys(filename string) (map[string][]string, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
validKeys := make(map[string][]string)
r := bufio.NewScanner(f)
for r.Scan() {
parts := strings.Split(r.Text(), " ")
if len(parts) < 2 {
return nil, errors.New("Invalid line input: expecting <KeyId> <namespace> ...")
}
validKeys[parts[0]] = parts[1:]
}
return validKeys, nil
}
func main() {
flag.Parse()
if ca == "" {
log.Fatal("Missing ca")
}
if chain == "" {
log.Fatalf("Missing chain")
}
if cert == "" {
log.Fatalf("Missing certificate")
}
if signKey == "" {
log.Fatalf("Missing key")
}
if validKeys == "" {
log.Fatalf("Missing valid keys")
}
caPool, err := libtrust.LoadCertificatePool(ca)
if err != nil {
log.Fatalf("Error loading ca certs: %s", err)
}
chainCerts, err := libtrust.LoadCertificateBundle(chain)
if err != nil {
log.Fatalf("Error loading chain certificates; %s", err)
}
chainPool := x509.NewCertPool()
for _, cert := range chainCerts {
chainPool.AddCert(cert)
}
signCert, err := tls.LoadX509KeyPair(cert, signKey)
if err != nil {
log.Fatalf("Error loading key: %s", err)
}
if signCert.Certificate == nil {
log.Fatalf("Signed Cert is empty")
}
validKeyMap, err := LoadValidKeys(validKeys)
if err != nil {
log.Fatalf("Error loading valid keys: %s", err)
}
verifyOptions := x509.VerifyOptions{
Intermediates: chainPool,
Roots: caPool,
}
parsedCert, err := x509.ParseCertificate(signCert.Certificate[0])
if err != nil {
log.Fatalf("Error parsing certificate: %s", err)
}
chains, err := parsedCert.Verify(verifyOptions)
if err != nil {
log.Fatalf("Error verifying certificate: %s", err)
}
if len(chains) == 0 {
log.Fatalf("No verified chains")
}
content, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("Error reading content from stdin: %s", err)
}
sig, err := libtrust.ParsePrettySignature(content, "signatures")
buildKeys, err := sig.Verify()
if err != nil {
log.Fatalf("Error verifying signatures: %s", err)
}
type manifest struct {
Name string `json:"name"`
Tag string `json:"tag"`
}
var buildManifest manifest
payload, err := sig.Payload()
if err != nil {
log.Fatalf("Error retrieving payload: %s", err)
}
err = json.Unmarshal(payload, &buildManifest)
if err != nil {
log.Fatalf("Error unmarshalling build manifest: %s", err)
}
log.Printf("Build keys: %#v", buildKeys)
// Check keys against list of valid keys
var foundKey bool
for _, key := range buildKeys {
keyID := key.KeyID()
log.Printf("Checking key id: %s", keyID)
namespaces, ok := validKeyMap[keyID]
if ok {
for _, namespace := range namespaces {
if namespace == "*" || strings.HasPrefix(buildManifest.Name, namespace) {
foundKey = true
}
}
}
}
if !foundKey {
log.Fatalf("No valid key found for build")
}
verifiedSig, err := libtrust.NewJSONSignature(content)
if err != nil {
log.Fatalf("Error creating JSON signature: %s", err)
}
privKey, err := libtrust.FromCryptoPrivateKey(signCert.PrivateKey)
if err != nil {
log.Fatalf("Error converting priv key: %s", err)
}
signChain := make([]*x509.Certificate, 1, len(chainCerts)+1)
signChain[0] = parsedCert
err = verifiedSig.SignWithChain(privKey, append(signChain, chainCerts...))
if err != nil {
log.Fatalf("Error signing with chain: %s", err)
}
// Output signed content to stdout
out, err := verifiedSig.PrettySignature("verifySignatures")
if err != nil {
log.Fatalf("Error formatting output: %s", err)
}
_, err = os.Stdout.Write(out)
if err != nil {
log.Fatalf("Error writing output: %s", err)
}
}

View File

@ -1,599 +0,0 @@
mode: set
github.com/docker/libtrust/jsonsign.go:53.40,57.2 1 1
github.com/docker/libtrust/jsonsign.go:61.52,63.2 1 0
github.com/docker/libtrust/jsonsign.go:65.60,72.16 3 1
github.com/docker/libtrust/jsonsign.go:76.2,76.49 1 1
github.com/docker/libtrust/jsonsign.go:72.16,74.3 1 0
github.com/docker/libtrust/jsonsign.go:79.76,85.2 5 1
github.com/docker/libtrust/jsonsign.go:88.53,90.16 2 1
github.com/docker/libtrust/jsonsign.go:93.2,94.16 2 1
github.com/docker/libtrust/jsonsign.go:97.2,98.16 2 1
github.com/docker/libtrust/jsonsign.go:102.2,114.12 4 1
github.com/docker/libtrust/jsonsign.go:90.16,92.3 1 0
github.com/docker/libtrust/jsonsign.go:94.16,96.3 1 0
github.com/docker/libtrust/jsonsign.go:98.16,100.3 1 0
github.com/docker/libtrust/jsonsign.go:120.89,127.16 2 1
github.com/docker/libtrust/jsonsign.go:130.2,131.16 2 1
github.com/docker/libtrust/jsonsign.go:134.2,135.16 2 1
github.com/docker/libtrust/jsonsign.go:139.2,144.29 2 1
github.com/docker/libtrust/jsonsign.go:148.2,156.12 3 1
github.com/docker/libtrust/jsonsign.go:127.16,129.3 1 0
github.com/docker/libtrust/jsonsign.go:131.16,133.3 1 0
github.com/docker/libtrust/jsonsign.go:135.16,137.3 1 0
github.com/docker/libtrust/jsonsign.go:144.29,146.3 1 1
github.com/docker/libtrust/jsonsign.go:161.56,163.42 2 1
github.com/docker/libtrust/jsonsign.go:200.2,200.18 1 1
github.com/docker/libtrust/jsonsign.go:163.42,165.17 2 1
github.com/docker/libtrust/jsonsign.go:168.3,169.38 2 1
github.com/docker/libtrust/jsonsign.go:188.3,189.17 2 1
github.com/docker/libtrust/jsonsign.go:193.3,194.17 2 1
github.com/docker/libtrust/jsonsign.go:198.3,198.22 1 1
github.com/docker/libtrust/jsonsign.go:165.17,167.4 1 0
github.com/docker/libtrust/jsonsign.go:169.38,171.18 2 0
github.com/docker/libtrust/jsonsign.go:174.4,175.18 2 0
github.com/docker/libtrust/jsonsign.go:178.4,179.18 2 0
github.com/docker/libtrust/jsonsign.go:171.18,173.5 1 0
github.com/docker/libtrust/jsonsign.go:175.18,177.5 1 0
github.com/docker/libtrust/jsonsign.go:179.18,181.5 1 0
github.com/docker/libtrust/jsonsign.go:182.5,182.41 1 1
github.com/docker/libtrust/jsonsign.go:182.41,184.4 1 1
github.com/docker/libtrust/jsonsign.go:184.5,186.4 1 0
github.com/docker/libtrust/jsonsign.go:189.17,191.4 1 0
github.com/docker/libtrust/jsonsign.go:194.17,196.4 1 0
github.com/docker/libtrust/jsonsign.go:206.89,208.42 2 1
github.com/docker/libtrust/jsonsign.go:266.2,266.20 1 1
github.com/docker/libtrust/jsonsign.go:208.42,210.17 2 1
github.com/docker/libtrust/jsonsign.go:213.3,214.38 2 1
github.com/docker/libtrust/jsonsign.go:210.17,212.4 1 0
github.com/docker/libtrust/jsonsign.go:214.38,216.18 2 1
github.com/docker/libtrust/jsonsign.go:219.4,220.18 2 1
github.com/docker/libtrust/jsonsign.go:223.4,224.18 2 1
github.com/docker/libtrust/jsonsign.go:227.4,228.39 2 1
github.com/docker/libtrust/jsonsign.go:243.4,249.18 3 1
github.com/docker/libtrust/jsonsign.go:252.4,255.18 3 1
github.com/docker/libtrust/jsonsign.go:259.4,260.18 2 1
github.com/docker/libtrust/jsonsign.go:216.18,218.5 1 0
github.com/docker/libtrust/jsonsign.go:220.18,222.5 1 0
github.com/docker/libtrust/jsonsign.go:224.18,226.5 1 0
github.com/docker/libtrust/jsonsign.go:228.39,230.38 2 1
github.com/docker/libtrust/jsonsign.go:230.38,232.20 2 1
github.com/docker/libtrust/jsonsign.go:235.6,236.20 2 1
github.com/docker/libtrust/jsonsign.go:239.6,239.41 1 1
github.com/docker/libtrust/jsonsign.go:232.20,234.7 1 0
github.com/docker/libtrust/jsonsign.go:236.20,238.7 1 0
github.com/docker/libtrust/jsonsign.go:249.18,251.5 1 1
github.com/docker/libtrust/jsonsign.go:255.18,257.5 1 0
github.com/docker/libtrust/jsonsign.go:260.18,262.5 1 0
github.com/docker/libtrust/jsonsign.go:271.48,272.29 1 0
github.com/docker/libtrust/jsonsign.go:275.2,280.47 2 0
github.com/docker/libtrust/jsonsign.go:272.29,274.3 1 0
github.com/docker/libtrust/jsonsign.go:283.28,285.2 1 1
github.com/docker/libtrust/jsonsign.go:287.59,288.77 1 1
github.com/docker/libtrust/jsonsign.go:294.2,294.8 1 1
github.com/docker/libtrust/jsonsign.go:288.77,290.21 2 1
github.com/docker/libtrust/jsonsign.go:290.21,292.4 1 1
github.com/docker/libtrust/jsonsign.go:310.55,317.16 4 0
github.com/docker/libtrust/jsonsign.go:320.2,320.33 1 0
github.com/docker/libtrust/jsonsign.go:323.2,324.16 2 0
github.com/docker/libtrust/jsonsign.go:328.2,329.16 2 0
github.com/docker/libtrust/jsonsign.go:332.2,333.46 2 0
github.com/docker/libtrust/jsonsign.go:354.2,354.16 1 0
github.com/docker/libtrust/jsonsign.go:317.16,319.3 1 0
github.com/docker/libtrust/jsonsign.go:320.33,322.3 1 0
github.com/docker/libtrust/jsonsign.go:324.16,326.3 1 0
github.com/docker/libtrust/jsonsign.go:329.16,331.3 1 0
github.com/docker/libtrust/jsonsign.go:333.46,337.36 2 0
github.com/docker/libtrust/jsonsign.go:340.3,340.34 1 0
github.com/docker/libtrust/jsonsign.go:347.3,351.4 1 0
github.com/docker/libtrust/jsonsign.go:337.36,339.4 1 0
github.com/docker/libtrust/jsonsign.go:340.34,342.18 2 0
github.com/docker/libtrust/jsonsign.go:345.4,345.26 1 0
github.com/docker/libtrust/jsonsign.go:342.18,344.5 1 0
github.com/docker/libtrust/jsonsign.go:359.63,362.16 3 1
github.com/docker/libtrust/jsonsign.go:366.2,373.32 5 1
github.com/docker/libtrust/jsonsign.go:376.2,377.35 2 1
github.com/docker/libtrust/jsonsign.go:380.2,383.16 3 1
github.com/docker/libtrust/jsonsign.go:362.16,364.3 1 0
github.com/docker/libtrust/jsonsign.go:373.32,375.3 1 0
github.com/docker/libtrust/jsonsign.go:377.35,379.3 1 0
github.com/docker/libtrust/jsonsign.go:388.75,389.24 1 1
github.com/docker/libtrust/jsonsign.go:396.2,400.16 4 1
github.com/docker/libtrust/jsonsign.go:403.2,409.16 4 1
github.com/docker/libtrust/jsonsign.go:390.2,390.30 0 1
github.com/docker/libtrust/jsonsign.go:391.2,391.16 0 0
github.com/docker/libtrust/jsonsign.go:392.2,393.46 1 0
github.com/docker/libtrust/jsonsign.go:400.16,402.3 1 0
github.com/docker/libtrust/jsonsign.go:412.71,414.9 2 1
github.com/docker/libtrust/jsonsign.go:417.2,417.27 1 1
github.com/docker/libtrust/jsonsign.go:414.9,416.3 1 0
github.com/docker/libtrust/jsonsign.go:418.2,419.17 1 0
github.com/docker/libtrust/jsonsign.go:420.2,421.22 1 1
github.com/docker/libtrust/jsonsign.go:422.2,423.18 1 0
github.com/docker/libtrust/jsonsign.go:427.82,429.9 2 1
github.com/docker/libtrust/jsonsign.go:432.2,433.8 2 1
github.com/docker/libtrust/jsonsign.go:429.9,431.3 1 0
github.com/docker/libtrust/jsonsign.go:440.88,443.16 3 1
github.com/docker/libtrust/jsonsign.go:446.2,447.9 2 1
github.com/docker/libtrust/jsonsign.go:451.2,453.16 3 1
github.com/docker/libtrust/jsonsign.go:457.2,460.49 3 1
github.com/docker/libtrust/jsonsign.go:511.2,511.36 1 1
github.com/docker/libtrust/jsonsign.go:514.2,520.16 6 1
github.com/docker/libtrust/jsonsign.go:443.16,445.3 1 0
github.com/docker/libtrust/jsonsign.go:447.9,449.3 1 0
github.com/docker/libtrust/jsonsign.go:453.16,455.3 1 0
github.com/docker/libtrust/jsonsign.go:460.49,462.17 2 1
github.com/docker/libtrust/jsonsign.go:465.3,467.17 3 1
github.com/docker/libtrust/jsonsign.go:471.3,472.10 2 1
github.com/docker/libtrust/jsonsign.go:475.3,476.10 2 1
github.com/docker/libtrust/jsonsign.go:479.3,480.17 2 1
github.com/docker/libtrust/jsonsign.go:483.3,483.27 1 1
github.com/docker/libtrust/jsonsign.go:488.3,488.30 1 1
github.com/docker/libtrust/jsonsign.go:494.3,498.39 2 1
github.com/docker/libtrust/jsonsign.go:505.3,509.4 1 1
github.com/docker/libtrust/jsonsign.go:462.17,464.4 1 0
github.com/docker/libtrust/jsonsign.go:467.17,469.4 1 0
github.com/docker/libtrust/jsonsign.go:472.10,474.4 1 0
github.com/docker/libtrust/jsonsign.go:476.10,478.4 1 0
github.com/docker/libtrust/jsonsign.go:480.17,482.4 1 0
github.com/docker/libtrust/jsonsign.go:483.27,485.4 1 1
github.com/docker/libtrust/jsonsign.go:485.5,485.45 1 0
github.com/docker/libtrust/jsonsign.go:485.45,487.4 1 0
github.com/docker/libtrust/jsonsign.go:488.30,490.4 1 1
github.com/docker/libtrust/jsonsign.go:490.5,490.59 1 0
github.com/docker/libtrust/jsonsign.go:490.59,492.4 1 0
github.com/docker/libtrust/jsonsign.go:498.39,500.18 2 1
github.com/docker/libtrust/jsonsign.go:503.4,503.26 1 1
github.com/docker/libtrust/jsonsign.go:500.18,502.5 1 0
github.com/docker/libtrust/jsonsign.go:511.36,513.3 1 0
github.com/docker/libtrust/jsonsign.go:525.79,526.29 1 1
github.com/docker/libtrust/jsonsign.go:529.2,530.16 2 1
github.com/docker/libtrust/jsonsign.go:533.2,537.21 4 1
github.com/docker/libtrust/jsonsign.go:542.2,542.24 1 1
github.com/docker/libtrust/jsonsign.go:546.2,549.21 4 1
github.com/docker/libtrust/jsonsign.go:563.2,565.25 2 1
github.com/docker/libtrust/jsonsign.go:526.29,528.3 1 0
github.com/docker/libtrust/jsonsign.go:530.16,532.3 1 0
github.com/docker/libtrust/jsonsign.go:537.21,539.3 1 1
github.com/docker/libtrust/jsonsign.go:539.4,541.3 1 1
github.com/docker/libtrust/jsonsign.go:542.24,544.3 1 0
github.com/docker/libtrust/jsonsign.go:549.21,557.3 7 1
github.com/docker/libtrust/jsonsign.go:557.4,562.3 4 1
github.com/docker/libtrust/key.go:71.79,72.51 1 1
github.com/docker/libtrust/key.go:73.2,74.42 1 1
github.com/docker/libtrust/key.go:75.2,76.48 1 1
github.com/docker/libtrust/key.go:77.2,78.81 1 0
github.com/docker/libtrust/key.go:85.83,86.53 1 1
github.com/docker/libtrust/key.go:87.2,88.44 1 1
github.com/docker/libtrust/key.go:89.2,90.50 1 1
github.com/docker/libtrust/key.go:91.2,92.83 1 0
github.com/docker/libtrust/key.go:98.60,100.21 2 1
github.com/docker/libtrust/key.go:106.2,106.37 1 1
github.com/docker/libtrust/key.go:100.21,102.3 1 0
github.com/docker/libtrust/key.go:102.4,102.42 1 1
github.com/docker/libtrust/key.go:102.42,104.3 1 0
github.com/docker/libtrust/key.go:112.68,115.6 2 1
github.com/docker/libtrust/key.go:132.2,132.21 1 1
github.com/docker/libtrust/key.go:115.6,118.22 3 1
github.com/docker/libtrust/key.go:124.3,125.17 2 1
github.com/docker/libtrust/key.go:129.3,129.36 1 1
github.com/docker/libtrust/key.go:118.22,119.9 1 1
github.com/docker/libtrust/key.go:120.5,120.43 1 1
github.com/docker/libtrust/key.go:120.43,122.4 1 0
github.com/docker/libtrust/key.go:125.17,127.4 1 0
github.com/docker/libtrust/key.go:137.62,139.21 2 1
github.com/docker/libtrust/key.go:143.2,145.9 2 1
github.com/docker/libtrust/key.go:165.2,167.17 2 1
github.com/docker/libtrust/key.go:139.21,141.3 1 0
github.com/docker/libtrust/key.go:146.2,148.17 2 1
github.com/docker/libtrust/key.go:151.3,151.41 1 1
github.com/docker/libtrust/key.go:152.2,154.17 2 1
github.com/docker/libtrust/key.go:157.3,158.17 2 1
github.com/docker/libtrust/key.go:161.2,162.86 1 0
github.com/docker/libtrust/key.go:148.17,150.4 1 0
github.com/docker/libtrust/key.go:154.17,156.4 1 0
github.com/docker/libtrust/key.go:158.17,160.4 1 0
github.com/docker/libtrust/key.go:172.60,176.16 3 1
github.com/docker/libtrust/key.go:183.2,184.16 2 1
github.com/docker/libtrust/key.go:188.2,188.9 1 1
github.com/docker/libtrust/key.go:176.16,180.3 1 0
github.com/docker/libtrust/key.go:184.16,186.3 1 0
github.com/docker/libtrust/key.go:189.2,191.33 1 1
github.com/docker/libtrust/key.go:192.2,194.34 1 1
github.com/docker/libtrust/key.go:195.2,198.4 1 0
github.com/docker/libtrust/key.go:204.65,206.16 2 1
github.com/docker/libtrust/key.go:210.2,212.33 2 1
github.com/docker/libtrust/key.go:220.2,220.21 1 1
github.com/docker/libtrust/key.go:206.16,208.3 1 0
github.com/docker/libtrust/key.go:212.33,214.17 2 1
github.com/docker/libtrust/key.go:217.3,217.36 1 1
github.com/docker/libtrust/key.go:214.17,216.4 1 0
github.com/docker/libtrust/key.go:225.62,229.16 3 1
github.com/docker/libtrust/key.go:236.2,237.16 2 1
github.com/docker/libtrust/key.go:241.2,241.9 1 1
github.com/docker/libtrust/key.go:229.16,233.3 1 0
github.com/docker/libtrust/key.go:237.16,239.3 1 0
github.com/docker/libtrust/key.go:242.2,244.34 1 1
github.com/docker/libtrust/key.go:245.2,247.35 1 1
github.com/docker/libtrust/key.go:248.2,251.4 1 0
github.com/docker/libtrust/key_files.go:18.56,20.16 2 1
github.com/docker/libtrust/key_files.go:30.2,30.18 1 1
github.com/docker/libtrust/key_files.go:20.16,21.25 1 1
github.com/docker/libtrust/key_files.go:27.3,27.18 1 1
github.com/docker/libtrust/key_files.go:21.25,23.4 1 1
github.com/docker/libtrust/key_files.go:23.5,25.4 1 0
github.com/docker/libtrust/key_files.go:39.55,41.16 2 1
github.com/docker/libtrust/key_files.go:45.2,47.81 2 1
github.com/docker/libtrust/key_files.go:59.2,59.17 1 1
github.com/docker/libtrust/key_files.go:41.16,43.3 1 0
github.com/docker/libtrust/key_files.go:47.81,49.17 2 1
github.com/docker/libtrust/key_files.go:49.17,51.4 1 0
github.com/docker/libtrust/key_files.go:52.4,54.17 2 1
github.com/docker/libtrust/key_files.go:54.17,56.4 1 0
github.com/docker/libtrust/key_files.go:64.60,66.16 2 1
github.com/docker/libtrust/key_files.go:70.2,72.81 2 1
github.com/docker/libtrust/key_files.go:84.2,84.17 1 1
github.com/docker/libtrust/key_files.go:66.16,68.3 1 0
github.com/docker/libtrust/key_files.go:72.81,74.17 2 1
github.com/docker/libtrust/key_files.go:74.17,76.4 1 0
github.com/docker/libtrust/key_files.go:77.4,79.17 2 1
github.com/docker/libtrust/key_files.go:79.17,81.4 1 0
github.com/docker/libtrust/key_files.go:89.53,93.81 3 1
github.com/docker/libtrust/key_files.go:108.2,109.16 2 1
github.com/docker/libtrust/key_files.go:113.2,113.12 1 1
github.com/docker/libtrust/key_files.go:93.81,96.17 2 1
github.com/docker/libtrust/key_files.go:96.17,98.4 1 0
github.com/docker/libtrust/key_files.go:99.4,102.17 2 1
github.com/docker/libtrust/key_files.go:105.3,105.44 1 1
github.com/docker/libtrust/key_files.go:102.17,104.4 1 0
github.com/docker/libtrust/key_files.go:109.16,111.3 1 0
github.com/docker/libtrust/key_files.go:117.58,121.81 3 1
github.com/docker/libtrust/key_files.go:136.2,137.16 2 1
github.com/docker/libtrust/key_files.go:141.2,141.12 1 1
github.com/docker/libtrust/key_files.go:121.81,124.17 2 1
github.com/docker/libtrust/key_files.go:124.17,126.4 1 0
github.com/docker/libtrust/key_files.go:127.4,130.17 2 1
github.com/docker/libtrust/key_files.go:133.3,133.44 1 1
github.com/docker/libtrust/key_files.go:130.17,132.4 1 0
github.com/docker/libtrust/key_files.go:137.16,139.3 1 0
github.com/docker/libtrust/key_files.go:151.59,152.81 1 1
github.com/docker/libtrust/key_files.go:157.2,157.36 1 1
github.com/docker/libtrust/key_files.go:152.81,154.3 1 1
github.com/docker/libtrust/key_files.go:160.64,161.20 1 1
github.com/docker/libtrust/key_files.go:166.2,169.16 3 1
github.com/docker/libtrust/key_files.go:173.2,173.25 1 1
github.com/docker/libtrust/key_files.go:161.20,164.3 1 1
github.com/docker/libtrust/key_files.go:169.16,171.3 1 0
github.com/docker/libtrust/key_files.go:176.63,178.49 2 1
github.com/docker/libtrust/key_files.go:182.2,182.43 1 1
github.com/docker/libtrust/key_files.go:178.49,180.3 1 0
github.com/docker/libtrust/key_files.go:185.62,187.49 2 1
github.com/docker/libtrust/key_files.go:191.2,191.42 1 1
github.com/docker/libtrust/key_files.go:187.49,189.3 1 0
github.com/docker/libtrust/key_files.go:195.58,196.81 1 1
github.com/docker/libtrust/key_files.go:201.2,201.40 1 1
github.com/docker/libtrust/key_files.go:196.81,198.3 1 1
github.com/docker/libtrust/key_files.go:204.62,206.16 2 1
github.com/docker/libtrust/key_files.go:210.2,211.49 2 1
github.com/docker/libtrust/key_files.go:215.2,216.16 2 1
github.com/docker/libtrust/key_files.go:220.2,224.16 4 1
github.com/docker/libtrust/key_files.go:228.2,229.16 2 1
github.com/docker/libtrust/key_files.go:233.2,233.12 1 1
github.com/docker/libtrust/key_files.go:206.16,208.3 1 0
github.com/docker/libtrust/key_files.go:211.49,213.3 1 0
github.com/docker/libtrust/key_files.go:216.16,218.3 1 0
github.com/docker/libtrust/key_files.go:224.16,226.3 1 0
github.com/docker/libtrust/key_files.go:229.16,231.3 1 0
github.com/docker/libtrust/key_files.go:236.61,239.16 2 1
github.com/docker/libtrust/key_files.go:242.2,245.16 3 1
github.com/docker/libtrust/key_files.go:249.2,250.16 2 1
github.com/docker/libtrust/key_files.go:254.2,254.12 1 1
github.com/docker/libtrust/key_files.go:239.16,241.3 1 0
github.com/docker/libtrust/key_files.go:245.16,247.3 1 0
github.com/docker/libtrust/key_files.go:250.16,252.3 1 0
github.com/docker/libtrust/rsa_key.go:26.69,28.2 1 1
github.com/docker/libtrust/rsa_key.go:31.41,33.2 1 1
github.com/docker/libtrust/rsa_key.go:36.39,47.2 5 1
github.com/docker/libtrust/rsa_key.go:49.40,51.2 1 1
github.com/docker/libtrust/rsa_key.go:57.83,60.16 2 1
github.com/docker/libtrust/rsa_key.go:64.2,66.16 3 1
github.com/docker/libtrust/rsa_key.go:69.2,72.16 3 1
github.com/docker/libtrust/rsa_key.go:76.2,76.12 1 1
github.com/docker/libtrust/rsa_key.go:60.16,62.3 1 0
github.com/docker/libtrust/rsa_key.go:66.16,68.3 1 0
github.com/docker/libtrust/rsa_key.go:72.16,74.3 1 0
github.com/docker/libtrust/rsa_key.go:82.59,84.2 1 1
github.com/docker/libtrust/rsa_key.go:86.55,88.31 2 1
github.com/docker/libtrust/rsa_key.go:91.2,96.12 5 1
github.com/docker/libtrust/rsa_key.go:88.31,90.3 1 1
github.com/docker/libtrust/rsa_key.go:101.63,103.2 1 1
github.com/docker/libtrust/rsa_key.go:106.55,108.16 2 1
github.com/docker/libtrust/rsa_key.go:111.2,112.59 2 1
github.com/docker/libtrust/rsa_key.go:108.16,110.3 1 0
github.com/docker/libtrust/rsa_key.go:115.74,117.2 1 1
github.com/docker/libtrust/rsa_key.go:119.67,121.9 2 1
github.com/docker/libtrust/rsa_key.go:124.2,124.10 1 1
github.com/docker/libtrust/rsa_key.go:121.9,123.3 1 0
github.com/docker/libtrust/rsa_key.go:127.77,134.16 2 1
github.com/docker/libtrust/rsa_key.go:138.2,139.16 2 1
github.com/docker/libtrust/rsa_key.go:144.2,145.16 2 1
github.com/docker/libtrust/rsa_key.go:149.2,150.16 2 1
github.com/docker/libtrust/rsa_key.go:154.2,160.8 3 1
github.com/docker/libtrust/rsa_key.go:170.2,170.27 1 1
github.com/docker/libtrust/rsa_key.go:174.2,176.17 2 1
github.com/docker/libtrust/rsa_key.go:134.16,136.3 1 0
github.com/docker/libtrust/rsa_key.go:139.16,141.3 1 0
github.com/docker/libtrust/rsa_key.go:145.16,147.3 1 0
github.com/docker/libtrust/rsa_key.go:150.16,152.3 1 0
github.com/docker/libtrust/rsa_key.go:160.8,162.17 2 1
github.com/docker/libtrust/rsa_key.go:165.3,165.25 1 1
github.com/docker/libtrust/rsa_key.go:162.17,164.4 1 0
github.com/docker/libtrust/rsa_key.go:165.25,167.4 1 0
github.com/docker/libtrust/rsa_key.go:170.27,172.3 1 0
github.com/docker/libtrust/rsa_key.go:189.73,194.2 1 1
github.com/docker/libtrust/rsa_key.go:197.47,199.2 1 1
github.com/docker/libtrust/rsa_key.go:201.41,203.2 1 0
github.com/docker/libtrust/rsa_key.go:211.108,217.16 4 1
github.com/docker/libtrust/rsa_key.go:220.2,223.16 3 1
github.com/docker/libtrust/rsa_key.go:227.2,229.8 2 1
github.com/docker/libtrust/rsa_key.go:217.16,219.3 1 0
github.com/docker/libtrust/rsa_key.go:223.16,225.3 1 0
github.com/docker/libtrust/rsa_key.go:235.62,237.2 1 1
github.com/docker/libtrust/rsa_key.go:239.56,252.26 10 1
github.com/docker/libtrust/rsa_key.go:265.2,265.12 1 1
github.com/docker/libtrust/rsa_key.go:252.26,254.33 2 0
github.com/docker/libtrust/rsa_key.go:262.3,262.31 1 0
github.com/docker/libtrust/rsa_key.go:254.33,261.4 6 0
github.com/docker/libtrust/rsa_key.go:270.64,272.2 1 1
github.com/docker/libtrust/rsa_key.go:275.56,279.2 3 1
github.com/docker/libtrust/rsa_key.go:281.79,289.16 2 1
github.com/docker/libtrust/rsa_key.go:292.2,293.16 2 1
github.com/docker/libtrust/rsa_key.go:296.2,297.16 2 1
github.com/docker/libtrust/rsa_key.go:300.2,301.16 2 1
github.com/docker/libtrust/rsa_key.go:304.2,305.16 2 1
github.com/docker/libtrust/rsa_key.go:308.2,309.16 2 1
github.com/docker/libtrust/rsa_key.go:313.2,314.29 2 1
github.com/docker/libtrust/rsa_key.go:322.2,323.16 2 1
github.com/docker/libtrust/rsa_key.go:327.2,338.16 2 1
github.com/docker/libtrust/rsa_key.go:383.2,388.17 2 1
github.com/docker/libtrust/rsa_key.go:289.16,291.3 1 0
github.com/docker/libtrust/rsa_key.go:293.16,295.3 1 0
github.com/docker/libtrust/rsa_key.go:297.16,299.3 1 0
github.com/docker/libtrust/rsa_key.go:301.16,303.3 1 0
github.com/docker/libtrust/rsa_key.go:305.16,307.3 1 0
github.com/docker/libtrust/rsa_key.go:309.16,311.3 1 0
github.com/docker/libtrust/rsa_key.go:314.29,317.3 2 0
github.com/docker/libtrust/rsa_key.go:323.16,325.3 1 0
github.com/docker/libtrust/rsa_key.go:338.16,341.10 2 0
github.com/docker/libtrust/rsa_key.go:344.3,345.32 2 0
github.com/docker/libtrust/rsa_key.go:348.3,352.39 4 0
github.com/docker/libtrust/rsa_key.go:379.3,380.47 2 0
github.com/docker/libtrust/rsa_key.go:341.10,343.4 1 0
github.com/docker/libtrust/rsa_key.go:345.32,347.4 1 0
github.com/docker/libtrust/rsa_key.go:352.39,354.11 2 0
github.com/docker/libtrust/rsa_key.go:358.4,359.18 2 0
github.com/docker/libtrust/rsa_key.go:362.4,363.18 2 0
github.com/docker/libtrust/rsa_key.go:366.4,367.18 2 0
github.com/docker/libtrust/rsa_key.go:371.4,376.73 6 0
github.com/docker/libtrust/rsa_key.go:354.11,356.5 1 0
github.com/docker/libtrust/rsa_key.go:359.18,361.5 1 0
github.com/docker/libtrust/rsa_key.go:363.18,365.5 1 0
github.com/docker/libtrust/rsa_key.go:367.18,369.5 1 0
github.com/docker/libtrust/rsa_key.go:395.68,398.16 3 1
github.com/docker/libtrust/rsa_key.go:402.2,405.8 3 1
github.com/docker/libtrust/rsa_key.go:398.16,400.3 1 0
github.com/docker/libtrust/rsa_key.go:409.54,411.16 2 1
github.com/docker/libtrust/rsa_key.go:415.2,415.15 1 1
github.com/docker/libtrust/rsa_key.go:411.16,413.3 1 0
github.com/docker/libtrust/rsa_key.go:419.54,421.16 2 1
github.com/docker/libtrust/rsa_key.go:425.2,425.15 1 1
github.com/docker/libtrust/rsa_key.go:421.16,423.3 1 0
github.com/docker/libtrust/rsa_key.go:429.54,431.16 2 1
github.com/docker/libtrust/rsa_key.go:435.2,435.15 1 1
github.com/docker/libtrust/rsa_key.go:431.16,433.3 1 0
github.com/docker/libtrust/util.go:21.43,23.2 1 1
github.com/docker/libtrust/util.go:29.52,30.20 1 1
github.com/docker/libtrust/util.go:39.2,39.43 1 1
github.com/docker/libtrust/util.go:31.2,31.9 0 1
github.com/docker/libtrust/util.go:32.2,33.12 1 1
github.com/docker/libtrust/util.go:34.2,35.11 1 1
github.com/docker/libtrust/util.go:36.2,37.53 1 0
github.com/docker/libtrust/util.go:42.35,46.33 4 1
github.com/docker/libtrust/util.go:51.2,52.21 2 1
github.com/docker/libtrust/util.go:46.33,50.3 3 1
github.com/docker/libtrust/util.go:55.74,57.9 2 1
github.com/docker/libtrust/util.go:61.2,62.9 2 1
github.com/docker/libtrust/util.go:65.2,67.17 2 1
github.com/docker/libtrust/util.go:57.9,59.3 1 0
github.com/docker/libtrust/util.go:62.9,64.3 1 0
github.com/docker/libtrust/util.go:70.80,74.16 3 1
github.com/docker/libtrust/util.go:77.2,78.33 2 1
github.com/docker/libtrust/util.go:81.2,81.43 1 1
github.com/docker/libtrust/util.go:74.16,76.3 1 0
github.com/docker/libtrust/util.go:78.33,80.3 1 0
github.com/docker/libtrust/util.go:84.82,86.16 2 1
github.com/docker/libtrust/util.go:98.2,102.32 4 1
github.com/docker/libtrust/util.go:106.2,106.43 1 1
github.com/docker/libtrust/util.go:86.16,88.3 1 0
github.com/docker/libtrust/util.go:102.32,104.3 1 0
github.com/docker/libtrust/util.go:109.61,111.16 2 1
github.com/docker/libtrust/util.go:115.2,115.43 1 1
github.com/docker/libtrust/util.go:111.16,113.3 1 0
github.com/docker/libtrust/util.go:118.52,126.24 4 1
github.com/docker/libtrust/util.go:131.2,131.16 1 1
github.com/docker/libtrust/util.go:126.24,127.18 1 1
github.com/docker/libtrust/util.go:127.18,128.9 1 1
github.com/docker/libtrust/util.go:134.63,136.16 2 1
github.com/docker/libtrust/util.go:142.2,146.50 4 1
github.com/docker/libtrust/util.go:136.16,138.3 1 0
github.com/docker/libtrust/util.go:149.93,151.16 2 1
github.com/docker/libtrust/util.go:155.2,156.16 2 1
github.com/docker/libtrust/util.go:160.2,160.47 1 1
github.com/docker/libtrust/util.go:151.16,153.3 1 0
github.com/docker/libtrust/util.go:156.16,158.3 1 0
github.com/docker/libtrust/util.go:163.103,165.28 2 1
github.com/docker/libtrust/util.go:180.2,180.22 1 1
github.com/docker/libtrust/util.go:165.28,166.26 1 1
github.com/docker/libtrust/util.go:167.3,168.29 1 1
github.com/docker/libtrust/util.go:169.3,170.20 1 1
github.com/docker/libtrust/util.go:175.3,175.11 0 0
github.com/docker/libtrust/util.go:170.20,172.5 1 1
github.com/docker/libtrust/util.go:172.6,174.5 0 0
github.com/docker/libtrust/util.go:183.65,185.16 2 1
github.com/docker/libtrust/util.go:189.2,190.16 2 1
github.com/docker/libtrust/util.go:194.2,196.20 2 1
github.com/docker/libtrust/util.go:185.16,187.3 1 0
github.com/docker/libtrust/util.go:190.16,192.3 1 0
github.com/docker/libtrust/util.go:199.64,200.43 1 1
github.com/docker/libtrust/util.go:200.43,202.21 2 1
github.com/docker/libtrust/util.go:207.3,207.40 1 1
github.com/docker/libtrust/util.go:202.21,204.4 1 1
github.com/docker/libtrust/util.go:204.5,206.4 1 1
github.com/docker/libtrust/certificates.go:24.69,33.15 2 1
github.com/docker/libtrust/certificates.go:37.2,37.21 1 1
github.com/docker/libtrust/certificates.go:41.2,41.21 1 1
github.com/docker/libtrust/certificates.go:45.2,58.3 1 1
github.com/docker/libtrust/certificates.go:33.15,35.3 1 1
github.com/docker/libtrust/certificates.go:37.21,39.3 1 1
github.com/docker/libtrust/certificates.go:41.21,43.3 1 1
github.com/docker/libtrust/certificates.go:61.123,69.16 4 1
github.com/docker/libtrust/certificates.go:73.2,74.16 2 1
github.com/docker/libtrust/certificates.go:78.2,78.8 1 1
github.com/docker/libtrust/certificates.go:69.16,71.3 1 0
github.com/docker/libtrust/certificates.go:74.16,76.3 1 0
github.com/docker/libtrust/certificates.go:84.118,93.2 2 1
github.com/docker/libtrust/certificates.go:97.78,104.2 2 1
github.com/docker/libtrust/certificates.go:108.89,118.2 3 1
github.com/docker/libtrust/certificates.go:123.93,126.41 2 1
github.com/docker/libtrust/certificates.go:135.2,135.22 1 1
github.com/docker/libtrust/certificates.go:126.41,128.17 2 1
github.com/docker/libtrust/certificates.go:132.3,132.25 1 1
github.com/docker/libtrust/certificates.go:128.17,130.4 1 0
github.com/docker/libtrust/certificates.go:140.74,142.16 2 1
github.com/docker/libtrust/certificates.go:145.2,148.47 4 1
github.com/docker/libtrust/certificates.go:160.2,160.26 1 1
github.com/docker/libtrust/certificates.go:142.16,144.3 1 0
github.com/docker/libtrust/certificates.go:148.47,149.34 1 1
github.com/docker/libtrust/certificates.go:149.34,151.18 2 1
github.com/docker/libtrust/certificates.go:154.4,154.45 1 1
github.com/docker/libtrust/certificates.go:151.18,153.5 1 0
github.com/docker/libtrust/certificates.go:155.5,157.4 1 0
github.com/docker/libtrust/certificates.go:165.67,167.16 2 1
github.com/docker/libtrust/certificates.go:170.2,171.29 2 1
github.com/docker/libtrust/certificates.go:174.2,174.18 1 1
github.com/docker/libtrust/certificates.go:167.16,169.3 1 0
github.com/docker/libtrust/certificates.go:171.29,173.3 1 1
github.com/docker/libtrust/ec_key.go:30.78,33.9 2 1
github.com/docker/libtrust/ec_key.go:34.2,35.86 1 1
github.com/docker/libtrust/ec_key.go:36.2,37.86 1 1
github.com/docker/libtrust/ec_key.go:38.2,39.86 1 1
github.com/docker/libtrust/ec_key.go:40.2,41.55 1 0
github.com/docker/libtrust/ec_key.go:46.40,48.2 1 1
github.com/docker/libtrust/ec_key.go:52.42,54.2 1 1
github.com/docker/libtrust/ec_key.go:57.38,68.2 5 1
github.com/docker/libtrust/ec_key.go:70.39,72.2 1 1
github.com/docker/libtrust/ec_key.go:78.82,81.47 1 1
github.com/docker/libtrust/ec_key.go:86.2,88.38 3 1
github.com/docker/libtrust/ec_key.go:92.2,98.16 6 1
github.com/docker/libtrust/ec_key.go:101.2,103.44 2 1
github.com/docker/libtrust/ec_key.go:107.2,107.12 1 1
github.com/docker/libtrust/ec_key.go:81.47,83.3 1 0
github.com/docker/libtrust/ec_key.go:88.38,90.3 1 0
github.com/docker/libtrust/ec_key.go:98.16,100.3 1 0
github.com/docker/libtrust/ec_key.go:103.44,105.3 1 0
github.com/docker/libtrust/ec_key.go:113.58,115.2 1 1
github.com/docker/libtrust/ec_key.go:117.54,119.31 2 1
github.com/docker/libtrust/ec_key.go:122.2,139.12 13 1
github.com/docker/libtrust/ec_key.go:119.31,121.3 1 1
github.com/docker/libtrust/ec_key.go:144.62,146.2 1 1
github.com/docker/libtrust/ec_key.go:149.54,151.16 2 1
github.com/docker/libtrust/ec_key.go:154.2,155.59 2 1
github.com/docker/libtrust/ec_key.go:151.16,153.3 1 0
github.com/docker/libtrust/ec_key.go:158.73,160.2 1 1
github.com/docker/libtrust/ec_key.go:162.66,164.9 2 1
github.com/docker/libtrust/ec_key.go:167.2,167.10 1 1
github.com/docker/libtrust/ec_key.go:164.9,166.3 1 1
github.com/docker/libtrust/ec_key.go:170.75,177.16 2 1
github.com/docker/libtrust/ec_key.go:181.2,186.9 2 1
github.com/docker/libtrust/ec_key.go:201.2,202.16 2 1
github.com/docker/libtrust/ec_key.go:205.2,206.16 2 1
github.com/docker/libtrust/ec_key.go:210.2,211.16 2 1
github.com/docker/libtrust/ec_key.go:214.2,215.16 2 1
github.com/docker/libtrust/ec_key.go:219.2,226.8 3 1
github.com/docker/libtrust/ec_key.go:236.2,238.17 2 1
github.com/docker/libtrust/ec_key.go:177.16,179.3 1 0
github.com/docker/libtrust/ec_key.go:187.2,189.17 2 1
github.com/docker/libtrust/ec_key.go:190.2,192.17 2 1
github.com/docker/libtrust/ec_key.go:193.2,195.17 2 1
github.com/docker/libtrust/ec_key.go:196.2,197.88 1 0
github.com/docker/libtrust/ec_key.go:202.16,204.3 1 0
github.com/docker/libtrust/ec_key.go:206.16,208.3 1 0
github.com/docker/libtrust/ec_key.go:211.16,213.3 1 0
github.com/docker/libtrust/ec_key.go:215.16,217.3 1 0
github.com/docker/libtrust/ec_key.go:226.8,228.17 2 1
github.com/docker/libtrust/ec_key.go:231.3,231.25 1 1
github.com/docker/libtrust/ec_key.go:228.17,230.4 1 0
github.com/docker/libtrust/ec_key.go:231.25,233.4 1 0
github.com/docker/libtrust/ec_key.go:252.82,254.16 2 1
github.com/docker/libtrust/ec_key.go:258.2,258.57 1 1
github.com/docker/libtrust/ec_key.go:254.16,256.3 1 0
github.com/docker/libtrust/ec_key.go:262.46,264.2 1 1
github.com/docker/libtrust/ec_key.go:266.40,268.2 1 0
github.com/docker/libtrust/ec_key.go:276.107,283.16 3 1
github.com/docker/libtrust/ec_key.go:286.2,289.16 3 1
github.com/docker/libtrust/ec_key.go:292.2,304.8 9 1
github.com/docker/libtrust/ec_key.go:283.16,285.3 1 0
github.com/docker/libtrust/ec_key.go:289.16,291.3 1 0
github.com/docker/libtrust/ec_key.go:310.61,312.2 1 1
github.com/docker/libtrust/ec_key.go:314.55,335.2 8 1
github.com/docker/libtrust/ec_key.go:339.63,341.2 1 1
github.com/docker/libtrust/ec_key.go:344.55,346.16 2 1
github.com/docker/libtrust/ec_key.go:349.2,350.63 2 1
github.com/docker/libtrust/ec_key.go:346.16,348.3 1 0
github.com/docker/libtrust/ec_key.go:353.77,355.16 2 1
github.com/docker/libtrust/ec_key.go:362.2,363.16 2 1
github.com/docker/libtrust/ec_key.go:367.2,368.16 2 1
github.com/docker/libtrust/ec_key.go:372.2,380.17 2 1
github.com/docker/libtrust/ec_key.go:355.16,357.3 1 0
github.com/docker/libtrust/ec_key.go:363.16,365.3 1 0
github.com/docker/libtrust/ec_key.go:368.16,370.3 1 0
github.com/docker/libtrust/ec_key.go:387.78,390.16 3 1
github.com/docker/libtrust/ec_key.go:394.2,397.8 3 1
github.com/docker/libtrust/ec_key.go:390.16,392.3 1 0
github.com/docker/libtrust/ec_key.go:401.53,403.16 2 1
github.com/docker/libtrust/ec_key.go:407.2,410.15 3 1
github.com/docker/libtrust/ec_key.go:403.16,405.3 1 0
github.com/docker/libtrust/ec_key.go:414.53,416.16 2 1
github.com/docker/libtrust/ec_key.go:420.2,423.15 3 1
github.com/docker/libtrust/ec_key.go:416.16,418.3 1 0
github.com/docker/libtrust/ec_key.go:427.53,429.16 2 1
github.com/docker/libtrust/ec_key.go:433.2,436.15 3 1
github.com/docker/libtrust/ec_key.go:429.16,431.3 1 0
github.com/docker/libtrust/filter.go:10.91,13.30 2 1
github.com/docker/libtrust/filter.go:49.2,49.22 1 1
github.com/docker/libtrust/filter.go:13.30,15.55 2 1
github.com/docker/libtrust/filter.go:28.3,28.22 1 1
github.com/docker/libtrust/filter.go:36.3,36.37 1 1
github.com/docker/libtrust/filter.go:16.3,17.13 1 1
github.com/docker/libtrust/filter.go:18.3,19.28 1 1
github.com/docker/libtrust/filter.go:19.28,21.12 2 1
github.com/docker/libtrust/filter.go:24.5,24.29 1 1
github.com/docker/libtrust/filter.go:21.12,22.14 1 0
github.com/docker/libtrust/filter.go:28.22,29.20 1 1
github.com/docker/libtrust/filter.go:32.4,32.12 1 1
github.com/docker/libtrust/filter.go:29.20,31.5 1 1
github.com/docker/libtrust/filter.go:36.37,38.18 2 1
github.com/docker/libtrust/filter.go:42.4,42.13 1 1
github.com/docker/libtrust/filter.go:38.18,40.5 1 0
github.com/docker/libtrust/filter.go:42.13,44.13 2 1
github.com/docker/libtrust/hash.go:15.51,17.2 1 1
github.com/docker/libtrust/hash.go:19.51,21.2 1 1
github.com/docker/libtrust/hash.go:32.75,33.9 1 1
github.com/docker/libtrust/hash.go:34.2,35.20 1 1
github.com/docker/libtrust/hash.go:36.2,37.20 1 1
github.com/docker/libtrust/hash.go:38.2,39.20 1 1
github.com/docker/libtrust/hash.go:40.2,41.82 1 0
github.com/docker/libtrust/hash.go:45.85,46.9 1 1
github.com/docker/libtrust/hash.go:47.2,48.15 1 1
github.com/docker/libtrust/hash.go:49.2,50.15 1 1
github.com/docker/libtrust/hash.go:51.2,52.14 1 1
github.com/docker/libtrust/hash.go:53.2,54.15 1 1

View File

@ -1,14 +0,0 @@
# The `trust` client binary
The `trust` binary is a tool to manage key pair, signatures, and ACLs
in the global trust graph.
## Command Reference
### `grant` command
### `grants` command
### `register` command
Registers a public key with a key server and links it with a user namespace

View File

@ -1,568 +0,0 @@
package jsonsign
import (
"bytes"
"crypto"
"crypto/x509"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"time"
"unicode"
"github.com/docker/libtrust"
)
var (
// ErrInvalidSignContent is used when the content to be signed is invalid.
ErrInvalidSignContent = errors.New("invalid sign content")
// ErrInvalidJSONContent is used when invalid json is encountered.
ErrInvalidJSONContent = errors.New("invalid json content")
// ErrMissingSignatureKey is used when the specified signature key
// does not exist in the JSON content.
ErrMissingSignatureKey = errors.New("missing signature key")
)
type jsHeader struct {
JWK libtrust.PublicKey `json:"jwk,omitempty"`
Algorithm string `json:"alg"`
Chain []string `json:"x5c,omitempty"`
}
type jsSignature struct {
Header *jsHeader `json:"header"`
Signature string `json:"signature"`
Protected string `json:"protected,omitempty"`
}
type signKey struct {
libtrust.PrivateKey
Chain []*x509.Certificate
}
// JSONSignature represents a signature of a json object.
type JSONSignature struct {
payload string
signatures []*jsSignature
indent string
formatLength int
formatTail []byte
}
func newJSONSignature() *JSONSignature {
return &JSONSignature{
signatures: make([]*jsSignature, 0, 1),
}
}
// Payload returns the encoded payload of the signature. This
// payload should not be signed directly
func (js *JSONSignature) Payload() ([]byte, error) {
return joseBase64UrlDecode(js.payload)
}
func (js *JSONSignature) protectedHeader() (string, error) {
protected := map[string]interface{}{
"formatLength": js.formatLength,
"formatTail": joseBase64UrlEncode(js.formatTail),
"time": time.Now().UTC().Format(time.RFC3339),
}
protectedBytes, err := json.Marshal(protected)
if err != nil {
return "", err
}
return joseBase64UrlEncode(protectedBytes), nil
}
func (js *JSONSignature) signBytes(protectedHeader string) ([]byte, error) {
buf := make([]byte, len(js.payload)+len(protectedHeader)+1)
copy(buf, protectedHeader)
buf[len(protectedHeader)] = '.'
copy(buf[len(protectedHeader)+1:], js.payload)
return buf, nil
}
// Sign adds a signature using the given private key.
func (js *JSONSignature) Sign(key PrivateKey) error {
protected, err := js.protectedHeader()
if err != nil {
return err
}
signBytes, err := js.signBytes(protected)
if err != nil {
return err
}
sigBytes, algorithm, err := key.Sign(bytes.NewReader(signBytes), crypto.SHA256)
if err != nil {
return err
}
header := &jsHeader{
JWK: key.PublicKey(),
Algorithm: algorithm,
}
sig := &jsSignature{
Header: header,
Signature: joseBase64UrlEncode(sigBytes),
Protected: protected,
}
js.signatures = append(js.signatures, sig)
return nil
}
// SignWithChain adds a signature using the given private key
// and setting the x509 chain. The public key of the first element
// in the chain must be the public key corresponding with the sign key.
func (js *JSONSignature) SignWithChain(key PrivateKey, chain []*x509.Certificate) error {
// Ensure key.Chain[0] is public key for key
//key.Chain.PublicKey
//key.PublicKey().CryptoPublicKey()
// Verify chain
protected, err := js.protectedHeader()
if err != nil {
return err
}
signBytes, err := js.signBytes(protected)
if err != nil {
return err
}
sigBytes, algorithm, err := key.Sign(bytes.NewReader(signBytes), crypto.SHA256)
if err != nil {
return err
}
header := &jsHeader{
Chain: make([]string, len(chain)),
Algorithm: algorithm,
}
for i, cert := range chain {
header.Chain[i] = base64.StdEncoding.EncodeToString(cert.Raw)
}
sig := &jsSignature{
Header: header,
Signature: joseBase64UrlEncode(sigBytes),
Protected: protected,
}
js.signatures = append(js.signatures, sig)
return nil
}
// Verify verifies all the signatures and returns the list of
// public keys used to sign. Any x509 chains are not checked.
func (js *JSONSignature) Verify() ([]libtrust.PublicKey, error) {
keys := make([]libtrust.PublicKey, len(js.signatures))
for i, signature := range js.signatures {
signBytes, err := js.signBytes(signature.Protected)
if err != nil {
return nil, err
}
var publicKey libtrust.PublicKey
if len(signature.Header.Chain) > 0 {
certBytes, err := base64.StdEncoding.DecodeString(signature.Header.Chain[0])
if err != nil {
return nil, err
}
cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return nil, err
}
publicKey, err = FromCryptoPublicKey(cert.PublicKey)
if err != nil {
return nil, err
}
} else if signature.Header.JWK != nil {
publicKey = signature.Header.JWK
} else {
return nil, errors.New("missing public key")
}
sigBytes, err := joseBase64UrlDecode(signature.Signature)
if err != nil {
return nil, err
}
err = publicKey.Verify(bytes.NewReader(signBytes), signature.Header.Algorithm, sigBytes)
if err != nil {
return nil, err
}
keys[i] = publicKey
}
return keys, nil
}
// VerifyChains verifies all the signatures and the chains associated
// with each signature and returns the list of verified chains.
// Signatures without an x509 chain are not checked.
func (js *JSONSignature) VerifyChains(ca *x509.CertPool) ([][]*x509.Certificate, error) {
chains := make([][]*x509.Certificate, 0, len(js.signatures))
for _, signature := range js.signatures {
signBytes, err := js.signBytes(signature.Protected)
if err != nil {
return nil, err
}
var publicKey libtrust.PublicKey
if len(signature.Header.Chain) > 0 {
certBytes, err := base64.StdEncoding.DecodeString(signature.Header.Chain[0])
if err != nil {
return nil, err
}
cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return nil, err
}
publicKey, err = FromCryptoPublicKey(cert.PublicKey)
if err != nil {
return nil, err
}
intermediates := x509.NewCertPool()
if len(signature.Header.Chain) > 1 {
intermediateChain := signature.Header.Chain[1:]
for i := range intermediateChain {
certBytes, err := base64.StdEncoding.DecodeString(intermediateChain[i])
if err != nil {
return nil, err
}
intermediate, err := x509.ParseCertificate(certBytes)
if err != nil {
return nil, err
}
intermediates.AddCert(intermediate)
}
}
verifyOptions := x509.VerifyOptions{
Intermediates: intermediates,
Roots: ca,
}
verifiedChains, err := cert.Verify(verifyOptions)
if err != nil {
return nil, err
}
chains = append(chains, verifiedChains...)
sigBytes, err := joseBase64UrlDecode(signature.Signature)
if err != nil {
return nil, err
}
err = publicKey.Verify(bytes.NewReader(signBytes), signature.Header.Algorithm, sigBytes)
if err != nil {
return nil, err
}
}
}
return chains, nil
}
// JWS returns JSON serialized JWS according to
// http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-7.2
func (js *JSONSignature) JWS() ([]byte, error) {
if len(js.signatures) == 0 {
return nil, errors.New("missing signature")
}
jsonMap := map[string]interface{}{
"payload": js.payload,
"signatures": js.signatures,
}
return json.MarshalIndent(jsonMap, "", " ")
}
func notSpace(r rune) bool {
return !unicode.IsSpace(r)
}
func detectJSONIndent(jsonContent []byte) (indent string) {
if len(jsonContent) > 2 && jsonContent[0] == '{' && jsonContent[1] == '\n' {
quoteIndex := bytes.IndexRune(jsonContent[1:], '"')
if quoteIndex > 0 {
indent = string(jsonContent[2 : quoteIndex+1])
}
}
return
}
type jsParsedHeader struct {
JWK json.RawMessage `json:"jwk"`
Algorithm string `json:"alg"`
Chain []string `json:"x5c"`
}
type jsParsedSignature struct {
Header *jsParsedHeader `json:"header"`
Signature string `json:"signature"`
Protected string `json:"protected"`
}
// ParseJWS parses a JWS serialized JSON object into a Json Signature.
func ParseJWS(content []byte) (*JSONSignature, error) {
type jsParsed struct {
Payload string `json:"payload"`
Signatures []*jsParsedSignature `json:"signatures"`
}
parsed := &jsParsed{}
err := json.Unmarshal(content, parsed)
if err != nil {
return nil, err
}
if len(parsed.Signatures) == 0 {
return nil, errors.New("missing signatures")
}
payload, err := joseBase64UrlDecode(parsed.Payload)
if err != nil {
return nil, err
}
js, err := NewJSONSignature(payload)
if err != nil {
return nil, err
}
js.signatures = make([]*jsSignature, len(parsed.Signatures))
for i, signature := range parsed.Signatures {
header := &jsHeader{
Algorithm: signature.Header.Algorithm,
}
if signature.Header.Chain != nil {
header.Chain = signature.Header.Chain
}
if signature.Header.JWK != nil {
publicKey, err := UnmarshalPublicKeyJWK([]byte(signature.Header.JWK))
if err != nil {
return nil, err
}
header.JWK = publicKey
}
js.signatures[i] = &jsSignature{
Header: header,
Signature: signature.Signature,
Protected: signature.Protected,
}
}
return js, nil
}
// NewJSONSignature returns a new unsigned JWS from a json byte array.
// JSONSignature will need to be signed before serializing or storing.
func NewJSONSignature(content []byte) (*JSONSignature, error) {
var dataMap map[string]interface{}
err := json.Unmarshal(content, &dataMap)
if err != nil {
return nil, err
}
js := newJSONSignature()
js.indent = detectJSONIndent(content)
js.payload = joseBase64UrlEncode(content)
// Find trailing } and whitespace, put in protected header
closeIndex := bytes.LastIndexFunc(content, notSpace)
if content[closeIndex] != '}' {
return nil, ErrInvalidJSONContent
}
lastRuneIndex := bytes.LastIndexFunc(content[:closeIndex], notSpace)
if content[lastRuneIndex] == ',' {
return nil, ErrInvalidJSONContent
}
js.formatLength = lastRuneIndex + 1
js.formatTail = content[js.formatLength:]
return js, nil
}
// NewJSONSignatureFromMap returns a new unsigned JSONSignature from a map or
// struct. JWS will need to be signed before serializing or storing.
func NewJSONSignatureFromMap(content interface{}) (*JSONSignature, error) {
switch content.(type) {
case map[string]interface{}:
case struct{}:
default:
return nil, errors.New("invalid data type")
}
js := newJSONSignature()
js.indent = " "
payload, err := json.MarshalIndent(content, "", js.indent)
if err != nil {
return nil, err
}
js.payload = joseBase64UrlEncode(payload)
// Remove '\n}' from formatted section, put in protected header
js.formatLength = len(payload) - 2
js.formatTail = payload[js.formatLength:]
return js, nil
}
func readIntFromMap(key string, m map[string]interface{}) (int, bool) {
value, ok := m[key]
if !ok {
return 0, false
}
switch v := value.(type) {
case int:
return v, true
case float64:
return int(v), true
default:
return 0, false
}
}
func readStringFromMap(key string, m map[string]interface{}) (v string, ok bool) {
value, ok := m[key]
if !ok {
return "", false
}
v, ok = value.(string)
return
}
// ParsePrettySignature parses a formatted signature into a
// JSON signature. If the signatures are missing the format information
// an error is thrown. The formatted signature must be created by
// the same method as format signature.
func ParsePrettySignature(content []byte, signatureKey string) (*JSONSignature, error) {
var contentMap map[string]json.RawMessage
err := json.Unmarshal(content, &contentMap)
if err != nil {
return nil, fmt.Errorf("error unmarshalling content: %s", err)
}
sigMessage, ok := contentMap[signatureKey]
if !ok {
return nil, ErrMissingSignatureKey
}
var signatureBlocks []jsParsedSignature
err = json.Unmarshal([]byte(sigMessage), &signatureBlocks)
if err != nil {
return nil, fmt.Errorf("error unmarshalling signatures: %s", err)
}
js := newJSONSignature()
js.signatures = make([]*jsSignature, len(signatureBlocks))
for i, signatureBlock := range signatureBlocks {
protectedBytes, err := joseBase64UrlDecode(signatureBlock.Protected)
if err != nil {
return nil, fmt.Errorf("base64 decode error: %s", err)
}
var protectedHeader map[string]interface{}
err = json.Unmarshal(protectedBytes, &protectedHeader)
if err != nil {
return nil, fmt.Errorf("error unmarshalling protected header: %s", err)
}
formatLength, ok := readIntFromMap("formatLength", protectedHeader)
if !ok {
return nil, errors.New("missing formatted length")
}
encodedTail, ok := readStringFromMap("formatTail", protectedHeader)
if !ok {
return nil, errors.New("missing formatted tail")
}
formatTail, err := joseBase64UrlDecode(encodedTail)
if err != nil {
return nil, fmt.Errorf("base64 decode error on tail: %s", err)
}
if js.formatLength == 0 {
js.formatLength = formatLength
} else if js.formatLength != formatLength {
return nil, errors.New("conflicting format length")
}
if len(js.formatTail) == 0 {
js.formatTail = formatTail
} else if bytes.Compare(js.formatTail, formatTail) != 0 {
return nil, errors.New("conflicting format tail")
}
header := &jsHeader{
Algorithm: signatureBlock.Header.Algorithm,
Chain: signatureBlock.Header.Chain,
}
if signatureBlock.Header.JWK != nil {
publicKey, err := UnmarshalPublicKeyJWK([]byte(signatureBlock.Header.JWK))
if err != nil {
return nil, fmt.Errorf("error unmarshalling public key: %s", err)
}
header.JWK = publicKey
}
js.signatures[i] = &jsSignature{
Header: header,
Signature: signatureBlock.Signature,
Protected: signatureBlock.Protected,
}
}
if js.formatLength > len(content) {
return nil, errors.New("invalid format length")
}
formatted := make([]byte, js.formatLength+len(js.formatTail))
copy(formatted, content[:js.formatLength])
copy(formatted[js.formatLength:], js.formatTail)
js.indent = detectJSONIndent(formatted)
js.payload = joseBase64UrlEncode(formatted)
return js, nil
}
// PrettySignature formats a json signature into an easy to read
// single json serialized object.
func (js *JSONSignature) PrettySignature(signatureKey string) ([]byte, error) {
if len(js.signatures) == 0 {
return nil, errors.New("no signatures")
}
payload, err := joseBase64UrlDecode(js.payload)
if err != nil {
return nil, err
}
payload = payload[:js.formatLength]
var marshalled []byte
var marshallErr error
if js.indent != "" {
marshalled, marshallErr = json.MarshalIndent(js.signatures, js.indent, js.indent)
} else {
marshalled, marshallErr = json.Marshal(js.signatures)
}
if marshallErr != nil {
return nil, marshallErr
}
buf := bytes.NewBuffer(make([]byte, 0, len(payload)+len(marshalled)+34))
buf.Write(payload)
buf.WriteByte(',')
if js.indent != "" {
buf.WriteByte('\n')
buf.WriteString(js.indent)
buf.WriteByte('"')
buf.WriteString(signatureKey)
buf.WriteString("\": ")
buf.Write(marshalled)
buf.WriteByte('\n')
} else {
buf.WriteByte('"')
buf.WriteString(signatureKey)
buf.WriteString("\":")
buf.Write(marshalled)
}
buf.WriteByte('}')
return buf.Bytes(), nil
}

View File

@ -1,372 +0,0 @@
package jsonsign
import (
"bytes"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"fmt"
"math/big"
"testing"
"time"
"github.com/docker/libtrust"
)
func createTestJSON(sigKey string, indent string) (map[string]interface{}, []byte) {
testMap := map[string]interface{}{
"name": "dmcgowan/mycontainer",
"config": map[string]interface{}{
"ports": []int{9101, 9102},
"run": "/bin/echo \"Hello\"",
},
"layers": []string{
"2893c080-27f5-11e4-8c21-0800200c9a66",
"c54bc25b-fbb2-497b-a899-a8bc1b5b9d55",
"4d5d7e03-f908-49f3-a7f6-9ba28dfe0fb4",
"0b6da891-7f7f-4abf-9c97-7887549e696c",
"1d960389-ae4f-4011-85fd-18d0f96a67ad",
},
}
formattedSection := `{"config":{"ports":[9101,9102],"run":"/bin/echo \"Hello\""},"layers":["2893c080-27f5-11e4-8c21-0800200c9a66","c54bc25b-fbb2-497b-a899-a8bc1b5b9d55","4d5d7e03-f908-49f3-a7f6-9ba28dfe0fb4","0b6da891-7f7f-4abf-9c97-7887549e696c","1d960389-ae4f-4011-85fd-18d0f96a67ad"],"name":"dmcgowan/mycontainer","%s":[{"header":{`
formattedSection = fmt.Sprintf(formattedSection, sigKey)
if indent != "" {
buf := bytes.NewBuffer(nil)
json.Indent(buf, []byte(formattedSection), "", indent)
return testMap, buf.Bytes()
}
return testMap, []byte(formattedSection)
}
func TestSignJSON(t *testing.T) {
key, err := GenerateECP256PrivateKey()
if err != nil {
t.Fatalf("Error generating EC key: %s", err)
}
testMap, _ := createTestJSON("buildSignatures", " ")
indented, err := json.MarshalIndent(testMap, "", " ")
if err != nil {
t.Fatalf("Marshall error: %s", err)
}
js, err := NewJSONSignature(indented)
if err != nil {
t.Fatalf("Error creating JSON signature: %s", err)
}
err = js.Sign(key)
if err != nil {
t.Fatalf("Error signing content: %s", err)
}
keys, err := js.Verify()
if err != nil {
t.Fatalf("Error verifying signature: %s", err)
}
if len(keys) != 1 {
t.Fatalf("Error wrong number of keys returned")
}
if keys[0].KeyID() != key.KeyID() {
t.Fatalf("Unexpected public key returned")
}
}
func TestSignMap(t *testing.T) {
key, err := GenerateECP256PrivateKey()
if err != nil {
t.Fatalf("Error generating EC key: %s", err)
}
testMap, _ := createTestJSON("buildSignatures", " ")
js, err := NewJSONSignatureFromMap(testMap)
if err != nil {
t.Fatalf("Error creating JSON signature: %s", err)
}
err = js.Sign(key)
if err != nil {
t.Fatalf("Error signing JSON signature: %s", err)
}
keys, err := js.Verify()
if err != nil {
t.Fatalf("Error verifying signature: %s", err)
}
if len(keys) != 1 {
t.Fatalf("Error wrong number of keys returned")
}
if keys[0].KeyID() != key.KeyID() {
t.Fatalf("Unexpected public key returned")
}
}
func TestFormattedJson(t *testing.T) {
key, err := GenerateECP256PrivateKey()
if err != nil {
t.Fatalf("Error generating EC key: %s", err)
}
testMap, firstSection := createTestJSON("buildSignatures", " ")
indented, err := json.MarshalIndent(testMap, "", " ")
if err != nil {
t.Fatalf("Marshall error: %s", err)
}
js, err := NewJSONSignature(indented)
if err != nil {
t.Fatalf("Error creating JSON signature: %s", err)
}
err = js.Sign(key)
if err != nil {
t.Fatalf("Error signing content: %s", err)
}
b, err := js.PrettySignature("buildSignatures")
if err != nil {
t.Fatalf("Error signing map: %s", err)
}
if bytes.Compare(b[:len(firstSection)], firstSection) != 0 {
t.Fatalf("Wrong signed value\nExpected:\n%s\nActual:\n%s", firstSection, b[:len(firstSection)])
}
parsed, err := ParsePrettySignature(b, "buildSignatures")
if err != nil {
t.Fatalf("Error parsing formatted signature: %s", err)
}
keys, err := parsed.Verify()
if err != nil {
t.Fatalf("Error verifying signature: %s", err)
}
if len(keys) != 1 {
t.Fatalf("Error wrong number of keys returned")
}
if keys[0].KeyID() != key.KeyID() {
t.Fatalf("Unexpected public key returned")
}
var unmarshalled map[string]interface{}
err = json.Unmarshal(b, &unmarshalled)
if err != nil {
t.Fatalf("Could not unmarshall after parse: %s", err)
}
}
func TestFormattedFlatJson(t *testing.T) {
key, err := GenerateECP256PrivateKey()
if err != nil {
t.Fatalf("Error generating EC key: %s", err)
}
testMap, firstSection := createTestJSON("buildSignatures", "")
unindented, err := json.Marshal(testMap)
if err != nil {
t.Fatalf("Marshall error: %s", err)
}
js, err := NewJSONSignature(unindented)
if err != nil {
t.Fatalf("Error creating JSON signature: %s", err)
}
err = js.Sign(key)
if err != nil {
t.Fatalf("Error signing JSON signature: %s", err)
}
b, err := js.PrettySignature("buildSignatures")
if err != nil {
t.Fatalf("Error signing map: %s", err)
}
if bytes.Compare(b[:len(firstSection)], firstSection) != 0 {
t.Fatalf("Wrong signed value\nExpected:\n%s\nActual:\n%s", firstSection, b[:len(firstSection)])
}
parsed, err := ParsePrettySignature(b, "buildSignatures")
if err != nil {
t.Fatalf("Error parsing formatted signature: %s", err)
}
keys, err := parsed.Verify()
if err != nil {
t.Fatalf("Error verifying signature: %s", err)
}
if len(keys) != 1 {
t.Fatalf("Error wrong number of keys returned")
}
if keys[0].KeyID() != key.KeyID() {
t.Fatalf("Unexpected public key returned")
}
}
func generateTrustCA() (PrivateKey, *x509.Certificate) {
key, err := GenerateECP256PrivateKey()
if err != nil {
panic(err)
}
cert := &x509.Certificate{
SerialNumber: big.NewInt(0),
Subject: pkix.Name{
CommonName: "CA Root",
},
NotBefore: time.Now().Add(-time.Second),
NotAfter: time.Now().Add(time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
}
certDER, err := x509.CreateCertificate(
rand.Reader, cert, cert,
key.CryptoPublicKey(), key.CryptoPrivateKey(),
)
if err != nil {
panic(err)
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
panic(err)
}
return key, cert
}
func generateIntermediate(key libtrust.PublicKey, parentKey PrivateKey, parent *x509.Certificate) *x509.Certificate {
cert := &x509.Certificate{
SerialNumber: big.NewInt(0),
Subject: pkix.Name{
CommonName: "Intermediate",
},
NotBefore: time.Now().Add(-time.Second),
NotAfter: time.Now().Add(time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
}
certDER, err := x509.CreateCertificate(
rand.Reader, cert, parent,
key.CryptoPublicKey(), parentKey.CryptoPrivateKey(),
)
if err != nil {
panic(err)
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
panic(err)
}
return cert
}
func generateTrustCert(key libtrust.PublicKey, parentKey PrivateKey, parent *x509.Certificate) *x509.Certificate {
cert := &x509.Certificate{
SerialNumber: big.NewInt(0),
Subject: pkix.Name{
CommonName: "Trust Cert",
},
NotBefore: time.Now().Add(-time.Second),
NotAfter: time.Now().Add(time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
certDER, err := x509.CreateCertificate(
rand.Reader, cert, parent,
key.CryptoPublicKey(), parentKey.CryptoPrivateKey(),
)
if err != nil {
panic(err)
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
panic(err)
}
return cert
}
func generateTrustChain(key PrivateKey, ca *x509.Certificate) (PrivateKey, []*x509.Certificate) {
parent := ca
parentKey := key
chain := make([]*x509.Certificate, 6)
for i := 5; i > 0; i-- {
intermediatekey, err := GenerateECP256PrivateKey()
if err != nil {
panic(err)
}
chain[i] = generateIntermediate(intermediatekey, parentKey, parent)
parent = chain[i]
parentKey = intermediatekey
}
trustKey, err := GenerateECP256PrivateKey()
if err != nil {
panic(err)
}
chain[0] = generateTrustCert(trustKey, parentKey, parent)
return trustKey, chain
}
func TestChainVerify(t *testing.T) {
caKey, ca := generateTrustCA()
trustKey, chain := generateTrustChain(caKey, ca)
testMap, _ := createTestJSON("verifySignatures", " ")
js, err := NewJSONSignatureFromMap(testMap)
if err != nil {
t.Fatalf("Error creating JSONSignature from map: %s", err)
}
err = js.SignWithChain(trustKey, chain)
if err != nil {
t.Fatalf("Error signing with chain: %s", err)
}
pool := x509.NewCertPool()
pool.AddCert(ca)
chains, err := js.VerifyChains(pool)
if err != nil {
t.Fatalf("Error verifying content: %s", err)
}
if len(chains) != 1 {
t.Fatalf("Unexpected chains length: %d", len(chains))
}
if len(chains[0]) != 7 {
t.Fatalf("Unexpected chain length: %d", len(chains[0]))
}
}
func TestInvalidChain(t *testing.T) {
caKey, ca := generateTrustCA()
trustKey, chain := generateTrustChain(caKey, ca)
testMap, _ := createTestJSON("verifySignatures", " ")
js, err := NewJSONSignatureFromMap(testMap)
if err != nil {
t.Fatalf("Error creating JSONSignature from map: %s", err)
}
err = js.SignWithChain(trustKey, chain[:5])
if err != nil {
t.Fatalf("Error signing with chain: %s", err)
}
pool := x509.NewCertPool()
pool.AddCert(ca)
chains, err := js.VerifyChains(pool)
if err == nil {
t.Fatalf("Expected error verifying with bad chain")
}
if len(chains) != 0 {
t.Fatalf("Unexpected chains returned from invalid verify")
}
}

Binary file not shown.

Binary file not shown.

View File

@ -1,27 +0,0 @@
package main
import (
"bytes"
"github.com/docker/libtrust"
"log"
)
func main() {
ids, err := libtrust.ListSSHAgentIDs()
if err != nil {
log.Fatalf("Error listing ssh agent ids: %s", err)
}
for i := range ids {
var id libtrust.ID
id = ids[i]
log.Printf("ID: %#v", id.JSONWebKey())
signed, err := id.Sign(bytes.NewReader([]byte("hello there")))
if err != nil {
log.Fatalf("Error signing: %s", err)
}
log.Printf("Signed\n%x", signed)
}
}

View File

@ -1,8 +0,0 @@
{
"crv": "P-256",
"d": "T68FInnZjHW8c8Y3y8UKDEwVEfubGX7mP8X5EOpxRw0",
"kid": "GW4F:GS7P:22KY:SQXM:FI74:SQBS:KRXR:V4TR:IG6Q:7NLL:OJIS:3XXJ",
"kty": "EC",
"x": "B23slGpLr16MTAJ3MaGVZK6QYEb_l5EZkpnrPcdX6JQ",
"y": "xgkrg8u46RGLbAMqeg7tYxMGbsEdpxdZ4liN_V8TNZQ"
}

View File

@ -1,11 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBnzCCAUSgAwIBAgIBADAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdT
N1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6
M1hYSjAeFw0xNDA5MDUyMzA3NTRaFw0yNDA5MDkyMzA3NTRaMEYxRDBCBgNVBAMT
O0dXNEY6R1M3UDoyMktZOlNRWE06Rkk3NDpTUUJTOktSWFI6VjRUUjpJRzZROjdO
TEw6T0pJUzozWFhKMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB23slGpLr16M
TAJ3MaGVZK6QYEb/l5EZkpnrPcdX6JTGCSuDy7jpEYtsAyp6Du1jEwZuwR2nF1ni
WI39XxM1lKMjMCEwDgYDVR0PAQH/BAQDAgAEMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDSQAwRgIhAOFl3YnbPAPd7hRbh2Wpe0RrtZ0KAZGpjKk3C1ZhQEG4
AiEAh6R8OVclkFNXFbQML8X5uEL+3d7wB+osNU0OlHFaiiQ=
-----END CERTIFICATE-----

View File

@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcy
QjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6
WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMT
O1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02
MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ
4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN
3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkC
IDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdT
N1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6
M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMT
O09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNV
TEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80e
o8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8Uw
Raw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsC
IQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg==
-----END CERTIFICATE-----

View File

@ -1,35 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
},
{
"subject": "/library",
"permission": 15,
"grantee": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4"
},
{
"subject": "/library",
"permission": 15,
"grantee": "PTC6:ABN6:Q4GG:GAAP:ZI7C:4TVD:NERQ:IWSC:UWVO:4HUK:DSI6:4NKD"
}
],
"expiration": "2017-03-19T19:30:00.894517334Z",
"issuedAt": "2015-03-19T19:30:00.894517667Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "KjhqAzsjY87dEyVdQkGoMgJciUalpFla1bno6KnZR6irMhfTxH_qwP69VAqPRrhHV5UdplAeKCDgTiXI6tphFg",
"protected": "eyJmb3JtYXRMZW5ndGgiOjYxNiwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE1LTAzLTE5VDE5OjMwOjAwWiJ9"
}
]
}

View File

@ -1,17 +0,0 @@
[
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
},
{
"subject": "/library",
"permission": 15,
"grantee": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4"
},
{
"subject": "/library",
"permission": 15,
"grantee": "PTC6:ABN6:Q4GG:GAAP:ZI7C:4TVD:NERQ:IWSC:UWVO:4HUK:DSI6:4NKD"
}
]

View File

@ -1,8 +0,0 @@
{
"crv": "P-256",
"d": "vIA7rvskakiQZI33vYTsOr_icsaTkQoml5IZjFAdBzA",
"kid": "OQIS:G2B4:P7QB:G3ZI:THPN:ZITM:UDP2:V7ZS:US6H:CULD:RIZB:X7PI",
"kty": "EC",
"x": "K0pEXXaql80eo8khKBUhwg8fXwDnc-QIR3CB86JnCVg",
"y": "hFrJFKwZkGb3XPCUw7cQQr37PZxu8mfFMEWsOhvUHVI"
}

View File

@ -1,17 +0,0 @@
[
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
},
{
"subject": "/library",
"permission": 15,
"grantee": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4"
},
{
"subject": "/library",
"permission": 15,
"grantee": "TIX7:E75F:VWRT:NFT6:3E25:TPJX:CAEL:YBHA:FTLE:IDGI:BBJ5:HS67"
}
]

View File

@ -1,25 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
}
],
"expiration": "2014-12-29T00:08:20.565183779Z",
"issuedAt": "2014-09-30T00:08:20.565183976Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "uYMwXO869mGDkq7jrE-xfXHcY96JkcIZt_lLWidUtK4Z3-VH8UJx8j-bHQh0rD3C4Olsx7SY5dDOO_Zq60_i1w",
"protected": "eyJmb3JtYXRMZW5ndGgiOjMwMCwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTMwVDAwOjA4OjIwWiJ9"
}
]
}

View File

@ -1,30 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
},
{
"subject": "/library",
"permission": 15,
"grantee": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4"
}
],
"expiration": "2017-02-19T22:55:15.973200265Z",
"issuedAt": "2015-02-19T22:55:15.973200588Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "YYP07HOiZWVZ5ZYBvFW5FOlAbY86GrLQ62uGpDphPAJFUFzGgCZCuN04iXVIyFueiJOS6brPSV2dDcd_LlSz-A",
"protected": "eyJmb3JtYXRMZW5ndGgiOjQ1OCwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE1LTAyLTE5VDIyOjU1OjE1WiJ9"
}
]
}

View File

@ -1,30 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
},
{
"subject": "/library",
"permission": 15,
"grantee": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4"
}
],
"expiration": "2015-05-20T22:07:15.075359917Z",
"issuedAt": "2015-02-19T22:07:15.075360044Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "te7xmIGQ9EGfYjikIwx0orqZ8WWH7DQN7-sAsoyfDfv_uq5DpgRqs5qkW_rGkwsbF37rq6Bdhdwktvt9YsmlVA",
"protected": "eyJmb3JtYXRMZW5ndGgiOjQ1OCwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE1LTAyLTE5VDIyOjA3OjE1WiJ9"
}
]
}

View File

@ -1,35 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
},
{
"subject": "/library",
"permission": 15,
"grantee": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4"
},
{
"subject": "/library",
"permission": 15,
"grantee": "TIX7:E75F:VWRT:NFT6:3E25:TPJX:CAEL:YBHA:FTLE:IDGI:BBJ5:HS67"
}
],
"expiration": "2017-03-22T19:04:46.713978458Z",
"issuedAt": "2015-03-22T19:04:46.713978769Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "h-4MmsL1QB9lEfq2V4MVpZNcuiw0cKYP4C8T-nd4JtU1WhJ1q2_9mMQmtaXOdg6wWTcBll1bbf11UwXP26OhaA",
"protected": "eyJmb3JtYXRMZW5ndGgiOjYxNiwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE1LTAzLTIyVDE5OjA0OjQ2WiJ9"
}
]
}

View File

@ -1,25 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
}
],
"expiration": "2014-12-29T00:08:20.565183779Z",
"issuedAt": "2014-09-30T00:08:20.565183976Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "uYMwXO869mGDkq7jrE-xfXHcY96JkcIZt_lLWidUtK4Z3-VH8UJx8j-bHQh0rD3C4Olsx7SY5dDOO_Zq60_i1w",
"protected": "eyJmb3JtYXRMZW5ndGgiOjMwMCwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTMwVDAwOjA4OjIwWiJ9"
}
]
}

View File

@ -1,30 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
},
{
"subject": "/library",
"permission": 15,
"grantee": "OIH7:HQFS:44FK:45VB:3B53:OIAG:TPL4:ATF5:6PNE:MGHN:NHQX:2GE4"
}
],
"expiration": "2015-02-22T22:47:54.722420237Z",
"issuedAt": "2014-11-24T22:47:54.722420583Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "WIxdNx3olDbq4fLRx46HHKyghPqpqTMB_RJkI5mCLrg3lIFq8ke-gNgfD_xDHHKgV7CBdmQpUS-FDABcKhQ_0g",
"protected": "eyJmb3JtYXRMZW5ndGgiOjQ1OCwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTExLTI0VDIyOjQ3OjU0WiJ9"
}
]
}

View File

@ -1,8 +0,0 @@
{
"crv": "P-256",
"d": "6kQq64Rv3qOPLbS9Yj125E1y0ytaUxL8zBA6NJcVEPM",
"kid": "W52V:BWCQ:OUY6:IQ5N:X5XG:M7KJ:GX6P:TWMQ:ZFHJ:M632:K23V:XF45",
"kty": "EC",
"x": "G9rANGMaOxoZ4XzItNBpqrzZLe_hyMY_hnlXARER0rY",
"y": "xKeQecpebA2GlxCPNFYKVBjb5XhTlXO8jd63JU9eLZs"
}

View File

@ -1,57 +0,0 @@
### Motivation
Currently, client to daemon authentication over a TCP port can only be achieved through generating TLS certificates for both the client and daemon. Each daemon instance then needs to be configured to use the generated TLS certificate and the client must specify its own certificate as well. Production critical, large-scale deployments should already be using this method to secure and control access to Docker daemons, but the extra setup required by generating your own keys, getting them signed by a certificate authority, and distributing those certificates is too much overhead for setting up small-scale deployments such as a Boot2Docker VM running on a developer's Mac, for example. Software developers are already familiar with how SSH key distribution works: through a list of authorized_keys on the server and known_host keys on the client. Ideally each instance of the Docker engine (client or daemon) would have a unique identity represented by its own public key. With a list of trusted public keys, two engines can authenticate to eachother and the daemon can authorize the connection. This can be done at the TLS layer after initially loading a list of trusted public keys into a CA Pool.
### Proposal Summary
Every instance of Docker will have its own public key which it either generates and saves on first run or loads from a file on subsequent runs. The public key will be distributed to other instances by a user of docker or system administrator to allow connections between two docker engines. Each instance will have a list of public keys which are trusted to accept connections from (trusted clients) and a separate list which it trusts to make connectionss to (trusted hosts). These public keys will be stored as JSON Web Keys and can be distributed as a JSON file, or as a standard PEM file. For TLS connections, the Docker engine's key pair will be used to generate a self-signed TLS certificate and the list of public keys will be used to generate a certificate pool with a certificate authority for each public key. For TLS servers the list of public keys will be loaded from an authorization file (authorized_keys.json) and for TLS clients the list will be loaded from a known hosts file (allowed_hosts.json), a client must always provide its certificate if the daemon requires it. In addition, a certificate authority PEM file will be allowed to be specified to maintain the existing TLS behavior. As another possible addition, upon connecting to a previously unknown server, a CLI user can be prompted to allow a public key now and in the future, leaving it up the users discretion.
### Key Files
Docker will support key files in either JSON Web Key format or more traditional PEM format.
##### Private and Public Key files
Both the docker daemon and client will have a private key file and a public key file in either of these formats. A client's private key default location will be at `~/.docker/key.(pem|json|jwk)` and public key at `~/.docker/pub_key.(pem|json|jwk)` where `~` is the home directory of the user running the `docker` client. The daemon's private key default location will be at `/var/lib/docker/key.(pem|json|jwk)` and public key at `/var/lib/docker/pub_key.(pem|json|jwk)`. Unix file permissions for these private keys MUST be set to `0600`, or 'Read/Write only by User'. It is suggested that the public keys have permissions set to `0644`, or 'Read/Write by User, Read by group/others'. Because these keys may have a variable file extension, Docker will load whichever one matches the glob `key.*` first, so it is NOT RECOMMENDED that there be multiple `key.*` files to avoid any ambiguity over which key file will be used. If the `--tlskey=KEYFILE` argument is used, that exact file will be used. Optionally, we may add a config file for Docker client and daemon in which users may specify the file to use, but that possibility is up for discussion.
##### Authorized Keys file
An instance of the Docker engine in daemon mode will need to know which clients are authorized to connect. We propose a file which contains a list of public keys which are authorized to access the Docker Remote API. This idea is borrowed from SSH's `authorized_keys` file. Any client which has the corresponding private key for any public key in this list will be able to connect. This is accomplished by generating a Certificate Authority Pool with a CA certificate automatically generated by the daemon for each key in this list. The server's TLS configuration will allow clients which present a self-signed certificate using one of these keys. Like today, the daemon can still be configured to use a traditional Certificate Authority (the `--tlscacert=CACERTFILE` option). The default location for this file will be `/var/lib/docker/authorized_keys.(pem|json|jwk)`. Docker will also look for trusted client keys in individual files in a directory at `/var/lib/docker/authorized_keys.d` in either PEM or JWK format.
##### Trusted Hosts file
An instance of the Docker engine in client mode will need to know which hosts it trusts to connect to. We propose a file which contains a list of public keys which the client trusts to be the key of the Docker Remote API server it wishes to connect to. This idea is borrowed from SSH's `know_hosts` file. Any daemon which has the corresponding private key for a public key in this list AND presents a self-signed server certificate in the TLS handshake which has the desired server name (hostname or IP address of `$DOCKER_HOST`) using one of these keys. Like today, the client can still be configured to use a traditional Certificate Authority (the `--tlscacert=CACERTFILE` option). The TCP address (in the form of `<hostname_or_ip>:<port>`) will be specified for each key using extended attributes for the key, i.e, a `address` JSON field if in JWK format or a `address` header if in PEM format. The default location for this file will be `~/.docker/trusted_hosts.(pem|json|jwk)`. Docker will also look for trusted host keys in individual files in a directory at `~/.docker/trusted_hosts.d` in either PEM or JWK format.
### Key Types
By default, a Docker engine will generate an ECDSA key, using the standard P-256 elliptic curve, if a private key file does not already exist. Supported Elliptic Curves are P-256, P-384, and P-521. RSA keys are also supported. The default of Elliptic Curve Cryptography was chosen due to more efficient key generation and smaller key sizes for equivalent levels of security when compared to RSA [[reference](http://www.nsa.gov/business/programs/elliptic_curve.shtml)].
### User visible changes
- TLS is always used for when using tcp:// (unix:// does not require)
- Client TLS verification is on by default (`--insecure` flag added to disable)
- Server TLS verification is on by default (`--insecure` flag added to disable)
- `--tls` and `--tlsverify` flags removed
- `-i`/`--identity` flag to specify the identity (private key) file
- User prompt added when connecting to unknown server
### Backwards Compatibility
In order to maintain backwards compatibility, existing TLS ca, cert, and key options for setting up TLS connections will be allowed. Scripts using `--tls` and `--tlsverify` will need to remove these options since these are now the default. To use the existing insecure behavior, run scripts will need to be modified to use `--insecure`, this is not recommended. These changes do no have any effect on servers using unix sockets.
- Connecting from older client: The client must generate a certificate which is distributed to the server. Optionally the newer server can run with `--insecure` which will require no changes to the client.
- Connecting to an older server: If non-TLS, Client will maintain ability to connect to endpoint using the `--insecure` flag. If TLS is manually configured, no changes should be required.
### Usage Pattern
- Single Machine - Setup using Unix socket, no changes
- Single Machine (with non-B2D VM) -
- Invoke docker on host to generate key.json
- Invoke docker on guest to generate key.json
- Copy ~/.docker/pub_key.json on guest to /var/lib/docker/trusted_hosts.d/guest.json on host
- Copy /var/lib/docker/pub_key.json on host to ~/.docker/authorized_keys.d/host.json on guest (optionally use prompt)
- Single Machine (B2D) - Boot2Docker installation generates and copies keys
- Two Machines -
- Invoke docker on client to generate key.json
- Invoke docker on server to generate key.json
- Copy ~/.docker/pub_key.json on client to ~/.docker/authorized_keys.d/client.json on server
- Copy /var/lib/docker/pub_key.json on server to ~/.docker/trusted_hosts.d/server.json on client

View File

@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC7DCCAdagAwIBAgIRAMzw0lcScp8VgiIX5W18bkUwCwYJKoZIhvcNAQELMBYx
FDASBgNVBAoTC0Jvb3QyRG9ja2VyMB4XDTE0MTAxMzIxMjIyOVoXDTE3MDkyNzIx
MjIyOVowEzERMA8GA1UEChMIUmVnaXN0cnkwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQC8V4jsxvsRZ5ml1Q/VXtrJStFcTjzwh2niEPCvER6xYcWHloMM
A6q8cvoHYv2/1ELbKQbLaIuKowWa3gvsiL1Fs3b02jv0a9rN4kFofkRLKuvYKroB
Y2P06LNT/sXnE+jCSw9OEdYZuoVXeohmVpcQUCeh8LNDS0b+vg+fU/O46iggUlqu
LOaXC8A68SSiBP6qG/cOBPNmfGi09G8sCJ7b7Xd2J8MPeUovNVw+2Wfj4Bzox8s/
7B9Ef6iIfwdkvclHoBZIzclJdA0ew5aam/a7SStuRMgX7yhDfRh9sRiyv/ZvKXW6
CUy0Oqa//UlmQoC6K3kOm/EMzPocI6NwJ53PAgMBAAGjPDA6MA4GA1UdDwEB/wQE
AwIAoDAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATAL
BgkqhkiG9w0BAQsDggEBAJjOpgKhzlMcrWhh2pFNaHK77IIROMG8XgmdWE3u2IS9
oKbe31n1scyNIvUkrE11iwqJ+4i6C9/eHf1sTz1sHSoBA+7w9O7ghErQ5XK+rfZD
Ax/Bu7o1lpnxtrQTiMaVUXZrBnowooDCdjyQyX0BeiIIRhQyBbx3lMpfjbyXFM/l
hTuRC8Mt2QSu6pn+Le8t9rlkFq9exHg0Jng1ZpaJWCt6K27J8rMS3jngFUa2ihG6
d5vSu6Gqaqhtki4uGA2mUu7RPUhZ5H+WLmDknHeD3/k9ASloa6jw2ehcyU9o4PMB
5Lr1zMEG5RkNDVcE5qurWNrpZc1ajPomxmuTrcwO6vQ=
-----END CERTIFICATE-----

View File

@ -1,173 +0,0 @@
// Usage:
// Generate CA
// ./generate_cert --cert ca.pem --key ca-key.pem
// Generate signed certificate
// ./generate_cert --host 127.0.0.1 --cert cert.pem --key key.pem --ca ca.pem --ca-key ca-key.pem
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"log"
"math/big"
"net"
"os"
"strings"
"time"
)
var (
host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
certFile = flag.String("cert", "", "Output file for certificate")
keyFile = flag.String("key", "", "Output file for key")
ca = flag.String("ca", "", "Certificate authority file to sign with")
caKey = flag.String("ca-key", "", "Certificate authority key file to sign with")
)
const (
RSABITS = 2048
VALIDFOR = 1080 * 24 * time.Hour
ORG = "Registry"
)
func main() {
flag.Parse()
if *certFile == "" {
log.Fatalf("Missing required parameter: --cert")
}
if *keyFile == "" {
log.Fatalf("Missing required parameter: --key")
}
if *ca == "" {
if *caKey != "" {
log.Fatalf("Must provide both --ca and --ca-key")
}
if err := GenerateCA(*certFile, *keyFile); err != nil {
log.Fatalf("Failured to generate CA: %s", err)
}
} else {
if err := GenerateCert(strings.Split(*host, ","), *certFile, *keyFile, *ca, *caKey); err != nil {
log.Fatalf("Failured to generate cert: %s", err)
}
}
}
// newCertificate creates a new template
func newCertificate() *x509.Certificate {
notBefore := time.Now()
notAfter := notBefore.Add(time.Hour * 24 * 1080)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
log.Fatalf("failed to generate serial number: %s", err)
}
return &x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{ORG},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
//ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
}
// GenerateCA generates a new certificate authority
// and stores the resulting certificate and key file
// in the arguments.
func GenerateCA(certFile, keyFile string) error {
template := newCertificate()
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign
priv, err := rsa.GenerateKey(rand.Reader, RSABITS)
if err != nil {
return err
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv)
if err != nil {
return err
}
certOut, err := os.Create(certFile)
if err != nil {
return err
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close()
return nil
}
// GenerateCert generates a new certificate signed using the provided
// certificate authority files and stores the result in the certificate
// file and key provided. The provided host names are set to the
// appropriate certificate fields.
func GenerateCert(hosts []string, certFile, keyFile, caFile, caKeyFile string) error {
template := newCertificate()
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, h)
}
}
tlsCert, err := tls.LoadX509KeyPair(caFile, caKeyFile)
if err != nil {
return err
}
priv, err := rsa.GenerateKey(rand.Reader, RSABITS)
if err != nil {
return err
}
x509Cert, err := x509.ParseCertificate(tlsCert.Certificate[0])
if err != nil {
return err
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, x509Cert, &priv.PublicKey, tlsCert.PrivateKey)
if err != nil {
return err
}
certOut, err := os.Create(certFile)
if err != nil {
return err
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close()
return nil
}

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAvFeI7Mb7EWeZpdUP1V7ayUrRXE488Idp4hDwrxEesWHFh5aD
DAOqvHL6B2L9v9RC2ykGy2iLiqMFmt4L7Ii9RbN29No79GvazeJBaH5ESyrr2Cq6
AWNj9OizU/7F5xPowksPThHWGbqFV3qIZlaXEFAnofCzQ0tG/r4Pn1PzuOooIFJa
rizmlwvAOvEkogT+qhv3DgTzZnxotPRvLAie2+13difDD3lKLzVcPtln4+Ac6MfL
P+wfRH+oiH8HZL3JR6AWSM3JSXQNHsOWmpv2u0krbkTIF+8oQ30YfbEYsr/2byl1
uglMtDqmv/1JZkKAuit5DpvxDMz6HCOjcCedzwIDAQABAoIBAQCDKJZTBbK8CSCH
yptPJNJJ0Y+Ar39ipXqIEvH5iHuOXZ8YcClsiXUx7QPPdxFssF2qj6SKrJBYiHST
x8QYAZWFX5gcpYmRCjcCn2ibYyseCZLaI88KvnNSj2aqvMaGyGeUPn83B9bIbgsD
w3IPioeCtb8T2DKOT3LuXd81PlqAz2Q2O1OHhTpWYA9gLAeXx+z6jU+Cvn9z67n0
+9utUTk8n+SN4+K4h7ufM7CFzLgnugyrhvIgm0NfHDhR9SBwwSTJ/J1CrD4TLkIm
d3HetZemfRjByg11Zrltm3YgxdTWKrjfqX3XguR/6HIiXvo5vWhs5DAuQtvTc8Wa
ahceS2KxAoGBAMPqj8mWu+LSlWmXIx2gXNPkhK1EovZL0gImouWbb7kCHxQNYTJs
wWzG61y9NdCHkhbCDsGXj9rFpPlrDr567gMZTYmLBzcB8DXpHr5XPyl6ZDqYs/L0
4jDTSG/tthIDnxVY1O+bGrzknVpakrgJ9H2yivgWIWBVX3XUfXEH8f4HAoGBAPYa
T5408onWBzWpbydvPd4loAbuCgG2bXOJjqsyZALHS4SoDQ2HUIZokVlf9yWOzyhd
R8iWYADhMps+/wVW6eNAva3hCzI8US0ZiF7SgIZlq31UV1kDXl/XV+ccFp1R95KV
c0VbRw2Tqzhmdu7OcvysP8FYZvGWGCev6Opxqe/5AoGBAJDt1xp4kFsWDwOCk66Z
77GsTd3jdW4f3qZKsJyMJNTG1fi+gRWNUHVIndoH+mRdtdtyCPp7RSbAqO79nHWa
eLIAKNTD7T1rCKjI4D5MSmRDrxuN1Si4sQ8PbXmnbtXaqfdftH3fzqLHuAOcFwdg
DeZiit1FecFKxohi/bz89K5HAoGAQI0qMQ8mRu0yuuqUUz2kdq5byTWKvmRBVTrR
hyoSfYAU2NjTg6bogjjPVygKxXkt8SJ2f7ChwdlP0tS1Q4tGkesbVY5fx292w2Od
F3ITcC0ezCLhPmHZ0T3EusPtUpp7W6GDuL92ZaNEF+kYbQ8NriToHCi558g80bwc
VdI2htECgYEAjOkauwVyJrNt3/NNW7yv/hLOzgX+Cxe9GSWZj9LoYdjB1Y9/rzyq
f2YGdmyrrY8dWXHI9YK/RXk9/r2EDNNGwyH0+6na5pS5D+r78DhS1fiba7EJrPYK
s68QsKo397pa6gWhlQpsUJr97/y2V9Fba8SINnzzmG0zJehPGQXuRFc=
-----END RSA PRIVATE KEY-----

View File

@ -1,18 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIC3DCCAcagAwIBAgIQXHT/h2+fDzoIxPvBTexiCjALBgkqhkiG9w0BAQswFjEU
MBIGA1UEChMLQm9vdDJEb2NrZXIwHhcNMTQxMDEzMjIxMzI5WhcNMTcwOTI3MjIx
MzI5WjATMREwDwYDVQQKEwhSZWdpc3RyeTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAPKkPwCO4bgmrJek6lWjToBuyF4Or3E/38GwIECpuZuymoBs4C1B
7Qp7oOrGIRh96htgYPl5WkDUM0If9yG2bDR9JwLxs5OEZrwLbzsvDgaGYiLocElH
nKoUdorkr2DtG/rBOgiAqiw9Rw4+Bb0J09hx/Q+S9xuebthSnnKKtBXicBfmHkbD
UhfolSdbdBa4u3R2gkFzGXCoAnuYJSerO6fewCJTg2jWxGjuU/Ekm3m13XWQWBis
OQN7qGRr/sHLaB4wp69X/mtOKyK1BoGPYV2f73VKremU52QsTcpYw9q6Zoy/iztq
WZMVY0Mo4x1TvVKFlzbb9g3UpqDEZCgxS60CAwEAAaMtMCswDgYDVR0PAQH/BAQD
AgCgMAwGA1UdEwEB/wQCMAAwCwYDVR0RBAQwAoIAMAsGCSqGSIb3DQEBCwOCAQEA
rq6CCnZKw39nT8VVAMiGS63q6+eGX0u8SjsPQu7qqxDex4La09rAZzlfh2GvusCz
kJcFyliCwbZTZqFyfYXex+dFgBRaGmjTaE5ZKS7e0UV0oPE4ig9OFMl8/5dsOWJe
3SpXOwC41idNAqzJ/StcWy2IIco7TM3YcjCFQeHwNOpspgOiTN3CYkUCmxkRVd2q
U8aEvk6/rmmVCesDWsAAngfdHPRVca7PSn8Xz0hglHtdTsO/32EfCmOJI9Lc78cR
6g9mX98oJwstQYTsA7lvcTArbCVhbQ/4z8T/AZu2P89Nr8+GW6XRxM5Ne08RnvlE
IZa1y0Fg07FIqgJB3HAbHA==
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA8qQ/AI7huCasl6TqVaNOgG7IXg6vcT/fwbAgQKm5m7KagGzg
LUHtCnug6sYhGH3qG2Bg+XlaQNQzQh/3IbZsNH0nAvGzk4RmvAtvOy8OBoZiIuhw
SUecqhR2iuSvYO0b+sE6CICqLD1HDj4FvQnT2HH9D5L3G55u2FKecoq0FeJwF+Ye
RsNSF+iVJ1t0Fri7dHaCQXMZcKgCe5glJ6s7p97AIlODaNbEaO5T8SSbebXddZBY
GKw5A3uoZGv+wctoHjCnr1f+a04rIrUGgY9hXZ/vdUqt6ZTnZCxNyljD2rpmjL+L
O2pZkxVjQyjjHVO9UoWXNtv2DdSmoMRkKDFLrQIDAQABAoIBAHkE4IN3wC7n4ydT
UqlZ5Tp7hqYa7vguInzpSnzV6kQ0xYiORRVtjzuuQ6k1Hqanjo8O9+8VzqUM8W/m
n40J/lgDn+SBBs7pt4/MqDK9mmI4vlOo2PBDrmjKAgHuY2aVfGIJ49b/zWB5Q6pf
1t7dOvL2j4AoDeWRlLmCI5L/iShsKlm8isnEqnvSoWYQEIjyesum8LhjfvDVyvl7
huOiIbwqCz5198GedhrbCRE4O/owbv9e1yv9RpV/Kruauw+W1uRg4o+WAzvaZ71q
rzlJAi0TQ144E0DqCmCswpJpB/jxK+prcagdTY80SYxg+MPToqqwlUGzwP4piHyO
Hltqm6UCgYEA+7IufLh6nhTgVRD5nPAVDZXxA5906YlZTWTeRH5gOBWoULh+4Ur/
L+hEZzwiZz5cdWf+qggDmO8HAgtbvUdgMddAOGfEcsVma+H1BqD6ktFXU3tuFqPG
+Mvtz7uDpyVCSiltBOBtI/Ps6VXXRyjXtpWir3QCjLn+emFlxB/kTKMCgYEA9spt
k6TcFMVI8pXzpDhi4WDaf63/WftF3+FBCXLIejq1gQH0edUtKTYieyajgemo4/ph
3LiF9P6lWLRjHpWyrIlW5j3qSOXu/KX1MkKGUnWXXu5EXf+U5+yXl/LgNvgkA3Rc
lpIiL6xhJkkOn0b9b6SfDO3Mkc+fdFLNtoFzu28CgYBhwLEXVVqh/L+nqiEX15KF
pT9mxc5VSTe6vDsq5N4fyiGFwDHe9A6qH445ffxqlqi4HHymstga1HKnU5v8pjTx
BoV1oq+EV7BQpABS48CNtuowjRaTimYjiKhC7rPR/cGCJhamNzeMKBdSBDnI9E7b
JcB6XhcDatUv2JX6ltxG+wKBgEGqbymf7idgrx5NI/0IO9c4TCs5Av7QSzFc4E9B
SXKseGsROBnKzS9wBhC6oTsKDzRKBQwT1SDxONG3fcA/mMEr8gFlbBdlhweWqP1s
kg0S2Oobf/l67gYf/94gc+RsdjitF43A6HPC7D6hpdBftUOli+SGya3qjsUG21G6
dC7lAoGAJ84wM2yGU358OCmMdbxdjSpwk3P5ue+kcZqYa6R9NX503hg+zdDAnPzS
Dn0Psf7XKklGqMnDRLyusKNPE4hhR/AukeGvBpB8rntBkXvBn0gR3Pz9mJioUvCw
nvsYNrv7yPaMUjDpi3tlDdCxA/c1OYI4nPD1RO1z6KtXzXumg6k=
-----END RSA PRIVATE KEY-----

View File

@ -1,12 +0,0 @@
{
"keyType": "jwk",
"keyId": "KVKI:GMUJ:FMD7:7BWO:KP7O:QIWP:VRDG:IAWU:MJ6Z:GX35:N6E5:XCD6:2AIQ",
"key": {
"crv": "P-256",
"d": "woOnFXsfJ2UhOW0A0sHRQr-j-ylaFp5hSqv9MXaWIfA",
"kid": "KVKI:GMUJ:FMD7:7BWO:KP7O:QIWP:VRDG:IAWU:MJ6Z:GX35:N6E5:XCD6:2AIQ",
"kty": "EC",
"x": "7C7zxqK8TJUO0yiO3QHhaUm5gjBO_u4UN6Gdw2U846Y",
"y": "11bnKVNb4Yoy0rpJA7slvBm44Lmc4c36h_LjEP8PJmQ"
}
}

View File

@ -1,5 +0,0 @@
MHcCAQEEIFlzVietDbzPESwRynJaAZA38KgGkyxkmnOko1OAxniMoAoGCCqGSM49AwEHoUQDQgAEL1Rx9iUzepbmqQub62qSPgC2YTabUFtnqDXNrfN7g2z0P9FYV/ScBIqxnBDdV6Sy1ZIrfUgiuA7JyaABg4hjCw==
MHcCAQEEIGrv2ULb+HV3KoJlciMJ1THswtYxvZ9HVrvIVYaZyt3UoAoGCCqGSM49AwEHoUQDQgAEV+CHKKPoF1rFiVkFiEdoXlXa8UybgoNPQmPVr8ImuR0grslx2Tk/Ja/23CYzYtLeEuRa+lRQSxKa2NjDo7BhfQ==
MHcCAQEEIBxKadItcsdt+lqIh9fCOYX8OpTiIYLlaeZWeKxvJrw4oAoGCCqGSM49AwEHoUQDQgAEp8JenwbJSTVXKS0IHH1KrwPgF7duEwV3aIejGYiBlVZDdgz+DzJcQOGEh9gcOjQ02p7/ciwE4RGZVWs5gUi2nA==
MHcCAQEEIEP8tpIAkgABEl87mJgiPLkdUIjowoDWFm6phU8bTpZ4oAoGCCqGSM49AwEHoUQDQgAEMvc0R61PCQT+NmyJjnjJugzZhfab2yb/7t40DiehQhotCpAiFY1xRIeTq0TphgsFAR7TSRajvBVwdPYfEypOAQ==
MHcCAQEEIHQ1lyvaMTwnbab+NRQvZY4+uvrRwhiotyrZHkfnNWpSoAoGCCqGSM49AwEHoUQDQgAEujEqwGrX0laAM+OHIjM/84n/eYitBmcTTNPgoRaiGfd5xdFPdtTG6ZSt4/m+FBdQ1RAF8bvYPgyMmvm8V7uFDg==

View File

@ -1,5 +0,0 @@
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

View File

@ -0,0 +1,8 @@
-----BEGIN EC PRIVATE KEY-----
comment: TLS Demo Client
keyID: YCNH:BVIR:5GVK:RZOG:JNWW:ZL4B:MQRY:WXEF:AOOD:S6N6:FQZW:RGZ2
MHcCAQEEIOLL3nXjiX0XDSRNYV7jH7Tpd1QGoeKedwGTmB96bz77oAoGCCqGSM49
AwEHoUQDQgAEHpO8+XFpL5+dcOazOlZDfnVNif+HSZxFaQ2bLcslQKUdIkrV2+Up
tQd6fXupPYDVfWGuelkQrdel5ObnMAZ8YQ==
-----END EC PRIVATE KEY-----

View File

@ -0,0 +1,8 @@
-----BEGIN PUBLIC KEY-----
comment: TLS Demo Client
keyID: YCNH:BVIR:5GVK:RZOG:JNWW:ZL4B:MQRY:WXEF:AOOD:S6N6:FQZW:RGZ2
kid: YCNH:BVIR:5GVK:RZOG:JNWW:ZL4B:MQRY:WXEF:AOOD:S6N6:FQZW:RGZ2
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHpO8+XFpL5+dcOazOlZDfnVNif+H
SZxFaQ2bLcslQKUdIkrV2+UptQd6fXupPYDVfWGuelkQrdel5ObnMAZ8YQ==
-----END PUBLIC KEY-----

View File

@ -0,0 +1,8 @@
-----BEGIN PUBLIC KEY-----
hosts: localhost,docker.example.com
keyID: LH6B:6ZBK:D34J:M6E5:RV6I:5BAL:7KGZ:PHCJ:JKDU:7PLV:2D7H:UZR2
kid: LH6B:6ZBK:D34J:M6E5:RV6I:5BAL:7KGZ:PHCJ:JKDU:7PLV:2D7H:UZR2
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGn+xPy/OOCXFidcKb13zfJJV0JwS
BE1vlyxog0tSsN/U8tObgpDKaCE7+9tLl4djnd+blOOIJq6fph/dAZal4A==
-----END PUBLIC KEY-----

View File

@ -0,0 +1,8 @@
-----BEGIN EC PRIVATE KEY-----
hosts: localhost,docker.example.com
keyID: LH6B:6ZBK:D34J:M6E5:RV6I:5BAL:7KGZ:PHCJ:JKDU:7PLV:2D7H:UZR2
MHcCAQEEILDWn14dH5vPo1JWpXrWB5qj6MS51T3XAGp/fuFTUg5IoAoGCCqGSM49
AwEHoUQDQgAEGn+xPy/OOCXFidcKb13zfJJV0JwSBE1vlyxog0tSsN/U8tObgpDK
aCE7+9tLl4djnd+blOOIJq6fph/dAZal4A==
-----END EC PRIVATE KEY-----

View File

@ -0,0 +1,8 @@
-----BEGIN PUBLIC KEY-----
hosts: localhost,docker.example.com
keyID: LH6B:6ZBK:D34J:M6E5:RV6I:5BAL:7KGZ:PHCJ:JKDU:7PLV:2D7H:UZR2
kid: LH6B:6ZBK:D34J:M6E5:RV6I:5BAL:7KGZ:PHCJ:JKDU:7PLV:2D7H:UZR2
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGn+xPy/OOCXFidcKb13zfJJV0JwS
BE1vlyxog0tSsN/U8tObgpDKaCE7+9tLl4djnd+blOOIJq6fph/dAZal4A==
-----END PUBLIC KEY-----

View File

@ -0,0 +1,8 @@
-----BEGIN PUBLIC KEY-----
comment: TLS Demo Client
keyID: YCNH:BVIR:5GVK:RZOG:JNWW:ZL4B:MQRY:WXEF:AOOD:S6N6:FQZW:RGZ2
kid: YCNH:BVIR:5GVK:RZOG:JNWW:ZL4B:MQRY:WXEF:AOOD:S6N6:FQZW:RGZ2
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHpO8+XFpL5+dcOazOlZDfnVNif+H
SZxFaQ2bLcslQKUdIkrV2+UptQd6fXupPYDVfWGuelkQrdel5ObnMAZ8YQ==
-----END PUBLIC KEY-----

Binary file not shown.

View File

@ -1,53 +0,0 @@
package main
import (
"flag"
"io/ioutil"
"log"
"os"
"github.com/docker/libtrust"
)
var ca string
var chain string
var cert string
var signKey string
var validKeys string
func init() {
flag.StringVar(&signKey, "k", "", "Private key to use for signing (pem or JWS file)")
}
func main() {
flag.Parse()
if signKey == "" {
log.Fatalf("Missing key")
}
content, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("Error reading content from stdin: %s", err)
}
sig, err := libtrust.NewJSONSignature(content)
if err != nil {
log.Fatalf("Error creating JSON signature: %s", err)
}
privKey, err := libtrust.LoadKeyFile(signKey)
if err != nil {
log.Fatalf("Error loading priv key: %s", err)
}
sig.Sign(privKey)
// Output signed content to stdout
out, err := sig.PrettySignature("signatures")
if err != nil {
log.Fatalf("Error formatting output: %s", err)
}
_, err = os.Stdout.Write(out)
if err != nil {
log.Fatalf("Error writing output: %s", err)
}
}

View File

@ -1,8 +0,0 @@
{
"crv": "P-256",
"d": "z7JYp-fmJMFPsalhcGy7G0RNdE2l23VDcNh6zYI75aE",
"kid": "UAY5:GSOJ:M4G5:Y5E4:CZ43:HJC4:G5AD:IDW3:GM7B:TRKT:5C3C:H3NH",
"kty": "EC",
"x": "8P_ZDmt8RFIeIDR_vma9SUZOF3GWUV9gDF6MuAJY68I",
"y": "kFEmSOPtggWhun8pyUh3V6oQZYXfQuoz4Ia7ituWpDc"
}

View File

@ -1,11 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBnjCCAUSgAwIBAgIBADAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztVQVk1OkdT
T0o6TTRHNTpZNUU0OkNaNDM6SEpDNDpHNUFEOklEVzM6R003QjpUUktUOjVDM0M6
SDNOSDAeFw0xNDExMDQyMDQxMTVaFw0yNDExMDgyMDQxMTVaMEYxRDBCBgNVBAMT
O1VBWTU6R1NPSjpNNEc1Olk1RTQ6Q1o0MzpISkM0Okc1QUQ6SURXMzpHTTdCOlRS
S1Q6NUMzQzpIM05IMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8P/ZDmt8RFIe
IDR/vma9SUZOF3GWUV9gDF6MuAJY68KQUSZI4+2CBaG6fynJSHdXqhBlhd9C6jPg
hruK25akN6MjMCEwDgYDVR0PAQH/BAQDAgAEMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDSAAwRQIhAKVFo9JVRbjIJaOjgMpPUuVMxfLYffDfiEYOPvJkEu9b
AiBWSPsJyfyiv5sD+qKc/pKU31o9v/gQ8agQMs6weIomrw==
-----END CERTIFICATE-----

View File

@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBnjCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztKQk5IOlgy
R1o6R0tIVzpJWjZEOk1TRzY6R1BZRjo0NDU2OkNFNDY6VDRKNjpWVVdROkZEWlU6
QUxZNDAeFw0xNDExMTEyMDQxMTRaFw0xNTAyMDkyMDQxMTVaMEYxRDBCBgNVBAMT
O1dXQUM6NURWRzpSVlhZOkFQU0M6Q0VaVzpUT1A0Ok1NSEo6RkVaVDpXTU9KOkhW
TFg6SFFNUDo2SldLMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfmp8Xhfx+d5l
FYD+Ouxq3b75DzAnCGjY2iGGwcGRpkmk5dslR9JmySCKl7saJHYcoGdljR1PeYwt
aRiEKL2Nm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDSAAwRQIgBhSPTHU/d4SvN9fD54wM9Es856s7KSikP2CSrvKvNW4C
IQDdwJd7h0u7oMKlD3QSadun4Wwu6hKnMoLevQPeRMV9bA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBnzCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztVQVk1OkdT
T0o6TTRHNTpZNUU0OkNaNDM6SEpDNDpHNUFEOklEVzM6R003QjpUUktUOjVDM0M6
SDNOSDAeFw0xNDExMTEyMDQxMTRaFw0xNTAyMDkyMDQxMTVaMEYxRDBCBgNVBAMT
O0pCTkg6WDJHWjpHS0hXOklaNkQ6TVNHNjpHUFlGOjQ0NTY6Q0U0NjpUNEo2OlZV
V1E6RkRaVTpBTFk0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECoQE4u9QsNH5
FmoDfSQHojxMN/NoFF5qs1Tnp5M9oHTzwT+vFA2g6jArP+ZKl67nLanA/K4pFle8
jgcCobScsKMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDSQAwRgIhANhTbxwevwYurL4GRP4PRreZEvSjgOJnQO0/7FGhzDct
AiEA5gPXKid+i1xQ+ZjiNcuUzdAi828WRqmpPYVbpK18AbA=
-----END CERTIFICATE-----

View File

@ -1,126 +0,0 @@
package main
import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"log"
"math/big"
"os"
"time"
"github.com/docker/libtrust"
)
func writeCertFile(filename string, certs []*x509.Certificate) error {
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return err
}
defer f.Close()
for _, cert := range certs {
err = pem.Encode(f, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
if err != nil {
return err
}
}
return nil
}
func generateIntermediate(parent *x509.Certificate, key libtrust.PublicKey, parentKey libtrust.PrivateKey) (*x509.Certificate, error) {
cert := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: key.KeyID(),
},
NotBefore: time.Now().Add(-time.Second),
NotAfter: time.Now().Add(90 * 24 * time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
}
certDER, err := x509.CreateCertificate(rand.Reader, cert, parent, key.CryptoPublicKey(), parentKey.CryptoPrivateKey())
if err != nil {
return nil, err
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
return nil, err
}
return cert, nil
}
func generateLeaf(parent *x509.Certificate, key libtrust.PublicKey, parentKey libtrust.PrivateKey) (*x509.Certificate, error) {
cert := &x509.Certificate{
SerialNumber: big.NewInt(2),
Subject: pkix.Name{
CommonName: key.KeyID(),
},
NotBefore: time.Now().Add(-time.Second),
NotAfter: time.Now().Add(90 * 24 * time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
certDER, err := x509.CreateCertificate(rand.Reader, cert, parent, key.CryptoPublicKey(), parentKey.CryptoPrivateKey())
if err != nil {
return nil, err
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
return nil, err
}
return cert, nil
}
func main() {
caKey, _ := libtrust.GenerateECP256PrivateKey()
masterKey, _ := libtrust.GenerateECP256PrivateKey()
trustKey, _ := libtrust.GenerateECP256PrivateKey()
log.Printf("Generated keys:\n\tCA: %s\n\tMaster: %s\n\tTrust: %s", caKey.KeyID(), masterKey.KeyID(), trustKey.KeyID())
libtrust.SaveKey("ca-key.json", caKey)
libtrust.SaveKey("master-key.json", masterKey)
libtrust.SaveKey("trust-key.json", trustKey)
// TODO better CA function
ca, err := libtrust.GenerateCACert(caKey, caKey.PublicKey())
if err != nil {
log.Fatalf("Error generating CA: %s", err)
}
err = writeCertFile("ca.pem", []*x509.Certificate{ca})
if err != nil {
log.Fatalf("Error writing CA pem file: %s", err)
}
masterCert, err := generateIntermediate(ca, masterKey.PublicKey(), caKey)
if err != nil {
log.Fatalf("Error generating master certificate: %s", err)
}
// Generate Master Server certificate, signed by CA
// Output master-key.json
leafCert, err := generateLeaf(masterCert, trustKey.PublicKey(), masterKey)
if err != nil {
log.Fatalf("Error generating leaf certificate: %s", err)
}
// Generate key, from key trust Server certificate, signed by master
// Output cert.pem (both trust server and master certificate), key.json
err = writeCertFile("cert.pem", []*x509.Certificate{leafCert, masterCert})
if err != nil {
log.Fatalf("Error generating cert pem file")
}
}

View File

@ -1,8 +0,0 @@
{
"crv": "P-256",
"d": "VTn3fGowJO6x7dYNvmYPIMt2nLJRMOVM-GG6ZdlSUS8",
"kid": "JBNH:X2GZ:GKHW:IZ6D:MSG6:GPYF:4456:CE46:T4J6:VUWQ:FDZU:ALY4",
"kty": "EC",
"x": "CoQE4u9QsNH5FmoDfSQHojxMN_NoFF5qs1Tnp5M9oHQ",
"y": "88E_rxQNoOowKz_mSpeu5y2pwPyuKRZXvI4HAqG0nLA"
}

View File

@ -1,28 +0,0 @@
package main
import (
"io/ioutil"
"log"
"os"
"github.com/docker/libtrust"
)
func main() {
input, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("Error reading stdin: %s", err)
}
sig, err := libtrust.ParsePrettySignature(input, "signatures")
if err != nil {
log.Fatalf("Error parsing pretty signature: %s", err)
}
jws, err := sig.JWS()
if err != nil {
log.Fatalf("Error creating JWS: %s", err)
}
os.Stdout.Write(jws)
}

Binary file not shown.

View File

@ -1,44 +0,0 @@
package main
import (
"io/ioutil"
"log"
"os"
"path/filepath"
"github.com/docker/libtrust"
)
func main() {
keyFile, err := filepath.Abs("/home/derek/.docker/key.json")
if err != nil {
log.Fatalf("Error getting path: %s", err)
}
pk, err := libtrust.LoadKeyFile(keyFile)
if err != nil {
log.Fatalf("Error loading key file: %s", err)
}
input, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("Error reading stdin: %s", err)
}
sig, err := libtrust.NewJSONSignature(input)
if err != nil {
log.Fatalf("Error creating JSON signature: %s", err)
}
err = sig.Sign(pk)
if err != nil {
log.Fatalf("Error signing: %s", err)
}
//log.Printf("Private key (%s): %s", pk.KeyType(), pk.KeyID())
jws, err := sig.JWS()
if err != nil {
log.Fatalf("Error getting JWS: %s", err)
}
os.Stdout.Write(jws)
}

View File

@ -1,8 +0,0 @@
{
"crv": "P-256",
"d": "M_n9CSpMg51gEhx1vf28QcQGjxcT43sps1-F8Yzo9dQ",
"kid": "WWAC:5DVG:RVXY:APSC:CEZW:TOP4:MMHJ:FEZT:WMOJ:HVLX:HQMP:6JWK",
"kty": "EC",
"x": "fmp8Xhfx-d5lFYD-Ouxq3b75DzAnCGjY2iGGwcGRpkk",
"y": "pOXbJUfSZskgipe7GiR2HKBnZY0dT3mMLWkYhCi9jZs"
}

View File

@ -1,112 +0,0 @@
package main
import (
"fmt"
"os"
"path"
"runtime"
log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
)
func main() {
dir := path.Join(getHomeDir(), ".docker")
app := cli.NewApp()
app.Name = "trust"
app.Usage = "manage keys and grants"
app.Commands = []cli.Command{
cli.Command{
Name: "tag",
Usage: "create or update a tag",
Action: actionTag,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "commit",
Usage: "Whether to immediately commit tag",
},
},
},
cli.Command{
Name: "untag",
Usage: "delete a tag",
Action: actionUntag,
Flags: []cli.Flag{
cli.StringFlag{
Name: "ref,r",
Value: "",
Usage: "Tag or Hash reference",
},
},
},
cli.Command{
Name: "commit",
Usage: "commit target changes",
Action: actionCommit,
},
}
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "dir,d",
Value: dir,
Usage: "Directory for repository",
},
}
app.Run(os.Args)
}
func getHomeDir() string {
if runtime.GOOS == "windows" {
return os.Getenv("USERPROFILE")
}
return os.Getenv("HOME")
}
func updateRepository() {
log.Infof("Getting updated targets from repository")
log.Infof("Verifying local keys match repository")
}
func actionTag(c *cli.Context) {
hash := c.Args().First()
if len(hash) == 0 {
cli.ShowCommandHelp(c, "tag")
return
}
tag := c.Args().Get(1)
if len(tag) == 0 {
cli.ShowCommandHelp(c, "tag")
return
}
// TODO parse tag (Get last index of ':')
updateRepository()
log.Infof("Checking hash exists for name")
log.Infof("Tagging %s as %s", hash, tag)
fmt.Printf("%s+ %s %s%s\n", Green, tag, hash, Clear)
}
func actionUntag(c *cli.Context) {
tagOrHash := c.Args().First()
if len(tagOrHash) == 0 {
cli.ShowCommandHelp(c, "untag")
return
}
updateRepository()
fmt.Printf("%s+ %s%s\n", Red, tagOrHash, Clear)
}
func actionCommit(c *cli.Context) {
}
const Black = "\x1b[30;1m"
const Red = "\x1b[31;1m"
const Green = "\x1b[32;1m"
const Yellow = "\x1b[33;1m"
const Blue = "\x1b[34;1m"
const Magenta = "\x1b[35;1m"
const Cyan = "\x1b[36;1m"
const White = "\x1b[37;1m"
const Clear = "\x1b[0m"

Binary file not shown.

View File

@ -1,11 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBnzCCAUSgAwIBAgIBADAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdT
N1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6
M1hYSjAeFw0xNDA5MDUyMzA3NTRaFw0yNDA5MDkyMzA3NTRaMEYxRDBCBgNVBAMT
O0dXNEY6R1M3UDoyMktZOlNRWE06Rkk3NDpTUUJTOktSWFI6VjRUUjpJRzZROjdO
TEw6T0pJUzozWFhKMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB23slGpLr16M
TAJ3MaGVZK6QYEb/l5EZkpnrPcdX6JTGCSuDy7jpEYtsAyp6Du1jEwZuwR2nF1ni
WI39XxM1lKMjMCEwDgYDVR0PAQH/BAQDAgAEMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDSQAwRgIhAOFl3YnbPAPd7hRbh2Wpe0RrtZ0KAZGpjKk3C1ZhQEG4
AiEAh6R8OVclkFNXFbQML8X5uEL+3d7wB+osNU0OlHFaiiQ=
-----END CERTIFICATE-----

View File

@ -1,38 +0,0 @@
package main
import (
"log"
"github.com/docker/libtrust"
"github.com/docker/libtrust/trustapi/client"
)
func exerciseBaseGraph(c *client.TrustClient, name string) []byte {
statement, err := c.GetBaseGraph(name)
if err != nil {
log.Fatal(err)
}
b, err := statement.Bytes()
if err != nil {
log.Fatal(err)
}
return b
}
func main() {
pool, err := libtrust.LoadCertificatePool("./ca.pem")
if err != nil {
log.Fatal(err)
}
c := client.NewTrustClient("localhost:8092", pool)
b1 := exerciseBaseGraph(c, "empty")
b2 := exerciseBaseGraph(c, "dmcgowan")
_, err = c.GetBaseGraph("empty-bad")
if err == nil {
log.Fatalf("Did not receive error getting empty-bad")
}
log.Printf("Expected error getting empty-bad: %s", err)
log.Printf("Statements:\nempty:\n%s\n\ndmcgowan\n%s", b1, b2)
}

View File

@ -1,25 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/dmcgowan/my-app",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
}
],
"expiration": "2014-12-11T23:14:27.32116801Z",
"issuedAt": "2014-09-12T23:14:27.321168201Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "SugIISjm_U1HD2ua6BK8mocu6H5mLBVsnMNXPue-J0yuEh1PeVy5waojA0eRUCXETlO1W9vJ-GO7W0YpVSFqtw",
"protected": "eyJmb3JtYXRMZW5ndGgiOjMwNywiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTEyVDIzOjE0OjI3WiJ9"
}
]
}

View File

@ -1,19 +0,0 @@
{
"revocations": [],
"grants": [],
"expiration": "2014-12-19T23:28:35.400329125Z",
"issuedAt": "2014-09-12T23:28:35.40032963Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "Dp_mTZUSBDIkXpl1qBM4u__wGfcpD-zeyWXkVAHL9NnCWfSXAECKwyYiAJCv4dYRplotrZVzuIMt6DnQpe34_w",
"protected": "eyJmb3JtYXRMZW5ndGgiOjEzOCwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTEyVDIzOjI4OjM1WiJ9"
}
]
}

View File

@ -1,19 +0,0 @@
{
"revocations": [],
"grants": [],
"expiration": "2014-12-11T23:28:35.400329125Z",
"issuedAt": "2014-09-12T23:28:35.40032963Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "Dp_mTZUSBDIkXpl1qBM4u__wGfcpD-zeyWXkVAHL9NnCWfSXAECKwyYiAJCv4dYRplotrZVzuIMt6DnQpe34_w",
"protected": "eyJmb3JtYXRMZW5ndGgiOjEzOCwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTEyVDIzOjI4OjM1WiJ9"
}
]
}

View File

@ -1,25 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/dmcgowan",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
}
],
"expiration": "2014-12-16T01:25:16.569500374Z",
"issuedAt": "2014-09-17T01:25:16.569500504Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "RSDqbBfd2OWdEpKTxO0V6rep-cwIGiayzb8VBqVYCTcj22JrogKjmUDji4Nz965s6vw7NG9cezdaRAJB3tpflA",
"protected": "eyJmb3JtYXRMZW5ndGgiOjMwMSwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTE3VDAxOjI1OjE2WiJ9"
}
]
}

View File

@ -1,25 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/library",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
}
],
"expiration": "2014-12-29T00:08:20.565183779Z",
"issuedAt": "2014-09-30T00:08:20.565183976Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "uYMwXO869mGDkq7jrE-xfXHcY96JkcIZt_lLWidUtK4Z3-VH8UJx8j-bHQh0rD3C4Olsx7SY5dDOO_Zq60_i1w",
"protected": "eyJmb3JtYXRMZW5ndGgiOjMwMCwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTMwVDAwOjA4OjIwWiJ9"
}
]
}

View File

@ -1,25 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/dmcgowan",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
}
],
"expiration": "2014-12-16T01:25:16.569500374Z",
"issuedAt": "2014-09-17T01:25:16.569500504Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "RSDqbBfd2OWdEpKTxO0V6rep-cwIGiayzb8VBqVYCTcj22JrogKjmUDji4Nz965s6vw7NG9cezdaRAJB3tpflA",
"protected": "eyJmb3JtYXRMZW5ndGgiOjMwMSwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTE3VDAxOjI1OjE2WiJ9"
}
]
}

View File

@ -1,25 +0,0 @@
{
"revocations": [],
"grants": [
{
"subject": "/dmcgowan",
"permission": 15,
"grantee": "LYRA:YAG2:QQKS:376F:QQXY:3UNK:SXH7:K6ES:Y5AU:XUN5:ZLVY:KBYL"
}
],
"expiration": "2014-09-17T15:50:31.965636009Z",
"issuedAt": "2014-09-17T15:48:31.965636222Z",
"signatures": [
{
"header": {
"alg": "ES256",
"x5c": [
"MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcyQjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkCIDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U",
"MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdTN1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMTO09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNVTEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80eo8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8UwRaw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsCIQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg=="
]
},
"signature": "N7fvmmwZbuV70PdzlQ75EDCHapnMLWDXD3iwOxv0KpTLFF2udh7liT888GVoCSFFae187KsymOT-EO4EXTPJDQ",
"protected": "eyJmb3JtYXRMZW5ndGgiOjMwMSwiZm9ybWF0VGFpbCI6IkNuMCIsInRpbWUiOiIyMDE0LTA5LTE3VDE1OjQ4OjMxWiJ9"
}
]
}

View File

@ -1,60 +0,0 @@
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"path/filepath"
"github.com/docker/libtrust/trustapi"
"github.com/gorilla/mux"
)
var baseGraphs map[string][]byte
var baseDirectory string
func init() {
baseGraphs = map[string][]byte{}
flag.StringVar(&baseDirectory, "base", "", "Base directory for base graph files")
}
func register(r *mux.Router) {
r.Get("graphbase").HandlerFunc(handleBaseGraph)
}
func main() {
flag.Parse()
files, err := filepath.Glob(filepath.Join(baseDirectory, "*.json"))
if err != nil {
log.Fatalf("Error loading json files: %s", err)
}
for _, f := range files {
name := filepath.Base(f)
name = name[:len(name)-5]
b, err := ioutil.ReadFile(f)
if err != nil {
log.Fatalf("Error reading file: %s", err)
}
baseGraphs[name] = b
}
r := trustapi.NewRouter("localhost")
register(r)
http.ListenAndServe("localhost:8092", r)
}
func handleBaseGraph(rw http.ResponseWriter, r *http.Request) {
graphname := mux.Vars(r)["graphname"]
log.Printf("Getting graph: %s", graphname)
b, ok := baseGraphs[graphname]
if !ok {
rw.WriteHeader(404)
fmt.Fprintf(rw, "base graph not found")
return
}
rw.Header().Set("Content-Type", "application/json")
rw.Write(b)
}

View File

@ -1,101 +0,0 @@
mode: set
github.com/docker/libtrust/trustgraph/memory_graph.go:18.32,23.2 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:28.49,30.31 2 1
github.com/docker/libtrust/trustgraph/memory_graph.go:47.2,47.28 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:30.31,35.30 5 1
github.com/docker/libtrust/trustgraph/memory_graph.go:35.30,37.15 2 1
github.com/docker/libtrust/trustgraph/memory_graph.go:41.4,41.18 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:44.4,44.25 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:37.15,40.5 2 1
github.com/docker/libtrust/trustgraph/memory_graph.go:41.18,43.5 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:50.55,55.33 5 1
github.com/docker/libtrust/trustgraph/memory_graph.go:62.2,62.20 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:55.33,57.14 2 1
github.com/docker/libtrust/trustgraph/memory_graph.go:60.3,60.24 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:57.14,59.4 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:65.39,66.34 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:71.2,71.14 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:66.34,67.53 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:67.53,69.4 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:76.43,78.2 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:80.147,81.20 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:84.2,86.31 3 1
github.com/docker/libtrust/trustgraph/memory_graph.go:101.2,101.34 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:115.2,115.14 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:81.20,83.3 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:86.31,87.21 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:90.3,91.48 2 1
github.com/docker/libtrust/trustgraph/memory_graph.go:87.21,88.12 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:91.48,92.40 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:92.40,93.24 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:93.24,95.6 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:96.6,98.5 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:101.34,103.14 2 1
github.com/docker/libtrust/trustgraph/memory_graph.go:111.3,111.86 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:103.14,107.4 3 1
github.com/docker/libtrust/trustgraph/memory_graph.go:107.5,109.4 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:111.86,113.4 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:118.100,120.2 1 1
github.com/docker/libtrust/trustgraph/memory_graph.go:122.109,124.53 2 1
github.com/docker/libtrust/trustgraph/memory_graph.go:131.2,132.20 2 1
github.com/docker/libtrust/trustgraph/memory_graph.go:124.53,130.3 5 1
github.com/docker/libtrust/trustgraph/statement.go:34.56,41.2 1 1
github.com/docker/libtrust/trustgraph/statement.go:53.38,55.2 1 1
github.com/docker/libtrust/trustgraph/statement.go:60.45,62.2 1 1
github.com/docker/libtrust/trustgraph/statement.go:65.79,67.16 2 1
github.com/docker/libtrust/trustgraph/statement.go:70.2,71.16 2 1
github.com/docker/libtrust/trustgraph/statement.go:74.2,75.16 2 1
github.com/docker/libtrust/trustgraph/statement.go:78.2,80.16 3 1
github.com/docker/libtrust/trustgraph/statement.go:84.2,84.22 1 1
github.com/docker/libtrust/trustgraph/statement.go:95.2,97.24 2 1
github.com/docker/libtrust/trustgraph/statement.go:67.16,69.3 1 0
github.com/docker/libtrust/trustgraph/statement.go:71.16,73.3 1 1
github.com/docker/libtrust/trustgraph/statement.go:75.16,77.3 1 0
github.com/docker/libtrust/trustgraph/statement.go:80.16,82.3 1 0
github.com/docker/libtrust/trustgraph/statement.go:84.22,86.17 2 1
github.com/docker/libtrust/trustgraph/statement.go:86.17,88.4 1 1
github.com/docker/libtrust/trustgraph/statement.go:89.4,91.17 2 1
github.com/docker/libtrust/trustgraph/statement.go:91.17,93.4 1 1
github.com/docker/libtrust/trustgraph/statement.go:102.151,105.16 3 1
github.com/docker/libtrust/trustgraph/statement.go:108.2,109.16 2 1
github.com/docker/libtrust/trustgraph/statement.go:112.2,116.16 4 1
github.com/docker/libtrust/trustgraph/statement.go:120.2,121.16 2 1
github.com/docker/libtrust/trustgraph/statement.go:124.2,125.16 2 1
github.com/docker/libtrust/trustgraph/statement.go:129.2,129.24 1 1
github.com/docker/libtrust/trustgraph/statement.go:105.16,107.3 1 0
github.com/docker/libtrust/trustgraph/statement.go:109.16,111.3 1 0
github.com/docker/libtrust/trustgraph/statement.go:116.16,118.3 1 0
github.com/docker/libtrust/trustgraph/statement.go:121.16,123.3 1 0
github.com/docker/libtrust/trustgraph/statement.go:125.16,127.3 1 0
github.com/docker/libtrust/trustgraph/statement.go:134.34,136.2 1 1
github.com/docker/libtrust/trustgraph/statement.go:138.44,140.2 1 1
github.com/docker/libtrust/trustgraph/statement.go:142.39,144.2 1 1
github.com/docker/libtrust/trustgraph/statement.go:148.96,150.39 2 1
github.com/docker/libtrust/trustgraph/statement.go:155.2,160.35 5 1
github.com/docker/libtrust/trustgraph/statement.go:204.2,205.34 2 1
github.com/docker/libtrust/trustgraph/statement.go:209.2,209.35 1 1
github.com/docker/libtrust/trustgraph/statement.go:150.39,151.43 1 1
github.com/docker/libtrust/trustgraph/statement.go:151.43,153.4 1 1
github.com/docker/libtrust/trustgraph/statement.go:160.35,161.56 1 1
github.com/docker/libtrust/trustgraph/statement.go:164.3,164.42 1 1
github.com/docker/libtrust/trustgraph/statement.go:181.3,181.52 1 1
github.com/docker/libtrust/trustgraph/statement.go:161.56,163.4 1 1
github.com/docker/libtrust/trustgraph/statement.go:164.42,170.31 5 1
github.com/docker/libtrust/trustgraph/statement.go:170.31,172.16 2 1
github.com/docker/libtrust/trustgraph/statement.go:176.5,177.26 2 1
github.com/docker/libtrust/trustgraph/statement.go:172.16,175.6 2 1
github.com/docker/libtrust/trustgraph/statement.go:181.52,187.31 5 1
github.com/docker/libtrust/trustgraph/statement.go:194.4,194.19 1 1
github.com/docker/libtrust/trustgraph/statement.go:187.31,189.16 2 1
github.com/docker/libtrust/trustgraph/statement.go:192.5,192.26 1 1
github.com/docker/libtrust/trustgraph/statement.go:189.16,190.11 1 1
github.com/docker/libtrust/trustgraph/statement.go:194.19,195.39 1 1
github.com/docker/libtrust/trustgraph/statement.go:195.39,196.54 1 1
github.com/docker/libtrust/trustgraph/statement.go:196.54,198.7 1 1
github.com/docker/libtrust/trustgraph/statement.go:205.34,207.3 1 1
github.com/docker/libtrust/trustgraph/statement.go:213.62,215.31 2 1
github.com/docker/libtrust/trustgraph/statement.go:220.2,222.36 3 1
github.com/docker/libtrust/trustgraph/statement.go:226.2,226.27 1 1
github.com/docker/libtrust/trustgraph/statement.go:215.31,216.29 1 1
github.com/docker/libtrust/trustgraph/statement.go:216.29,218.4 1 1
github.com/docker/libtrust/trustgraph/statement.go:222.36,225.3 2 1

View File

@ -1,8 +0,0 @@
{
"crv": "P-256",
"d": "T68FInnZjHW8c8Y3y8UKDEwVEfubGX7mP8X5EOpxRw0",
"kid": "GW4F:GS7P:22KY:SQXM:FI74:SQBS:KRXR:V4TR:IG6Q:7NLL:OJIS:3XXJ",
"kty": "EC",
"x": "B23slGpLr16MTAJ3MaGVZK6QYEb_l5EZkpnrPcdX6JQ",
"y": "xgkrg8u46RGLbAMqeg7tYxMGbsEdpxdZ4liN_V8TNZQ"
}

View File

@ -1,11 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBnzCCAUSgAwIBAgIBADAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdT
N1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6
M1hYSjAeFw0xNDA5MDUyMzA3NTRaFw0yNDA5MDkyMzA3NTRaMEYxRDBCBgNVBAMT
O0dXNEY6R1M3UDoyMktZOlNRWE06Rkk3NDpTUUJTOktSWFI6VjRUUjpJRzZROjdO
TEw6T0pJUzozWFhKMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB23slGpLr16M
TAJ3MaGVZK6QYEb/l5EZkpnrPcdX6JTGCSuDy7jpEYtsAyp6Du1jEwZuwR2nF1ni
WI39XxM1lKMjMCEwDgYDVR0PAQH/BAQDAgAEMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDSQAwRgIhAOFl3YnbPAPd7hRbh2Wpe0RrtZ0KAZGpjKk3C1ZhQEG4
AiEAh6R8OVclkFNXFbQML8X5uEL+3d7wB+osNU0OlHFaiiQ=
-----END CERTIFICATE-----

View File

@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBnTCCAUSgAwIBAgIBAjAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztPUUlTOkcy
QjQ6UDdRQjpHM1pJOlRIUE46WklUTTpVRFAyOlY3WlM6VVM2SDpDVUxEOlJJWkI6
WDdQSTAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMT
O1c1MlY6QldDUTpPVVk2OklRNU46WDVYRzpNN0tKOkdYNlA6VFdNUTpaRkhKOk02
MzI6SzIzVjpYRjQ1MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEG9rANGMaOxoZ
4XzItNBpqrzZLe/hyMY/hnlXARER0rbEp5B5yl5sDYaXEI80VgpUGNvleFOVc7yN
3rclT14tm6MjMCEwDgYDVR0PAQH/BAQDAgCAMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDRwAwRAIgQhkTTERnf/+2i1hM+hHivMngiciCQgqdcxo1UeK53fkC
IDzml+Gk4oAFGGcsO3wdHqbxfjyGkNr8hxfuWoq6Wl3U
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBnjCCAUSgAwIBAgIBATAKBggqhkjOPQQDAjBGMUQwQgYDVQQDEztHVzRGOkdT
N1A6MjJLWTpTUVhNOkZJNzQ6U1FCUzpLUlhSOlY0VFI6SUc2UTo3TkxMOk9KSVM6
M1hYSjAeFw0xNDA5MTIyMzA3NTNaFw0xNDEyMTEyMzA3NTRaMEYxRDBCBgNVBAMT
O09RSVM6RzJCNDpQN1FCOkczWkk6VEhQTjpaSVRNOlVEUDI6VjdaUzpVUzZIOkNV
TEQ6UklaQjpYN1BJMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK0pEXXaql80e
o8khKBUhwg8fXwDnc+QIR3CB86JnCViEWskUrBmQZvdc8JTDtxBCvfs9nG7yZ8Uw
Raw6G9QdUqMjMCEwDgYDVR0PAQH/BAQDAgAGMA8GA1UdEwEB/wQFMAMBAf8wCgYI
KoZIzj0EAwIDSAAwRQIgCA6aCc66+d2/yz47PmvvZy+GDudWXFxD6plt2KUtuGsC
IQDykk/gYQ5MfIUlS8O+UEAwY7okfz6DxlpFGMVSO57gEg==
-----END CERTIFICATE-----

Some files were not shown because too many files have changed in this diff Show More