Skip to content

Commit ea9ef8e

Browse files
author
Gregory Hill
committed
force symmetric secrets
Signed-off-by: Gregory Hill <[email protected]>
1 parent 20d08da commit ea9ef8e

File tree

12 files changed

+72
-2292
lines changed

12 files changed

+72
-2292
lines changed

Gopkg.lock

Lines changed: 2 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/secrets/secrets.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package secrets
22

33
import (
4+
"fmt"
45
"io/ioutil"
56
)
67

@@ -31,7 +32,7 @@ type Manager struct {
3132
OpenPGP *OpenPGPSecret
3233
}
3334

34-
type SymmetricProvider func(secretID string) []byte
35+
type SymmetricProvider func(secretID string) ([]byte, error)
3536

3637
// NoopSecretManager is an empty secret manager
3738
var NoopSecretManager = Manager{
@@ -40,8 +41,8 @@ var NoopSecretManager = Manager{
4041
}
4142

4243
// NoopSymmetricProvider returns an empty provider
43-
func NoopSymmetricProvider(_ string) []byte {
44-
return nil
44+
func NoopSymmetricProvider(_ string) ([]byte, error) {
45+
return nil, fmt.Errorf("no secrets provided to hoard")
4546
}
4647

4748
// ProviderFromConfig creates a secret reader from a set of symmetric secrets
@@ -53,8 +54,14 @@ func ProviderFromConfig(conf *SecretsConfig) SymmetricProvider {
5354
for _, s := range conf.Symmetric {
5455
secs[s.PublicID] = []byte(s.Passphrase)
5556
}
56-
return func(id string) []byte {
57-
return secs[id]
57+
return func(id string) ([]byte, error) {
58+
if id == "" {
59+
return nil, fmt.Errorf("empty secret ID passed to provider")
60+
}
61+
if val, ok := secs[id]; ok {
62+
return val, nil
63+
}
64+
return nil, fmt.Errorf("could not find symmetric secret with ID '%s'", id)
5865
}
5966
}
6067

grant/grant.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ func Seal(secret secrets.Manager, ref *reference.Ref, spec *Spec) (*Grant, error
1515
case *PlaintextSpec:
1616
grt.EncryptedReference = PlaintextGrant(ref)
1717
case *SymmetricSpec:
18-
encRef, err := SymmetricGrant(ref, secret.Provider(s.PublicID))
18+
secret, err := secret.Provider(s.PublicID)
19+
if err != nil {
20+
return nil, err
21+
}
22+
encRef, err := SymmetricGrant(ref, secret)
1923
if err != nil {
2024
return nil, err
2125
}
@@ -38,7 +42,11 @@ func Unseal(secret secrets.Manager, grt *Grant) (*reference.Ref, error) {
3842
case *PlaintextSpec:
3943
return PlaintextReference(grt.EncryptedReference), nil
4044
case *SymmetricSpec:
41-
return SymmetricReference(grt.EncryptedReference, secret.Provider(s.PublicID))
45+
secret, err := secret.Provider(s.PublicID)
46+
if err != nil {
47+
return nil, err
48+
}
49+
return SymmetricReference(grt.EncryptedReference, secret)
4250
case *OpenPGPSpec:
4351
return OpenPGPReference(grt.EncryptedReference, secret.OpenPGP)
4452
}

grant/grant_test.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ func TestGrants(t *testing.T) {
1818

1919
testPGP := secrets.OpenPGPSecret{
2020
PrivateID: "10449759736975846181",
21-
Data: []byte(keyPrivate),
21+
Data: keyPrivate,
2222
}
2323

2424
testSecrets := secrets.Manager{
25-
Provider: func(_ string) []byte {
26-
return nil
25+
Provider: func(_ string) ([]byte, error) {
26+
return nil, nil
2727
},
2828
OpenPGP: &testPGP,
2929
}
@@ -36,18 +36,29 @@ func TestGrants(t *testing.T) {
3636
plaintextRef, err := Unseal(testSecrets, plaintextGrant)
3737
assert.Equal(t, testRef, plaintextRef)
3838

39+
// SymmetricGrant with empty provider
3940
symmetricSpec := Spec{Symmetric: &SymmetricSpec{PublicID: "test"}}
4041
symmetricGrant, err := Seal(testSecrets, testRef, &symmetricSpec)
42+
assert.Error(t, err)
43+
assert.Nil(t, symmetricGrant)
44+
45+
// SymmetricGrant with correct provider
46+
testSecrets.Provider = func(_ string) ([]byte, error) {
47+
return []byte("sssshhhh"), nil
48+
}
49+
symmetricGrant, err = Seal(testSecrets, testRef, &symmetricSpec)
50+
assert.NotNil(t, symmetricGrant)
4151
assert.NoError(t, err)
4252
symmetricRef, err := Unseal(testSecrets, symmetricGrant)
4353
assert.Equal(t, testRef, symmetricRef)
4454
assert.NoError(t, err)
4555

46-
asymmetricSpec := Spec{OpenPGP: &OpenPGPSpec{}}
47-
asymmetricGrant, err := Seal(testSecrets, testRef, &asymmetricSpec)
56+
// OpenPGPGrant encrypt / decrypt with local keypair
57+
openpgpSpec := Spec{OpenPGP: &OpenPGPSpec{}}
58+
openpgpGrant, err := Seal(testSecrets, testRef, &openpgpSpec)
4859
assert.NoError(t, err)
49-
asymmetricRef, err := Unseal(testSecrets, asymmetricGrant)
50-
assert.Equal(t, testRef, asymmetricRef)
60+
openpgpRef, err := Unseal(testSecrets, openpgpGrant)
61+
assert.Equal(t, testRef, openpgpRef)
5162
assert.NoError(t, err)
5263
}
5364

grant/openpgp.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import (
1616
)
1717

1818
// OpenPGPGrant encrypts and signs a given reference
19-
func OpenPGPGrant(ref *reference.Ref, public string, private *secrets.OpenPGPSecret) ([]byte, error) {
20-
if private == nil {
19+
func OpenPGPGrant(ref *reference.Ref, public string, keyring *secrets.OpenPGPSecret) ([]byte, error) {
20+
if keyring == nil {
2121
return nil, fmt.Errorf("cannot encrypt because no private key was provided")
2222
}
2323

@@ -35,24 +35,24 @@ func OpenPGPGrant(ref *reference.Ref, public string, private *secrets.OpenPGPSec
3535
}
3636
} else {
3737
// default to configured keyring
38-
if to, err = openpgp.ReadArmoredKeyRing(bytes.NewBuffer(private.Data)); err != nil {
38+
if to, err = openpgp.ReadArmoredKeyRing(bytes.NewBuffer(keyring.Data)); err != nil {
3939
return nil, fmt.Errorf("could not read private keyring: %s", err)
4040
}
4141
}
4242

4343
// read configured keyring
44-
keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBuffer(private.Data))
44+
keys, err := openpgp.ReadArmoredKeyRing(bytes.NewBuffer(keyring.Data))
4545
if err != nil {
4646
return nil, err
4747
}
4848

49-
id, err := strconv.ParseUint(private.PrivateID, 10, 64)
49+
id, err := strconv.ParseUint(keyring.PrivateID, 10, 64)
5050
if err != nil {
5151
return nil, err
5252
}
5353

5454
// we can only sign with one key
55-
from := keyring.KeysById(id)[0].Entity
55+
from := keys.KeysById(id)[0].Entity
5656
if from == nil {
5757
return nil, fmt.Errorf("signing identity not found")
5858
}
@@ -73,13 +73,13 @@ func OpenPGPGrant(ref *reference.Ref, public string, private *secrets.OpenPGPSec
7373
}
7474

7575
// OpenPGPReference decrypts a given grant
76-
func OpenPGPReference(grant []byte, private *secrets.OpenPGPSecret) (*reference.Ref, error) {
77-
if private == nil {
76+
func OpenPGPReference(grant []byte, keyring *secrets.OpenPGPSecret) (*reference.Ref, error) {
77+
if keyring == nil {
7878
return nil, fmt.Errorf("cannot decrypt because no private key was provided")
7979
}
8080

8181
// read local keyring
82-
to, err := openpgp.ReadArmoredKeyRing(bytes.NewBuffer(private.Data))
82+
to, err := openpgp.ReadArmoredKeyRing(bytes.NewBuffer(keyring.Data))
8383
block, err := armor.Decode(bytes.NewBuffer(grant))
8484
if err != nil {
8585
return nil, err

grant/symmetric.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ import (
1111

1212
// We bump it a little from the 100ms for interactive logins rule: https://blog.filippo.io/the-scrypt-parameters/
1313
const scryptSecurityWorkExponent = 16
14+
const minSecretSize = 8
1415

1516
// SymmetricGrant encrypts the given reference based on a secret read from the provider store
1617
func SymmetricGrant(ref *reference.Ref, secret []byte) ([]byte, error) {
18+
if len(secret) < minSecretSize {
19+
return nil, fmt.Errorf("SymmetricGrant cannot encrypt with a secret of size < %d", minSecretSize)
20+
}
1721
// Generate scrypt salt
1822
salt := make([]byte, encryption.NonceSize)
1923
_, err := rand.Read(salt)

grant/symmetric_test.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,30 @@ package grant
33
import (
44
"testing"
55

6+
"github.com/stretchr/testify/assert"
7+
68
"github.com/monax/hoard/reference"
7-
"github.com/stretchr/testify/require"
89
)
910

1011
func TestSymmetricGrant(t *testing.T) {
11-
secret := []byte("sshh")
1212
ref := &reference.Ref{
1313
Address: []byte("adddressss"),
1414
SecretKey: []byte("other secret"),
1515
}
16-
grt, err := SymmetricGrant(ref, secret)
17-
require.NoError(t, err)
16+
grt, err := SymmetricGrant(ref, nil)
17+
assert.Error(t, err)
18+
assert.Nil(t, grt)
19+
20+
secret := []byte("sshh")
21+
grt, err = SymmetricGrant(ref, secret)
22+
assert.Errorf(t, err, "SymmetricGrant cannot encrypt with a secret of size < %d", minSecretSize)
23+
assert.Nil(t, grt)
24+
25+
secret = []byte("sssshhhh")
26+
grt, err = SymmetricGrant(ref, secret)
27+
assert.NoError(t, err)
28+
assert.NotNil(t, grt)
1829
refOut, err := SymmetricReference(grt, secret)
19-
require.NoError(t, err)
20-
require.Equal(t, ref, refOut)
30+
assert.NoError(t, err)
31+
assert.Equal(t, ref, refOut)
2132
}

vendor/github.com/stretchr/testify/require/doc.go

Lines changed: 0 additions & 28 deletions
This file was deleted.

vendor/github.com/stretchr/testify/require/forward_requirements.go

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)