Add sym key
This commit is contained in:
parent
3a07939b01
commit
7c4abdbb8c
@ -1,10 +1,11 @@
|
|||||||
package aclrecordproto
|
package aclrecordproto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/anytypeio/any-sync/util/crypto"
|
||||||
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AclReadKeyDerive(signKey []byte, encKey []byte) (*symmetric.Key, error) {
|
func AclReadKeyDerive(signKey []byte, encKey []byte) (*crypto.AESKey, error) {
|
||||||
concBuf := make([]byte, 0, len(signKey)+len(encKey))
|
concBuf := make([]byte, 0, len(signKey)+len(encKey))
|
||||||
concBuf = append(concBuf, signKey...)
|
concBuf = append(concBuf, signKey...)
|
||||||
concBuf = append(concBuf, encKey...)
|
concBuf = append(concBuf, encKey...)
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import (
|
|||||||
"github.com/anytypeio/any-sync/commonspace/object/keychain"
|
"github.com/anytypeio/any-sync/commonspace/object/keychain"
|
||||||
"github.com/anytypeio/any-sync/util/cidutil"
|
"github.com/anytypeio/any-sync/util/cidutil"
|
||||||
"github.com/anytypeio/any-sync/util/crypto"
|
"github.com/anytypeio/any-sync/util/crypto"
|
||||||
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -37,7 +36,7 @@ func (a *aclRecordBuilder) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyByt
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
encSymKey, err := symmetric.FromBytes(encSymKeyBytes)
|
encSymKey, err := crypto.UnmarshallAESKey(encSymKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/anytypeio/any-sync/util/keys"
|
"github.com/anytypeio/any-sync/util/keys"
|
||||||
"github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey"
|
"github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey"
|
||||||
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
||||||
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@ -44,7 +43,7 @@ type UserPermissionPair struct {
|
|||||||
type AclState struct {
|
type AclState struct {
|
||||||
id string
|
id string
|
||||||
currentReadKeyHash uint64
|
currentReadKeyHash uint64
|
||||||
userReadKeys map[uint64]*symmetric.Key
|
userReadKeys map[uint64]*crypto.AESKey
|
||||||
userStates map[string]*aclrecordproto.AclUserState
|
userStates map[string]*aclrecordproto.AclUserState
|
||||||
userInvites map[string]*aclrecordproto.AclUserInvite
|
userInvites map[string]*aclrecordproto.AclUserInvite
|
||||||
encryptionKey encryptionkey.PrivKey
|
encryptionKey encryptionkey.PrivKey
|
||||||
@ -71,7 +70,7 @@ func newAclStateWithKeys(
|
|||||||
identity: string(identity),
|
identity: string(identity),
|
||||||
signingKey: signingKey,
|
signingKey: signingKey,
|
||||||
encryptionKey: encryptionKey,
|
encryptionKey: encryptionKey,
|
||||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
userReadKeys: make(map[uint64]*crypto.AESKey),
|
||||||
userStates: make(map[string]*aclrecordproto.AclUserState),
|
userStates: make(map[string]*aclrecordproto.AclUserState),
|
||||||
userInvites: make(map[string]*aclrecordproto.AclUserInvite),
|
userInvites: make(map[string]*aclrecordproto.AclUserInvite),
|
||||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
@ -81,7 +80,7 @@ func newAclStateWithKeys(
|
|||||||
func newAclState(id string) *AclState {
|
func newAclState(id string) *AclState {
|
||||||
return &AclState{
|
return &AclState{
|
||||||
id: id,
|
id: id,
|
||||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
userReadKeys: make(map[uint64]*crypto.AESKey),
|
||||||
userStates: make(map[string]*aclrecordproto.AclUserState),
|
userStates: make(map[string]*aclrecordproto.AclUserState),
|
||||||
userInvites: make(map[string]*aclrecordproto.AclUserInvite),
|
userInvites: make(map[string]*aclrecordproto.AclUserInvite),
|
||||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
@ -92,7 +91,7 @@ func (st *AclState) CurrentReadKeyHash() uint64 {
|
|||||||
return st.currentReadKeyHash
|
return st.currentReadKeyHash
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *AclState) CurrentReadKey() (*symmetric.Key, error) {
|
func (st *AclState) CurrentReadKey() (*crypto.AESKey, error) {
|
||||||
key, exists := st.userReadKeys[st.currentReadKeyHash]
|
key, exists := st.userReadKeys[st.currentReadKeyHash]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, ErrNoReadKey
|
return nil, ErrNoReadKey
|
||||||
@ -100,7 +99,7 @@ func (st *AclState) CurrentReadKey() (*symmetric.Key, error) {
|
|||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *AclState) UserReadKeys() map[uint64]*symmetric.Key {
|
func (st *AclState) UserReadKeys() map[uint64]*crypto.AESKey {
|
||||||
return st.userReadKeys
|
return st.userReadKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +194,7 @@ func (st *AclState) applyRoot(root *aclrecordproto.AclRoot) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto.AclRoot) (err error) {
|
func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto.AclRoot) (err error) {
|
||||||
var readKey *symmetric.Key
|
var readKey *crypto.AESKey
|
||||||
if len(root.GetDerivationScheme()) != 0 {
|
if len(root.GetDerivationScheme()) != 0 {
|
||||||
var encPrivKey []byte
|
var encPrivKey []byte
|
||||||
encPrivKey, err = st.encryptionKey.Raw()
|
encPrivKey, err = st.encryptionKey.Raw()
|
||||||
@ -401,13 +400,13 @@ func (st *AclState) applyUserRemove(ch *aclrecordproto.AclUserRemove) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *AclState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, error) {
|
func (st *AclState) decryptReadKeyAndHash(msg []byte) (*crypto.AESKey, uint64, error) {
|
||||||
decrypted, err := st.encryptionKey.Decrypt(msg)
|
decrypted, err := st.encryptionKey.Decrypt(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, ErrFailedToDecrypt
|
return nil, 0, ErrFailedToDecrypt
|
||||||
}
|
}
|
||||||
|
|
||||||
key, err := symmetric.FromBytes(decrypted)
|
key, err := crypto.UnmarshallAESKey(decrypted)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, ErrFailedToDecrypt
|
return nil, 0, ErrFailedToDecrypt
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,14 +6,13 @@ import (
|
|||||||
"github.com/anytypeio/any-sync/util/keys"
|
"github.com/anytypeio/any-sync/util/keys"
|
||||||
"github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey"
|
"github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey"
|
||||||
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
||||||
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SymKey struct {
|
type SymKey struct {
|
||||||
Hash uint64
|
Hash uint64
|
||||||
Key *symmetric.Key
|
Key *crypto.AESKey
|
||||||
}
|
}
|
||||||
|
|
||||||
type YAMLKeychain struct {
|
type YAMLKeychain struct {
|
||||||
@ -111,11 +110,11 @@ func (k *YAMLKeychain) AddReadKey(key *Key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rkey *symmetric.Key
|
rkey *crypto.AESKey
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if key.Value == "generated" {
|
if key.Value == "generated" {
|
||||||
rkey, err = symmetric.NewRandom()
|
rkey, err = crypto.NewRandomAES()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("should be able to generate symmetric key")
|
panic("should be able to generate symmetric key")
|
||||||
}
|
}
|
||||||
@ -127,7 +126,7 @@ func (k *YAMLKeychain) AddReadKey(key *Key) {
|
|||||||
panic("should be able to derive symmetric key")
|
panic("should be able to derive symmetric key")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rkey, err = symmetric.FromString(key.Value)
|
rkey, err = crypto.UnmarshallAESKeyString(key.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("should be able to parse symmetric key")
|
panic("should be able to parse symmetric key")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,9 +7,9 @@ import (
|
|||||||
"github.com/anytypeio/any-sync/commonspace/object/acl/liststorage"
|
"github.com/anytypeio/any-sync/commonspace/object/acl/liststorage"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/acl/testutils/yamltests"
|
"github.com/anytypeio/any-sync/commonspace/object/acl/testutils/yamltests"
|
||||||
"github.com/anytypeio/any-sync/util/cidutil"
|
"github.com/anytypeio/any-sync/util/cidutil"
|
||||||
|
"github.com/anytypeio/any-sync/util/crypto"
|
||||||
"github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey"
|
"github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey"
|
||||||
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
||||||
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path"
|
"path"
|
||||||
@ -249,7 +249,7 @@ func (t *AclListStorageBuilder) encryptReadKeysWithPubKey(keys []string, encKey
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *AclListStorageBuilder) encryptReadKeysWithSymKey(keys []string, key *symmetric.Key) (enc [][]byte) {
|
func (t *AclListStorageBuilder) encryptReadKeysWithSymKey(keys []string, key *crypto.AESKey) (enc [][]byte) {
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
realKey := t.keychain.GetKey(k).(*SymKey).Key.Bytes()
|
realKey := t.keychain.GetKey(k).(*SymKey).Key.Bytes()
|
||||||
res, err := key.Encrypt(realKey)
|
res, err := key.Encrypt(realKey)
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import (
|
|||||||
"github.com/anytypeio/any-sync/commonspace/object/keychain"
|
"github.com/anytypeio/any-sync/commonspace/object/keychain"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
||||||
"github.com/anytypeio/any-sync/util/cidutil"
|
"github.com/anytypeio/any-sync/util/cidutil"
|
||||||
|
"github.com/anytypeio/any-sync/util/crypto"
|
||||||
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
||||||
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -21,7 +21,7 @@ type BuilderContent struct {
|
|||||||
Identity []byte
|
Identity []byte
|
||||||
IsSnapshot bool
|
IsSnapshot bool
|
||||||
SigningKey signingkey.PrivKey
|
SigningKey signingkey.PrivKey
|
||||||
ReadKey *symmetric.Key
|
ReadKey *crypto.AESKey
|
||||||
Content []byte
|
Content []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ package objecttree
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/anytypeio/any-sync/util/crypto"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -11,7 +12,6 @@ import (
|
|||||||
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
|
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
|
||||||
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
|
||||||
"github.com/anytypeio/any-sync/util/slice"
|
"github.com/anytypeio/any-sync/util/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ type objectTree struct {
|
|||||||
root *Change
|
root *Change
|
||||||
tree *Tree
|
tree *Tree
|
||||||
|
|
||||||
keys map[uint64]*symmetric.Key
|
keys map[uint64]*crypto.AESKey
|
||||||
|
|
||||||
// buffers
|
// buffers
|
||||||
difSnapshotBuf []*treechangeproto.RawTreeChangeWithId
|
difSnapshotBuf []*treechangeproto.RawTreeChangeWithId
|
||||||
@ -225,7 +225,7 @@ func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
state = ot.aclList.AclState() // special method for own keys
|
state = ot.aclList.AclState() // special method for own keys
|
||||||
readKey *symmetric.Key
|
readKey *crypto.AESKey
|
||||||
readKeyHash uint64
|
readKeyHash uint64
|
||||||
)
|
)
|
||||||
canWrite := state.HasPermission(content.Identity, aclrecordproto.AclUserPermissions_Writer) ||
|
canWrite := state.HasPermission(content.Identity, aclrecordproto.AclUserPermissions_Writer) ||
|
||||||
|
|||||||
@ -5,8 +5,8 @@ import (
|
|||||||
"github.com/anytypeio/any-sync/commonspace/object/keychain"
|
"github.com/anytypeio/any-sync/commonspace/object/keychain"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
|
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
|
||||||
|
"github.com/anytypeio/any-sync/util/crypto"
|
||||||
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/any-sync/util/keys/asymmetric/signingkey"
|
||||||
"github.com/anytypeio/any-sync/util/keys/symmetric"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -189,7 +189,7 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
|
|||||||
aclList: deps.aclList,
|
aclList: deps.aclList,
|
||||||
changeBuilder: deps.changeBuilder,
|
changeBuilder: deps.changeBuilder,
|
||||||
rawChangeLoader: deps.rawChangeLoader,
|
rawChangeLoader: deps.rawChangeLoader,
|
||||||
keys: make(map[uint64]*symmetric.Key),
|
keys: make(map[uint64]*crypto.AESKey),
|
||||||
newChangesBuf: make([]*Change, 0, 10),
|
newChangesBuf: make([]*Change, 0, 10),
|
||||||
difSnapshotBuf: make([]*treechangeproto.RawTreeChangeWithId, 0, 10),
|
difSnapshotBuf: make([]*treechangeproto.RawTreeChangeWithId, 0, 10),
|
||||||
notSeenIdxBuf: make([]int, 0, 10),
|
notSeenIdxBuf: make([]int, 0, 10),
|
||||||
@ -225,7 +225,7 @@ func buildHistoryTree(deps objectTreeDeps, params HistoryTreeParams) (ht History
|
|||||||
aclList: deps.aclList,
|
aclList: deps.aclList,
|
||||||
changeBuilder: deps.changeBuilder,
|
changeBuilder: deps.changeBuilder,
|
||||||
rawChangeLoader: deps.rawChangeLoader,
|
rawChangeLoader: deps.rawChangeLoader,
|
||||||
keys: make(map[uint64]*symmetric.Key),
|
keys: make(map[uint64]*crypto.AESKey),
|
||||||
newChangesBuf: make([]*Change, 0, 10),
|
newChangesBuf: make([]*Change, 0, 10),
|
||||||
difSnapshotBuf: make([]*treechangeproto.RawTreeChangeWithId, 0, 10),
|
difSnapshotBuf: make([]*treechangeproto.RawTreeChangeWithId, 0, 10),
|
||||||
notSeenIdxBuf: make([]int, 0, 10),
|
notSeenIdxBuf: make([]int, 0, 10),
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
package symmetric
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/subtle"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/minio/sha256-simd"
|
|
||||||
|
|
||||||
mbase "github.com/multiformats/go-multibase"
|
mbase "github.com/multiformats/go-multibase"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,83 +17,65 @@ const (
|
|||||||
KeyBytes = 32
|
KeyBytes = 32
|
||||||
)
|
)
|
||||||
|
|
||||||
type Key struct {
|
type AESKey struct {
|
||||||
raw []byte
|
raw []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeriveFromBytes(bytes []byte) (*Key, error) {
|
func (k *AESKey) Equals(key Key) bool {
|
||||||
bArray := sha256.Sum256(bytes)
|
aesKey, ok := key.(*AESKey)
|
||||||
bSlice := bArray[:]
|
if !ok {
|
||||||
return FromBytes(bSlice)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *Key) Equals(otherKey *Key) bool {
|
|
||||||
otherRaw := otherKey.raw
|
|
||||||
keyRaw := k.raw
|
|
||||||
|
|
||||||
if len(keyRaw) != len(otherRaw) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(keyRaw); i++ {
|
return subtle.ConstantTimeCompare(k.raw, aesKey.raw) == 1
|
||||||
if keyRaw[i] != otherRaw[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Key) Raw() ([]byte, error) {
|
func (k *AESKey) Raw() ([]byte, error) {
|
||||||
return k.raw, nil
|
return k.raw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRandom returns a random key.
|
// NewRandomAES returns a random key.
|
||||||
func NewRandom() (*Key, error) {
|
func NewRandomAES() (*AESKey, error) {
|
||||||
raw := make([]byte, KeyBytes)
|
raw := make([]byte, KeyBytes)
|
||||||
if _, err := rand.Read(raw); err != nil {
|
if _, err := rand.Read(raw); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Key{raw: raw}, nil
|
return &AESKey{raw: raw}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns Key if err is nil and panics otherwise.
|
// NewAES returns AESKey if err is nil and panics otherwise.
|
||||||
func New() *Key {
|
func NewAES() *AESKey {
|
||||||
k, err := NewRandom()
|
k, err := NewRandomAES()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromBytes returns a key by decoding bytes.
|
// UnmarshallAESKey returns a key by decoding bytes.
|
||||||
func FromBytes(k []byte) (*Key, error) {
|
func UnmarshallAESKey(k []byte) (*AESKey, error) {
|
||||||
if len(k) != KeyBytes {
|
if len(k) != KeyBytes {
|
||||||
return nil, fmt.Errorf("invalid key")
|
return nil, fmt.Errorf("invalid key")
|
||||||
}
|
}
|
||||||
return &Key{raw: k}, nil
|
return &AESKey{raw: k}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromString returns a key by decoding a base32-encoded string.
|
// UnmarshallAESKeyString returns a key by decoding a base32-encoded string.
|
||||||
func FromString(k string) (*Key, error) {
|
func UnmarshallAESKeyString(k string) (*AESKey, error) {
|
||||||
_, b, err := mbase.Decode(k)
|
_, b, err := mbase.Decode(k)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return FromBytes(b)
|
return UnmarshallAESKey(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns raw key bytes.
|
// Bytes returns raw key bytes.
|
||||||
func (k *Key) Bytes() []byte {
|
func (k *AESKey) Bytes() []byte {
|
||||||
return k.raw
|
return k.raw
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalBinary implements BinaryMarshaler.
|
|
||||||
func (k *Key) MarshalBinary() ([]byte, error) {
|
|
||||||
return k.raw, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the base32-encoded string representation of raw key bytes.
|
// String returns the base32-encoded string representation of raw key bytes.
|
||||||
func (k *Key) String() string {
|
func (k *AESKey) String() string {
|
||||||
str, err := mbase.Encode(mbase.Base32, k.raw)
|
str, err := mbase.Encode(mbase.Base32, k.raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("should not error with hardcoded mbase: " + err.Error())
|
panic("should not error with hardcoded mbase: " + err.Error())
|
||||||
@ -103,7 +84,7 @@ func (k *Key) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Encrypt performs AES-256 GCM encryption on plaintext.
|
// Encrypt performs AES-256 GCM encryption on plaintext.
|
||||||
func (k *Key) Encrypt(plaintext []byte) ([]byte, error) {
|
func (k *AESKey) Encrypt(plaintext []byte) ([]byte, error) {
|
||||||
block, err := aes.NewCipher(k.raw[:KeyBytes])
|
block, err := aes.NewCipher(k.raw[:KeyBytes])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -122,7 +103,7 @@ func (k *Key) Encrypt(plaintext []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt uses key to perform AES-256 GCM decryption on ciphertext.
|
// Decrypt uses key to perform AES-256 GCM decryption on ciphertext.
|
||||||
func (k *Key) Decrypt(ciphertext []byte) ([]byte, error) {
|
func (k *AESKey) Decrypt(ciphertext []byte) ([]byte, error) {
|
||||||
block, err := aes.NewCipher(k.raw[:KeyBytes])
|
block, err := aes.NewCipher(k.raw[:KeyBytes])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1,20 +1,14 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package utilcrypto;
|
package crypto;
|
||||||
option go_package = "util/crypto/cryptoproto";
|
option go_package = "util/crypto/cryptoproto";
|
||||||
|
|
||||||
enum KeyType {
|
enum KeyType {
|
||||||
RSA = 0;
|
Ed25519Public = 0;
|
||||||
Ed25519 = 1;
|
Ed25519Private = 1;
|
||||||
Secp256k1 = 2;
|
AES = 2;
|
||||||
ECDSA = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message PublicKey {
|
message Key {
|
||||||
KeyType Type = 1;
|
KeyType Type = 1;
|
||||||
bytes Data = 2;
|
bytes Data = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PrivateKey {
|
|
||||||
KeyType Type = 1;
|
|
||||||
bytes Data = 2;
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ed25519"
|
|
||||||
"crypto/sha512"
|
|
||||||
"filippo.io/edwards25519"
|
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ed25519PublicKeyToCurve25519 converts an Ed25519 public key to a Curve25519 public key
|
|
||||||
func Ed25519PublicKeyToCurve25519(pk ed25519.PublicKey) []byte {
|
|
||||||
// Unmarshalling public key into edwards curve point
|
|
||||||
epk, err := (&edwards25519.Point{}).SetBytes(pk)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// converting to curve25519 (see here for more details https://github.com/golang/go/issues/20504)
|
|
||||||
return epk.BytesMontgomery()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ISC License
|
|
||||||
//
|
|
||||||
// Copyright (c) 2013-2020
|
|
||||||
// Frank Denis <j at pureftpd dot org>
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice appear in all copies.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
// https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_sign/ed25519/ref10/keypair.c#L69-L83
|
|
||||||
|
|
||||||
// Ed25519PrivateKeyToCurve25519 converts an Ed25519 private key to a Curve25519 private key
|
|
||||||
// This code is originally taken from here https://github.com/jorrizza/ed2curve25519/blob/master/ed2curve25519.go
|
|
||||||
func Ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) []byte {
|
|
||||||
h := sha512.New()
|
|
||||||
h.Write(pk.Seed())
|
|
||||||
out := h.Sum(nil)
|
|
||||||
|
|
||||||
// used in libsodium
|
|
||||||
out[0] &= 248
|
|
||||||
out[31] &= 127
|
|
||||||
out[31] |= 64
|
|
||||||
|
|
||||||
return out[:curve25519.ScalarSize]
|
|
||||||
}
|
|
||||||
@ -25,7 +25,7 @@ type PrivKey interface {
|
|||||||
GetPublic() PubKey
|
GetPublic() PubKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// PubKey is the public key used to verify the signatures made by SignPrivKey
|
// PubKey is the public key used to verify the signatures and decrypt messages
|
||||||
type PubKey interface {
|
type PubKey interface {
|
||||||
Key
|
Key
|
||||||
|
|
||||||
@ -35,6 +35,15 @@ type PubKey interface {
|
|||||||
Verify(data []byte, sig []byte) (bool, error)
|
Verify(data []byte, sig []byte) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SymKey interface {
|
||||||
|
Key
|
||||||
|
|
||||||
|
// Decrypt decrypts the message and returns the result
|
||||||
|
Decrypt(message []byte) ([]byte, error)
|
||||||
|
// Encrypt encrypts the message and returns the result
|
||||||
|
Encrypt(message []byte) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
func KeyEquals(k1, k2 Key) bool {
|
func KeyEquals(k1, k2 Key) bool {
|
||||||
a, err := k1.Raw()
|
a, err := k1.Raw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -1,14 +1,62 @@
|
|||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ed25519"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha512"
|
||||||
"errors"
|
"errors"
|
||||||
|
"filippo.io/edwards25519"
|
||||||
"golang.org/x/crypto/blake2b"
|
"golang.org/x/crypto/blake2b"
|
||||||
|
"golang.org/x/crypto/curve25519"
|
||||||
"golang.org/x/crypto/nacl/box"
|
"golang.org/x/crypto/nacl/box"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrX25519DecryptionFailed = errors.New("failed decryption with x25519 key")
|
var ErrX25519DecryptionFailed = errors.New("failed decryption with x25519 key")
|
||||||
|
|
||||||
|
// Ed25519PublicKeyToCurve25519 converts an Ed25519 public key to a Curve25519 public key
|
||||||
|
func Ed25519PublicKeyToCurve25519(pk ed25519.PublicKey) []byte {
|
||||||
|
// Unmarshalling public key into edwards curve point
|
||||||
|
epk, err := (&edwards25519.Point{}).SetBytes(pk)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// converting to curve25519 (see here for more details https://github.com/golang/go/issues/20504)
|
||||||
|
return epk.BytesMontgomery()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISC License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020
|
||||||
|
// Frank Denis <j at pureftpd dot org>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
// https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_sign/ed25519/ref10/keypair.c#L69-L83
|
||||||
|
|
||||||
|
// Ed25519PrivateKeyToCurve25519 converts an Ed25519 private key to a Curve25519 private key
|
||||||
|
// This code is originally taken from here https://github.com/jorrizza/ed2curve25519/blob/master/ed2curve25519.go
|
||||||
|
func Ed25519PrivateKeyToCurve25519(pk ed25519.PrivateKey) []byte {
|
||||||
|
h := sha512.New()
|
||||||
|
h.Write(pk.Seed())
|
||||||
|
out := h.Sum(nil)
|
||||||
|
|
||||||
|
// used in libsodium
|
||||||
|
out[0] &= 248
|
||||||
|
out[31] &= 127
|
||||||
|
out[31] |= 64
|
||||||
|
|
||||||
|
return out[:curve25519.ScalarSize]
|
||||||
|
}
|
||||||
|
|
||||||
// EncryptX25519 takes a x25519 public key and encrypts the message
|
// EncryptX25519 takes a x25519 public key and encrypts the message
|
||||||
func EncryptX25519(pubKey *[32]byte, msg []byte) []byte {
|
func EncryptX25519(pubKey *[32]byte, msg []byte) []byte {
|
||||||
// see discussion here https://github.com/golang/go/issues/29128
|
// see discussion here https://github.com/golang/go/issues/29128
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user