github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/memberlist/keyring.go (about) 1 package memberlist 2 3 import ( 4 "bytes" 5 "fmt" 6 "sync" 7 ) 8 9 type Keyring struct { 10 // Keys stores the key data used during encryption and decryption. It is 11 // ordered in such a way where the first key (index 0) is the primary key, 12 // which is used for encrypting messages, and is the first key tried during 13 // message decryption. 14 keys [][]byte 15 16 // The keyring lock is used while performing IO operations on the keyring. 17 l sync.Mutex 18 } 19 20 // Init allocates substructures 21 func (k *Keyring) init() { 22 k.keys = make([][]byte, 0) 23 } 24 25 // NewKeyring constructs a new container for a set of encryption keys. The 26 // keyring contains all key data used internally by memberlist. 27 // 28 // While creating a new keyring, you must do one of: 29 // - Omit keys and primary key, effectively disabling encryption 30 // - Pass a set of keys plus the primary key 31 // - Pass only a primary key 32 // 33 // If only a primary key is passed, then it will be automatically added to the 34 // keyring. If creating a keyring with multiple keys, one key must be designated 35 // primary by passing it as the primaryKey. If the primaryKey does not exist in 36 // the list of secondary keys, it will be automatically added at position 0. 37 // 38 // A key should be either 16, 24, or 32 bytes to select AES-128, 39 // AES-192, or AES-256. 40 func NewKeyring(keys [][]byte, primaryKey []byte) (*Keyring, error) { 41 keyring := &Keyring{} 42 keyring.init() 43 44 if len(keys) > 0 || len(primaryKey) > 0 { 45 if len(primaryKey) == 0 { 46 return nil, fmt.Errorf("Empty primary key not allowed") 47 } 48 if err := keyring.AddKey(primaryKey); err != nil { 49 return nil, err 50 } 51 for _, key := range keys { 52 if err := keyring.AddKey(key); err != nil { 53 return nil, err 54 } 55 } 56 } 57 58 return keyring, nil 59 } 60 61 // ValidateKey will check to see if the key is valid and returns an error if not. 62 // 63 // key should be either 16, 24, or 32 bytes to select AES-128, 64 // AES-192, or AES-256. 65 func ValidateKey(key []byte) error { 66 if l := len(key); l != 16 && l != 24 && l != 32 { 67 return fmt.Errorf("key size must be 16, 24 or 32 bytes") 68 } 69 return nil 70 } 71 72 // AddKey will install a new key on the ring. Adding a key to the ring will make 73 // it available for use in decryption. If the key already exists on the ring, 74 // this function will just return noop. 75 // 76 // key should be either 16, 24, or 32 bytes to select AES-128, 77 // AES-192, or AES-256. 78 func (k *Keyring) AddKey(key []byte) error { 79 if err := ValidateKey(key); err != nil { 80 return err 81 } 82 83 // No-op if key is already installed 84 for _, installedKey := range k.keys { 85 if bytes.Equal(installedKey, key) { 86 return nil 87 } 88 } 89 90 keys := append(k.keys, key) 91 primaryKey := k.GetPrimaryKey() 92 if primaryKey == nil { 93 primaryKey = key 94 } 95 k.installKeys(keys, primaryKey) 96 return nil 97 } 98 99 // UseKey changes the key used to encrypt messages. This is the only key used to 100 // encrypt messages, so peers should know this key before this method is called. 101 func (k *Keyring) UseKey(key []byte) error { 102 for _, installedKey := range k.keys { 103 if bytes.Equal(key, installedKey) { 104 k.installKeys(k.keys, key) 105 return nil 106 } 107 } 108 return fmt.Errorf("Requested key is not in the keyring") 109 } 110 111 // RemoveKey drops a key from the keyring. This will return an error if the key 112 // requested for removal is currently at position 0 (primary key). 113 func (k *Keyring) RemoveKey(key []byte) error { 114 if bytes.Equal(key, k.keys[0]) { 115 return fmt.Errorf("Removing the primary key is not allowed") 116 } 117 for i, installedKey := range k.keys { 118 if bytes.Equal(key, installedKey) { 119 keys := append(k.keys[:i], k.keys[i+1:]...) 120 k.installKeys(keys, k.keys[0]) 121 } 122 } 123 return nil 124 } 125 126 // installKeys will take out a lock on the keyring, and replace the keys with a 127 // new set of keys. The key indicated by primaryKey will be installed as the new 128 // primary key. 129 func (k *Keyring) installKeys(keys [][]byte, primaryKey []byte) { 130 k.l.Lock() 131 defer k.l.Unlock() 132 133 newKeys := [][]byte{primaryKey} 134 for _, key := range keys { 135 if !bytes.Equal(key, primaryKey) { 136 newKeys = append(newKeys, key) 137 } 138 } 139 k.keys = newKeys 140 } 141 142 // GetKeys returns the current set of keys on the ring. 143 func (k *Keyring) GetKeys() [][]byte { 144 k.l.Lock() 145 defer k.l.Unlock() 146 147 return k.keys 148 } 149 150 // GetPrimaryKey returns the key on the ring at position 0. This is the key used 151 // for encrypting messages, and is the first key tried for decrypting messages. 152 func (k *Keyring) GetPrimaryKey() (key []byte) { 153 k.l.Lock() 154 defer k.l.Unlock() 155 156 if len(k.keys) > 0 { 157 key = k.keys[0] 158 } 159 return 160 }