feat(bsr): Sync BSR keys
This commit is contained in:
1 parent
51e6e64d09
commit
444af9151c
14 files changed
+394
-9
No files matched your search
@@ -5,6 +5,7 @@ package bsr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/bsr/internal/is"
|
||||
"github.com/hashicorp/boundary/internal/bsr/kms"
|
||||
"github.com/hashicorp/boundary/internal/storage"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -20,6 +22,12 @@ const (
|
||||
channelFile = "%s.channel"
|
||||
messagesFile = "messages-%s.data"
|
||||
requestsFile = "requests-%s.data"
|
||||
|
||||
bsrPubKeyFile = "bsrKey.pub"
|
||||
wrappedBsrKeyFile = "wrappedBsrKey"
|
||||
wrappedPrivKeyFile = "wrappedPrivKey"
|
||||
pubKeyBsrSignatureFile = "pubKeyBsrSignature.sign"
|
||||
pubKeySelfSignatureFile = "pubKeySelfSignature.sign"
|
||||
)
|
||||
|
||||
// SessionMeta contains metadata about a session in a BSR.
|
||||
@@ -63,6 +71,13 @@ func NewSession(ctx context.Context, meta *SessionMeta, f storage.FS, keys *kms.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Sync keys and signatures
|
||||
err = persistBsrSessionKeys(ctx, keys, nc)
|
||||
if err != nil {
|
||||
return nil, errors.Join(err, fmt.Errorf("%s: %w", op, ErrBsrKeyPersistenceFailure))
|
||||
}
|
||||
|
||||
_, err = nc.WriteMeta(ctx, "id", meta.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -78,6 +93,51 @@ func NewSession(ctx context.Context, meta *SessionMeta, f storage.FS, keys *kms.
|
||||
}, nil
|
||||
}
|
||||
|
||||
// persistBsrSessionKeys will marshal, write, and close BSR keys locally before syncing to
|
||||
// storage. Any error while syncing the key files should result in the termination of
|
||||
// the session this recording is for.
|
||||
// The key files synced are:
|
||||
// * the BSR public key, bsrKey.pub
|
||||
// * the wrapped BSR key, wrappedBsrKey
|
||||
// * the wrapped private key, wrappedPrivKey
|
||||
// * the public key BSR signature, pubKeyBsrSignature.sign
|
||||
// * the public key self signature, pubKeySelfSignature.sign
|
||||
func persistBsrSessionKeys(ctx context.Context, keys *kms.Keys, c *container) error {
|
||||
const op = "bsr.persistBsrSessionKeys"
|
||||
switch {
|
||||
case keys.PubKey == nil:
|
||||
return fmt.Errorf("%s: missing kms pub key: %w", op, ErrInvalidParameter)
|
||||
case keys.WrappedBsrKey == nil:
|
||||
return fmt.Errorf("%s: missing kms wrapped BSR key: %w", op, ErrInvalidParameter)
|
||||
case keys.WrappedPrivKey == nil:
|
||||
return fmt.Errorf("%s: missing kms wrapped priv key: %w", op, ErrInvalidParameter)
|
||||
case keys.PubKeyBsrSignature == nil:
|
||||
return fmt.Errorf("%s: missing kms pub key BSR signature: %w", op, ErrInvalidParameter)
|
||||
case keys.PubKeySelfSignature == nil:
|
||||
return fmt.Errorf("%s: missing kms pub key self signature: %w", op, ErrInvalidParameter)
|
||||
}
|
||||
|
||||
keyFiles := map[string]proto.Message{
|
||||
bsrPubKeyFile: keys.PubKey,
|
||||
wrappedBsrKeyFile: keys.WrappedBsrKey,
|
||||
wrappedPrivKeyFile: keys.WrappedPrivKey,
|
||||
pubKeyBsrSignatureFile: keys.PubKeyBsrSignature,
|
||||
pubKeySelfSignatureFile: keys.PubKeySelfSignature,
|
||||
}
|
||||
for f, k := range keyFiles {
|
||||
b, err := proto.Marshal(k)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed to marshal data for %s: %w", op, f, err)
|
||||
}
|
||||
err = c.syncBsrKey(ctx, f, b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: failed syncing bsr key %s: %w", op, f, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewConnection creates a Connection container for a given connection id.
|
||||
func (s *Session) NewConnection(ctx context.Context, meta *ConnectionMeta) (*Connection, error) {
|
||||
const op = "bsr.(Session).NewConnection"
|
||||
|
||||
+105
-3
@@ -11,6 +11,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
@@ -52,14 +53,23 @@ func assertContainer(ctx context.Context, t *testing.T, path, state string, typ
|
||||
require.NoError(t, err, "unable to find test data file")
|
||||
checksums, ok := fs.Files["SHA256SUM"]
|
||||
require.True(t, ok, "container is missing checksums file")
|
||||
assert.Equal(t, string(wantChecksums), checksums.Buf.String())
|
||||
checksumSlice := strings.Split(string(wantChecksums), "\n")
|
||||
var wChecksumsRegex []*regexp.Regexp
|
||||
for _, c := range checksumSlice {
|
||||
r, err := regexp.Compile(c)
|
||||
require.NoError(t, err)
|
||||
wChecksumsRegex = append(wChecksumsRegex, r)
|
||||
}
|
||||
for _, cr := range wChecksumsRegex {
|
||||
assert.True(t, cr.MatchString(checksums.Buf.String()))
|
||||
}
|
||||
|
||||
// SHA256SUM.sig signature file
|
||||
sig, ok := fs.Files["SHA256SUM.sig"]
|
||||
require.True(t, ok, "container is missing sig file")
|
||||
switch state {
|
||||
case "closed":
|
||||
want, err := keys.SignWithPrivKey(ctx, wantChecksums)
|
||||
want, err := keys.SignWithPrivKey(ctx, checksums.Buf.Bytes())
|
||||
require.NoError(t, err)
|
||||
|
||||
got := &wrapping.SigInfo{}
|
||||
@@ -82,7 +92,39 @@ func assertContainer(ctx context.Context, t *testing.T, path, state string, typ
|
||||
require.NoError(t, err, "unable to find test data file")
|
||||
journal, ok := fs.Files[".journal"]
|
||||
require.True(t, ok, "container is missing journal file")
|
||||
assert.Equal(t, string(wantJournal), journal.Buf.String())
|
||||
journalSlice := strings.Split(string(wantJournal), "\n")
|
||||
var wJournalRegex []*regexp.Regexp
|
||||
for _, c := range journalSlice {
|
||||
r, err := regexp.Compile(c)
|
||||
require.NoError(t, err)
|
||||
wJournalRegex = append(wJournalRegex, r)
|
||||
}
|
||||
for _, cr := range wJournalRegex {
|
||||
assert.True(t, cr.MatchString(journal.Buf.String()))
|
||||
}
|
||||
|
||||
if typ == "session" {
|
||||
// BSR keys, if this is a session container
|
||||
bsrPub, ok := fs.Files["bsrKey.pub"]
|
||||
require.True(t, ok, "container is missing bsrPub file")
|
||||
assert.NotEmpty(t, bsrPub.Buf.String())
|
||||
|
||||
wrappedBsrKey, ok := fs.Files["wrappedBsrKey"]
|
||||
require.True(t, ok, "container is missing wrappedBsrKey file")
|
||||
assert.NotEmpty(t, wrappedBsrKey.Buf.String())
|
||||
|
||||
wrappedPrivKey, ok := fs.Files["wrappedPrivKey"]
|
||||
require.True(t, ok, "container is missing wrappedPrivKey file")
|
||||
assert.NotEmpty(t, wrappedPrivKey.Buf.String())
|
||||
|
||||
pubKeyBsrSignature, ok := fs.Files["pubKeyBsrSignature.sign"]
|
||||
require.True(t, ok, "container is missing pubKeyBsrSignature.sign file")
|
||||
assert.NotEmpty(t, pubKeyBsrSignature.Buf.String())
|
||||
|
||||
pubKeySelfSignature, ok := fs.Files["pubKeySelfSignature.sign"]
|
||||
require.True(t, ok, "container is missing pubKeySelfSignature.sign file")
|
||||
assert.NotEmpty(t, pubKeySelfSignature.Buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
type connection struct {
|
||||
@@ -362,6 +404,66 @@ func TestNewSessionErrors(t *testing.T) {
|
||||
nil,
|
||||
errors.New("bsr.NewSession: missing kms keys: invalid parameter"),
|
||||
},
|
||||
{
|
||||
"missing-bsr-signature",
|
||||
&bsr.SessionMeta{Id: "session"},
|
||||
&fstest.MemFS{},
|
||||
&kms.Keys{
|
||||
PubKey: keys.PubKey,
|
||||
WrappedBsrKey: keys.WrappedBsrKey,
|
||||
WrappedPrivKey: keys.WrappedPrivKey,
|
||||
PubKeySelfSignature: keys.PubKeySelfSignature,
|
||||
},
|
||||
errors.New("bsr.persistBsrSessionKeys: missing kms pub key BSR signature: invalid parameter\nbsr.NewSession: could not persist BSR keys"),
|
||||
},
|
||||
{
|
||||
"missing-pub-signature",
|
||||
&bsr.SessionMeta{Id: "session"},
|
||||
&fstest.MemFS{},
|
||||
&kms.Keys{
|
||||
PubKey: keys.PubKey,
|
||||
WrappedBsrKey: keys.WrappedBsrKey,
|
||||
WrappedPrivKey: keys.WrappedPrivKey,
|
||||
PubKeyBsrSignature: keys.PubKeyBsrSignature,
|
||||
},
|
||||
errors.New("bsr.persistBsrSessionKeys: missing kms pub key self signature: invalid parameter\nbsr.NewSession: could not persist BSR keys"),
|
||||
},
|
||||
{
|
||||
"missing-pub-key",
|
||||
&bsr.SessionMeta{Id: "session"},
|
||||
&fstest.MemFS{},
|
||||
&kms.Keys{
|
||||
WrappedBsrKey: keys.WrappedBsrKey,
|
||||
WrappedPrivKey: keys.WrappedPrivKey,
|
||||
PubKeySelfSignature: keys.PubKeySelfSignature,
|
||||
PubKeyBsrSignature: keys.PubKeyBsrSignature,
|
||||
},
|
||||
errors.New("bsr.persistBsrSessionKeys: missing kms pub key: invalid parameter\nbsr.NewSession: could not persist BSR keys"),
|
||||
},
|
||||
{
|
||||
"missing-wrapped-bsr-key",
|
||||
&bsr.SessionMeta{Id: "session"},
|
||||
&fstest.MemFS{},
|
||||
&kms.Keys{
|
||||
PubKey: keys.PubKey,
|
||||
WrappedPrivKey: keys.WrappedPrivKey,
|
||||
PubKeySelfSignature: keys.PubKeySelfSignature,
|
||||
PubKeyBsrSignature: keys.PubKeyBsrSignature,
|
||||
},
|
||||
errors.New("bsr.persistBsrSessionKeys: missing kms wrapped BSR key: invalid parameter\nbsr.NewSession: could not persist BSR keys"),
|
||||
},
|
||||
{
|
||||
"missing-wrapped-priv-key",
|
||||
&bsr.SessionMeta{Id: "session"},
|
||||
&fstest.MemFS{},
|
||||
&kms.Keys{
|
||||
PubKey: keys.PubKey,
|
||||
WrappedBsrKey: keys.WrappedBsrKey,
|
||||
PubKeySelfSignature: keys.PubKeySelfSignature,
|
||||
PubKeyBsrSignature: keys.PubKeyBsrSignature,
|
||||
},
|
||||
errors.New("bsr.persistBsrSessionKeys: missing kms wrapped priv key: invalid parameter\nbsr.NewSession: could not persist BSR keys"),
|
||||
},
|
||||
{
|
||||
"fs-new-error",
|
||||
&bsr.SessionMeta{Id: "session"},
|
||||
|
||||
@@ -105,21 +105,74 @@ func newContainer(ctx context.Context, t containerType, c storage.Container, key
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// Create creates a new file in the container for writing.
|
||||
func (c *container) create(ctx context.Context, s string) (storage.File, error) {
|
||||
c.journal.Record("CREATING", s)
|
||||
f, err := c.container.Create(ctx, s)
|
||||
// create creates a new file in the container for writing.
|
||||
func (c *container) create(ctx context.Context, s string, options ...storage.Option) (storage.File, error) {
|
||||
const op = "bsr.(container).create"
|
||||
|
||||
err := c.journal.Record("CREATING", s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
var f storage.File
|
||||
switch len(options) {
|
||||
case 0:
|
||||
f, err = c.container.Create(ctx, s)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
default:
|
||||
f, err = c.container.OpenFile(ctx, s, options...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
}
|
||||
|
||||
jf, err := journal.NewFile(ctx, f, c.journal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
defer c.journal.Record("CREATED", s)
|
||||
return jf, nil
|
||||
}
|
||||
|
||||
// syncBsrKey will take the marshalled bytes of a key, write its contents to a local file,
|
||||
// and then close it. The key file is created using the synchronous storage option, so
|
||||
// close will block until the file is synced to remote storage
|
||||
func (c *container) syncBsrKey(ctx context.Context, s string, data []byte) error {
|
||||
const op = "bsr.(container).syncBsrKey"
|
||||
switch {
|
||||
case len(s) == 0:
|
||||
return fmt.Errorf("%s: missing file name %w", op, ErrInvalidParameter)
|
||||
case data == nil:
|
||||
return fmt.Errorf("%s: missing data payload %w", op, ErrInvalidParameter)
|
||||
}
|
||||
|
||||
jf, err := c.create(ctx, s, storage.WithCreateFile(),
|
||||
storage.WithFileAccessMode(storage.WriteOnly),
|
||||
storage.WithCloseSyncMode(storage.Synchronous))
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
cf, err := checksum.NewFile(ctx, jf, c.checksums)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
_, err = cf.Write(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
err = cf.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", op, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeMetaString writes a string to the containers meta file.
|
||||
func (c *container) writeMetaString(_ context.Context, s string) (int, error) {
|
||||
return c.meta.WriteString(s)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package bsr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/bsr/internal/fstest"
|
||||
"github.com/hashicorp/boundary/internal/bsr/kms"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSyncBsrKeys(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
keys, err := kms.CreateKeys(ctx, kms.TestWrapper(t), "session")
|
||||
require.NoError(t, err)
|
||||
f := &fstest.MemFS{}
|
||||
|
||||
fc, err := f.New(ctx, fmt.Sprintf(bsrFile, "session-id"))
|
||||
require.NoError(t, err)
|
||||
|
||||
c, err := newContainer(ctx, sessionContainer, fc, keys)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, c)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
fname string
|
||||
data []byte
|
||||
expErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "no filename",
|
||||
data: []byte("got no name"),
|
||||
expErr: true,
|
||||
expErrMsg: "bsr.(container).syncBsrKey: missing file name invalid parameter",
|
||||
},
|
||||
{
|
||||
name: "no data",
|
||||
fname: "i have a name",
|
||||
expErr: true,
|
||||
expErrMsg: "bsr.(container).syncBsrKey: missing data payload invalid parameter",
|
||||
},
|
||||
{
|
||||
name: "success",
|
||||
fname: "i have a name",
|
||||
data: []byte("payload coming thru"),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := c.syncBsrKey(ctx, tc.fname, tc.data)
|
||||
|
||||
if tc.expErr {
|
||||
require.EqualError(t, err, tc.expErrMsg)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -16,3 +16,6 @@ var ErrInvalidParameter = errors.New("invalid parameter")
|
||||
// ErrNotSupported represents an operation that is not supported for a
|
||||
// particular protocol.
|
||||
var ErrNotSupported = errors.New("not supported by protocol")
|
||||
|
||||
// ErrBsrKeyPersistenceFailure indicates a failure in persisting BSR encryption keys
|
||||
var ErrBsrKeyPersistenceFailure = errors.New("could not persist BSR keys")
|
||||
@@ -90,6 +90,7 @@ func (f *File) Close() error {
|
||||
|
||||
var closeErrors *multierror.Error
|
||||
|
||||
// Call stat before closure; calling it after results in an err
|
||||
s, err := f.Stat()
|
||||
if err != nil {
|
||||
closeErrors = multierror.Append(closeErrors, fmt.Errorf("%s: %w", op, err))
|
||||
|
||||
@@ -6,6 +6,26 @@ CREATING session.meta
|
||||
CREATED session.meta
|
||||
CREATING session.summary
|
||||
CREATED session.summary
|
||||
CREATING bsrKey.pub
|
||||
CREATED bsrKey.pub
|
||||
CLOSING bsrKey.pub
|
||||
CLOSED bsrKey.pub
|
||||
CREATING wrappedBsrKey
|
||||
CREATED wrappedBsrKey
|
||||
CLOSING wrappedBsrKey
|
||||
CLOSED wrappedBsrKey
|
||||
CREATING wrappedPrivKey
|
||||
CREATED wrappedPrivKey
|
||||
CLOSING wrappedPrivKey
|
||||
CLOSED wrappedPrivKey
|
||||
CREATING pubKeyBsrSignature.sign
|
||||
CREATED pubKeyBsrSignature.sign
|
||||
CLOSING pubKeyBsrSignature.sign
|
||||
CLOSED pubKeyBsrSignature.sign
|
||||
CREATING pubKeySelfSignature.sign
|
||||
CREATED pubKeySelfSignature.sign
|
||||
CLOSING pubKeySelfSignature.sign
|
||||
CLOSED pubKeySelfSignature.sign
|
||||
CLOSING session.meta
|
||||
CLOSED session.meta
|
||||
CLOSING session.summary
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
.* bsrKey.pub
|
||||
.* wrappedBsrKey
|
||||
.* wrappedPrivKey
|
||||
.* pubKeyBsrSignature.sign
|
||||
.* pubKeySelfSignature.sign
|
||||
a7b7dc4a1c6032980f84d22afb71d59ccdf498db37f2e855a83d8854bdc297db session.meta
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 session.summary
|
||||
@@ -6,3 +6,23 @@ CREATING session.meta
|
||||
CREATED session.meta
|
||||
CREATING session.summary
|
||||
CREATED session.summary
|
||||
CREATING bsrKey.pub
|
||||
CREATED bsrKey.pub
|
||||
CLOSING bsrKey.pub
|
||||
CLOSED bsrKey.pub
|
||||
CREATING wrappedBsrKey
|
||||
CREATED wrappedBsrKey
|
||||
CLOSING wrappedBsrKey
|
||||
CLOSED wrappedBsrKey
|
||||
CREATING wrappedPrivKey
|
||||
CREATED wrappedPrivKey
|
||||
CLOSING wrappedPrivKey
|
||||
CLOSED wrappedPrivKey
|
||||
CREATING pubKeyBsrSignature.sign
|
||||
CREATED pubKeyBsrSignature.sign
|
||||
CLOSING pubKeyBsrSignature.sign
|
||||
CLOSED pubKeyBsrSignature.sign
|
||||
CREATING pubKeySelfSignature.sign
|
||||
CREATED pubKeySelfSignature.sign
|
||||
CLOSING pubKeySelfSignature.sign
|
||||
CLOSED pubKeySelfSignature.sign
|
||||
@@ -0,0 +1,5 @@
|
||||
.* bsrKey.pub
|
||||
.* wrappedBsrKey
|
||||
.* wrappedPrivKey
|
||||
.* pubKeyBsrSignature.sign
|
||||
.* pubKeySelfSignature.sign
|
||||
@@ -6,6 +6,26 @@ CREATING session.meta
|
||||
CREATED session.meta
|
||||
CREATING session.summary
|
||||
CREATED session.summary
|
||||
CREATING bsrKey.pub
|
||||
CREATED bsrKey.pub
|
||||
CLOSING bsrKey.pub
|
||||
CLOSED bsrKey.pub
|
||||
CREATING wrappedBsrKey
|
||||
CREATED wrappedBsrKey
|
||||
CLOSING wrappedBsrKey
|
||||
CLOSED wrappedBsrKey
|
||||
CREATING wrappedPrivKey
|
||||
CREATED wrappedPrivKey
|
||||
CLOSING wrappedPrivKey
|
||||
CLOSED wrappedPrivKey
|
||||
CREATING pubKeyBsrSignature.sign
|
||||
CREATED pubKeyBsrSignature.sign
|
||||
CLOSING pubKeyBsrSignature.sign
|
||||
CLOSED pubKeyBsrSignature.sign
|
||||
CREATING pubKeySelfSignature.sign
|
||||
CREATED pubKeySelfSignature.sign
|
||||
CLOSING pubKeySelfSignature.sign
|
||||
CLOSED pubKeySelfSignature.sign
|
||||
CLOSING session.meta
|
||||
CLOSED session.meta
|
||||
CLOSING session.summary
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
.* bsrKey.pub
|
||||
.* wrappedBsrKey
|
||||
.* wrappedPrivKey
|
||||
.* pubKeyBsrSignature.sign
|
||||
.* pubKeySelfSignature.sign
|
||||
a7b7dc4a1c6032980f84d22afb71d59ccdf498db37f2e855a83d8854bdc297db session.meta
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 session.summary
|
||||
@@ -6,3 +6,23 @@ CREATING session.meta
|
||||
CREATED session.meta
|
||||
CREATING session.summary
|
||||
CREATED session.summary
|
||||
CREATING bsrKey.pub
|
||||
CREATED bsrKey.pub
|
||||
CLOSING bsrKey.pub
|
||||
CLOSED bsrKey.pub
|
||||
CREATING wrappedBsrKey
|
||||
CREATED wrappedBsrKey
|
||||
CLOSING wrappedBsrKey
|
||||
CLOSED wrappedBsrKey
|
||||
CREATING wrappedPrivKey
|
||||
CREATED wrappedPrivKey
|
||||
CLOSING wrappedPrivKey
|
||||
CLOSED wrappedPrivKey
|
||||
CREATING pubKeyBsrSignature.sign
|
||||
CREATED pubKeyBsrSignature.sign
|
||||
CLOSING pubKeyBsrSignature.sign
|
||||
CLOSED pubKeyBsrSignature.sign
|
||||
CREATING pubKeySelfSignature.sign
|
||||
CREATED pubKeySelfSignature.sign
|
||||
CLOSING pubKeySelfSignature.sign
|
||||
CLOSED pubKeySelfSignature.sign
|
||||
@@ -0,0 +1,5 @@
|
||||
.* bsrKey.pub
|
||||
.* wrappedBsrKey
|
||||
.* wrappedPrivKey
|
||||
.* pubKeyBsrSignature.sign
|
||||
.* pubKeySelfSignature.sign
|
||||
Reference in new issue
Block a user