func TestCipher(t *testing.T) { var aes cipher.Block var err error for cipher_id, expected := range cipher_results { aes, err = NewCipher(cipher_id, key, nil) if err != nil { t.Fatal(err) } blocksize := aes.BlockSize() ciphertext := make([]byte, blocksize) aes.Encrypt(ciphertext, cleartext) deciphertext := make([]byte, blocksize) if !strings.EqualFold(expected, fmt.Sprintf("%x", ciphertext)) { t.Fatal("couldn't encrypt") } aes, err = NewCipher(cipher_id, key, nil) aes.Decrypt(deciphertext, ciphertext) if !bytes.Equal(cleartext, deciphertext) { t.Fatal("couldn't decrypt %s %s", cleartext, deciphertext) } if err != nil { t.Fatal(err) } } }
// Given the supplied cipher, whose block size must be 16 bytes, return two // subkeys that can be used in MAC generation. See section 5.3 of NIST SP // 800-38B. Note that the other NIST-approved block size of 8 bytes is not // supported by this function. func generateSubkeys(ciph cipher.Block) (k1 []byte, k2 []byte) { if ciph.BlockSize() != blockSize { panic("generateSubkeys requires a cipher with a block size of 16 bytes.") } // Step 1 l := make([]byte, blockSize) ciph.Encrypt(l, subkeyZero) // Step 2: Derive the first subkey. if common.Msb(l) == 0 { // TODO(jacobsa): Accept a destination buffer in ShiftLeft and then hoist // the allocation in the else branch below. k1 = common.ShiftLeft(l) } else { k1 = make([]byte, blockSize) common.Xor(k1, common.ShiftLeft(l), subkeyRb) } // Step 3: Derive the second subkey. if common.Msb(k1) == 0 { k2 = common.ShiftLeft(k1) } else { k2 = make([]byte, blockSize) common.Xor(k2, common.ShiftLeft(k1), subkeyRb) } return }
// Encrypts the contents of a file and returns the encrypted byte slice. // AES encryption with PCKS#7 padding. func Encrypt(filename, key string) (encrypted []byte, err error) { var ( aesCipher cipher.Block data []byte tempenc = make([]byte, blockSize) ) aesCipher, err = aes.NewCipher([]byte(key)) if err != nil { return } data, err = ioutil.ReadFile(filename) if err != nil { return encrypted, err } padded, err := padding.Pad(data, blockSize) if err != nil { return encrypted, err } for i := 0; i < len(padded)/blockSize; i++ { aesCipher.Encrypt(tempenc, padded[i*blockSize:i*blockSize+blockSize]) encrypted = append(encrypted, tempenc...) } return encrypted, nil }
func CTREncrypt(block cipher.Block, nonce, dst, src []byte) { size := block.BlockSize() if len(nonce) != size { panic("size of IV not equal to block size") } if len(dst) == 0 || len(src) == 0 { return } // temp key key := make([]byte, size) // copy of nonce n := make([]byte, size) copy(n, nonce) counter := binary.LittleEndian.Uint64(n[8:]) for i := 0; i < len(dst) && i < len(src); i += size { block.Encrypt(key, n) for j := 0; j < size && i+j < len(src); j++ { dst[i+j] = src[i+j] ^ key[j] } counter++ binary.LittleEndian.PutUint64(n[8:], counter) } return }
func ECBEncrypt(block cipher.Block, dst, src []byte) { size := block.BlockSize() if len(dst)%size != 0 { panic("size of dst and src should be multiples of blocksize") } for i := 0; i < len(dst); i += size { block.Encrypt(dst[i:i+size], src[i:i+size]) } }
// aesTransform - encrypt or decrypt (according to "direction") using block // cipher "bc" (typically AES) func aesTransform(dst []byte, src []byte, direction directionConst, bc cipher.Block) { if direction == DirectionEncrypt { bc.Encrypt(dst, src) return } else if direction == DirectionDecrypt { bc.Decrypt(dst, src) return } }
func get_key(master cipher.Block, ctr uint64) (cipher.Block, []byte) { plain := make([]byte, 16) new_key := make([]byte, 16) binary.BigEndian.PutUint64(plain, ctr) master.Encrypt(new_key, plain) new_cipher, err := aes.NewCipher(new_key) check(err) return new_cipher, new_key }
// updateMAC reseeds the given hash with encrypted seed. // it returns the first 16 bytes of the hash sum after seeding. func updateMAC(mac hash.Hash, block cipher.Block, seed []byte) []byte { aesbuf := make([]byte, aes.BlockSize) block.Encrypt(aesbuf, mac.Sum(nil)) for i := range aesbuf { aesbuf[i] ^= seed[i] } mac.Write(aesbuf) return mac.Sum(nil)[:16] }
// Encrypt encrypts the plaintext src and outputs the corresponding ciphertext into dst. // Besides outputting a ciphertext into dst, Encrypt also outputs an authentication tag // of ocb2.TagSize bytes into tag, which should be used to verify the authenticity of the // message on the receiving side. // // To ensure both authenticity and secrecy of messages, each invocation to this function must // be given an unique nonce of ocb2.NonceSize bytes. The nonce need not be secret (it can be // a counter), but it needs to be unique. // // The block cipher used in function must work on a block size equal to ocb2.BlockSize. // The tag slice used in this function must have a length equal to ocb2.TagSize. // The nonce slice used in this function must have a length equal to ocb2.NonceSize. // If any of the above are violated, Encrypt will panic. func Encrypt(cipher cipher.Block, dst []byte, src []byte, nonce []byte, tag []byte) { if cipher.BlockSize() != BlockSize { panic("ocb2: cipher blocksize is not equal to ocb2.BlockSize") } if len(nonce) != NonceSize { panic("ocb2: nonce length is not equal to ocb2.NonceSize") } var ( checksum [BlockSize]byte delta [BlockSize]byte tmp [BlockSize]byte pad [BlockSize]byte calcTag [NonceSize]byte off int ) cipher.Encrypt(delta[0:], nonce[0:]) zeros(checksum[0:]) remain := len(src) for remain > BlockSize { times2(delta[0:]) xor(tmp[0:], delta[0:], src[off:off+BlockSize]) cipher.Encrypt(tmp[0:], tmp[0:]) xor(dst[off:off+BlockSize], delta[0:], tmp[0:]) xor(checksum[0:], checksum[0:], src[off:off+BlockSize]) remain -= BlockSize off += BlockSize } times2(delta[0:]) zeros(tmp[0:]) num := remain * 8 tmp[BlockSize-2] = uint8((uint32(num) >> 8) & 0xff) tmp[BlockSize-1] = uint8(num & 0xff) xor(tmp[0:], tmp[0:], delta[0:]) cipher.Encrypt(pad[0:], tmp[0:]) copied := copy(tmp[0:], src[off:]) if copied != remain { panic("ocb2: copy failed") } if copy(tmp[copied:], pad[copied:]) != (BlockSize - remain) { panic("ocb2: copy failed") } xor(checksum[0:], checksum[0:], tmp[0:]) xor(tmp[0:], pad[0:], tmp[0:]) if copy(dst[off:], tmp[0:]) != remain { panic("ocb2: copy failed") } times3(delta[0:]) xor(tmp[0:], delta[0:], checksum[0:]) cipher.Encrypt(calcTag[0:], tmp[0:]) copy(tag, calcTag[:]) }
func aesEncrypt(block cipher.Block, src []byte) []byte { var dst = make([]byte, 16) var src_len = len(src) if src_len%16 != 0 { src = append(src, make([]byte, 16-src_len%16)...) } var enc []byte for i := 0; i < src_len; i += 16 { block.Encrypt(dst, src[i:i+16]) enc = append(enc, dst...) } return enc }
func AESEncryptBytes(block cipher.Block, plain []byte) (cipherBytes []byte, err error) { blockSize := block.BlockSize() plain = utils.PadBytes(plain, blockSize) length := len(plain) // Encrypt cipherBytes = make([]byte, length) for i := 0; i < length; i += blockSize { block.Encrypt(cipherBytes[i:i+blockSize], plain[i:i+blockSize]) } return }
func DecryptCTR(ciph cipher.Block, iv []byte, ciphertext []byte) ([]byte, error) { var pad []byte var mixin big.Int mixin.SetBytes(iv) for i := 0; i <= len(ciphertext)/16; i++ { if i != 0 { mixin.Add(&mixin, big.NewInt(1)) // mixin++ } encrypted := make([]byte, 16) ciph.Encrypt(encrypted, mixin.Bytes()) pad = append(pad, encrypted...) } return mobytes.XOR(ciphertext, pad), nil }
func encryptBlocks(b cipher.Block, src, dst []byte) error { if len(src)%b.BlockSize() != 0 { return ErrBlockSize } if len(dst) < len(src) { return ErrOutputSize } for len(src) > 0 { b.Encrypt(dst, src[:b.BlockSize()]) src = src[b.BlockSize():] dst = dst[b.BlockSize():] } return nil }
// blockEncrypt encrypts using the block cipher blk in ECB mode. func blockEncrypt(blk cipher.Block, dst, src []byte) error { if len(src) > len(dst) || len(src)%blk.BlockSize() != 0 { return errors.New("Block encryption failed") } l := len(src) - blk.BlockSize() for i := 0; i <= l; i += blk.BlockSize() { blk.Encrypt(dst[i:], src[i:]) } return nil }
// tabulateL - calculate L_i for messages up to a length of m cipher blocks func tabulateL(bc cipher.Block, m int) [][]byte { /* set L0 = 2*AESenc(K; 0) */ eZero := make([]byte, 16) Li := make([]byte, 16) bc.Encrypt(Li, eZero) LTable := make([][]byte, m) // Allocate pool once and slice into m pieces in the loop pool := make([]byte, m*16) for i := 0; i < m; i++ { multByTwo(Li, Li) LTable[i] = pool[i*16 : (i+1)*16] copy(LTable[i], Li) } return LTable }
func TestStreamCipher(t *testing.T) { var aes cipher.Block var err error iv := []byte{0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} aes, err = NewCipher(CRYPTO_AES_CBC, key, iv) if err != nil { t.Fatal(err) } blocksize := aes.BlockSize() ciphertext := make([]byte, blocksize) aes.Encrypt(ciphertext, cleartext) deciphertext := make([]byte, blocksize) aes, err = NewCipher(CRYPTO_AES_CBC, key, iv) aes.Decrypt(deciphertext, ciphertext) if !bytes.Equal(cleartext, deciphertext) { t.Fatal("couldn't decrypt %s %s", cleartext, deciphertext) } if err != nil { t.Fatal(err) } }
// Creates a new Galois/Counter Mode for a given block cipher. The iv parameter is // required, but a tagSizeInBits of zero can be supplied, in which case the default tag // size of 128 bits will be used. func NewGCM(b cipher.Block, tagSizeInBits int, iv []byte) (GaloisCounterMode, error) { if b.BlockSize() != 16 && b.BlockSize() != 18 && b.BlockSize() != 24 { return nil, errors.New("Block cipher MUST have a 128-bit block size") } if tagSizeInBits <= 0 { tagSizeInBits = 128 } h := make([]byte, 16) b.Encrypt(h, zeroes[:16]) return &gcm{ b: b, blockSize: b.BlockSize(), iv: dup(iv), h: h, tagSize: tagSizeInBits / 8, tmp: make([]byte, b.BlockSize()), }, nil }
func CBCEncrypt(block cipher.Block, iv, dst, src []byte) { size := block.BlockSize() if len(iv) != size { panic("size of IV not equal to block size") } if len(dst)%size != 0 { panic("size of dst and src should be multiples of blocksize") } if len(dst) == 0 || len(src) == 0 { return } x := make([]byte, size) copy(x, iv) for i := 0; i < len(dst) && i < len(src); i += size { for j := 0; j < size; j++ { x[j] ^= src[i+j] } block.Encrypt(dst[i:i+size], x) copy(x, dst[i:i+size]) } }
// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's // cipher feedback mode using the given cipher.Block, and an initial amount of // ciphertext. randData must be random bytes and be the same length as the // cipher.Block's block size. Resync determines if the "resynchronization step" // from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on // this point. func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { blockSize := block.BlockSize() if len(randData) != blockSize { return nil, nil } x := &ocfbEncrypter{ b: block, fre: make([]byte, blockSize), outUsed: 0, } prefix := make([]byte, blockSize+2) block.Encrypt(x.fre, x.fre) for i := 0; i < blockSize; i++ { prefix[i] = randData[i] ^ x.fre[i] } block.Encrypt(x.fre, prefix[:blockSize]) prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] if resync { block.Encrypt(x.fre, prefix[2:]) } else { x.fre[0] = prefix[blockSize] x.fre[1] = prefix[blockSize+1] x.outUsed = 2 } return x, prefix }
func keywrap(kek cipher.Block, cek []byte) ([]byte, error) { if len(cek)%8 != 0 { return nil, ErrInvalidBlockSize } n := len(cek) / keywrapChunkLen r := make([][]byte, n) for i := 0; i < n; i++ { r[i] = make([]byte, keywrapChunkLen) copy(r[i], cek[i*keywrapChunkLen:]) } buffer := make([]byte, keywrapChunkLen*2) tBytes := make([]byte, keywrapChunkLen) copy(buffer, keywrapDefaultIV) for t := 0; t < 6*n; t++ { copy(buffer[keywrapChunkLen:], r[t%n]) kek.Encrypt(buffer, buffer) binary.BigEndian.PutUint64(tBytes, uint64(t+1)) for i := 0; i < keywrapChunkLen; i++ { buffer[i] = buffer[i] ^ tBytes[i] } copy(r[t%n], buffer[keywrapChunkLen:]) } out := make([]byte, (n+1)*keywrapChunkLen) copy(out, buffer[:keywrapChunkLen]) for i := range r { copy(out[(i+1)*8:], r[i]) } return out, nil }
// KeyWrap implements NIST key wrapping; it wraps a content encryption key (cek) with the given block cipher. func KeyWrap(block cipher.Block, cek []byte) ([]byte, error) { if len(cek)%8 != 0 { return nil, errors.New("square/go-jose: key wrap input must be 8 byte blocks") } n := len(cek) / 8 r := make([][]byte, n) for i := range r { r[i] = make([]byte, 8) copy(r[i], cek[i*8:]) } buffer := make([]byte, 16) tBytes := make([]byte, 8) copy(buffer, defaultIV) for t := 0; t < 6*n; t++ { copy(buffer[8:], r[t%n]) block.Encrypt(buffer, buffer) binary.BigEndian.PutUint64(tBytes, uint64(t+1)) for i := 0; i < 8; i++ { buffer[i] = buffer[i] ^ tBytes[i] } copy(r[t%n], buffer[8:]) } out := make([]byte, (n+1)*8) copy(out, buffer[:8]) for i := range r { copy(out[(i+1)*8:], r[i]) } return out, nil }
// New returns a hash.Hash computing the CMac checksum. // If the block cipher is not supported by CMac // (see package doc), a non-nil error is returned. func New(c cipher.Block) (hash.Hash, error) { if c == nil { return nil, errors.New("the cipher.Block must not be nil") } bs := c.BlockSize() var p int switch bs { default: return nil, errors.New("cipher block size not supported") case 8: p = p64 case 16: p = p128 case 32: p = p256 case 64: p = p512 case 128: p = p1024 } m := &macFunc{ cipher: c, k0: make([]byte, bs), k1: make([]byte, bs), buf: make([]byte, bs), } c.Encrypt(m.k0, m.k0) v := shift(m.k0, m.k0) m.k0[bs-1] ^= byte(subtle.ConstantTimeSelect(v, p, 0)) v = shift(m.k1, m.k0) m.k1[bs-1] ^= byte(subtle.ConstantTimeSelect(v, p, 0)) return m, nil }
// encryptDES enrypts plaintext input with passed key, IV and 3DES-flag in DES block cipher; // and returns ciphertext output func encryptDES(input, key, iv []byte, tripleDES bool) ([]byte, error) { var block cipher.Block var err error if tripleDES { block, err = des.NewTripleDESCipher(key) } else { block, err = des.NewCipher(key) } if err != nil { return nil, errors.New("Couldn't create block cipher.") } if len(input)%des.BlockSize != 0 { input = addPadding(input, des.BlockSize) } output := make([]byte, len(input)) for i := 0; i < len(input)/des.BlockSize; i++ { start := des.BlockSize * i end := start + des.BlockSize block.Encrypt(output[start:end], input[start:end]) } return output, nil }
func key_warp(block cp.Block, cek []byte) ([]byte, error) { if len(cek)%8 != 0 { return nil, errors.New("key warp must 8 byte") } n := len(cek) / 8 r := make([][]byte, n) for i := range r { r[i] = make([]byte, 8) copy(r[i], cek[i*8:]) } buf := make([]byte, 16) tb := make([]byte, 8) copy(buf, default_iv) for t := 0; t < 6*n; t++ { copy(buf[8:], r[t%n]) block.Encrypt(buf, buf) binary.BigEndian.PutUint64(tb, uint64(t+1)) for i := 0; i < 8; i++ { buf[i] = buf[i] ^ tb[i] } copy(r[t%n], buf[8:]) } out := make([]byte, (n+1)*8) copy(out, buf[:8]) for i := range r { copy(out[(i+1)*8:], r[i]) } return out, nil }
func encrypt(src io.Reader, des io.Writer, cipher cipher.Block, length int) error { if length <= 0 { return errors.New("length must be greater than 0") } blockSize := cipher.BlockSize() buf := make([]byte, blockSize) acc := 0 var n int var err error if length-acc >= blockSize { n, err = src.Read(buf) } else { n, err = src.Read(buf[0 : length-acc]) } for err == nil && acc != length { acc += n if n > 0 && n < blockSize { paddings := blockSize - n for i := blockSize - paddings; i < blockSize; i++ { buf[i] = padding } } cipher.Encrypt(buf, buf) des.Write(buf) buf = make([]byte, blockSize) if length-acc >= blockSize { n, err = src.Read(buf) } else { n, err = src.Read(buf[0 : length-acc]) } } return nil }
// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's // cipher feedback mode using the given cipher.Block. Prefix must be the first // blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's // block size. If an incorrect key is detected then nil is returned. On // successful exit, blockSize+2 bytes of decrypted data are written into // prefix. Resync determines if the "resynchronization step" from RFC 4880, // 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { blockSize := block.BlockSize() if len(prefix) != blockSize+2 { return nil } x := &ocfbDecrypter{ b: block, fre: make([]byte, blockSize), outUsed: 0, } prefixCopy := make([]byte, len(prefix)) copy(prefixCopy, prefix) block.Encrypt(x.fre, x.fre) for i := 0; i < blockSize; i++ { prefixCopy[i] ^= x.fre[i] } block.Encrypt(x.fre, prefix[:blockSize]) prefixCopy[blockSize] ^= x.fre[0] prefixCopy[blockSize+1] ^= x.fre[1] if prefixCopy[blockSize-2]!=prefixCopy[blockSize] || prefixCopy[blockSize-1]!=prefixCopy[blockSize+1] { return nil } if resync { block.Encrypt(x.fre, prefix[2:]) } else { x.fre[0] = prefix[blockSize] x.fre[1] = prefix[blockSize+1] x.outUsed = 2 } copy(prefix, prefixCopy) return x }
// Decrypt takes a ciphertext, a nonce, and a tag as its input and outputs a decrypted // plaintext (if successful) and a boolean flag that determines whether the function // successfully decrypted the given ciphertext. // // Before using the decrpyted plaintext, the application // should verify that the computed authentication tag matches the tag that was produced when // encrypting the message (taking into consideration that OCB tags are allowed to be truncated // to a length less than ocb.TagSize). // // The block cipher used in function must work on a block size equal to ocb2.BlockSize. // The tag slice used in this function must have a length equal to ocb2.TagSize. // The nonce slice used in this function must have a length equal to ocb2.NonceSize. // If any of the above are violated, Encrypt will panic. func Decrypt(cipher cipher.Block, plain []byte, encrypted []byte, nonce []byte, tag []byte) bool { if cipher.BlockSize() != BlockSize { panic("ocb2: cipher blocksize is not equal to ocb2.BlockSize") } if len(nonce) != NonceSize { panic("ocb2: nonce length is not equal to ocb2.NonceSize") } var ( checksum [BlockSize]byte delta [BlockSize]byte tmp [BlockSize]byte pad [BlockSize]byte calcTag [NonceSize]byte off int ) cipher.Encrypt(delta[0:], nonce[0:]) zeros(checksum[0:]) remain := len(encrypted) for remain > BlockSize { times2(delta[0:]) xor(tmp[0:], delta[0:], encrypted[off:off+BlockSize]) cipher.Decrypt(tmp[0:], tmp[0:]) xor(plain[off:off+BlockSize], delta[0:], tmp[0:]) xor(checksum[0:], checksum[0:], plain[off:off+BlockSize]) off += BlockSize remain -= BlockSize } times2(delta[0:]) zeros(tmp[0:]) num := remain * 8 tmp[BlockSize-2] = uint8((uint32(num) >> 8) & 0xff) tmp[BlockSize-1] = uint8(num & 0xff) xor(tmp[0:], tmp[0:], delta[0:]) cipher.Encrypt(pad[0:], tmp[0:]) zeros(tmp[0:]) copied := copy(tmp[0:remain], encrypted[off:off+remain]) if copied != remain { panic("ocb2: copy failed") } xor(tmp[0:], tmp[0:], pad[0:]) xor(checksum[0:], checksum[0:], tmp[0:]) copied = copy(plain[off:off+remain], tmp[0:remain]) if copied != remain { panic("ocb2: copy failed") } times3(delta[0:]) xor(tmp[0:], delta[0:], checksum[0:]) cipher.Encrypt(calcTag[0:], tmp[0:]) // Compare the calculated tag with the expected tag. Truncate // the computed tag if necessary. if subtle.ConstantTimeCompare(calcTag[:len(tag)], tag) != 1 { return false } return true }
// wrapKey encrypts the clear key according to an access structure. func (encrypted *EncryptedData) wrapKey(records *passvault.Records, clearKey []byte, access AccessStructure) (err error) { generateRandomKey := func(name string) (singleWrappedKey SingleWrappedKey, err error) { rec, ok := records.GetRecord(name) if !ok { err = errors.New("Missing user on disk") return } if singleWrappedKey.aesKey, err = symcrypt.MakeRandom(16); err != nil { return } if singleWrappedKey.Key, err = rec.EncryptKey(singleWrappedKey.aesKey); err != nil { return } return } encryptKey := func(outer, inner string, clearKey []byte) (keyBytes []byte, err error) { var outerCrypt, innerCrypt cipher.Block keyBytes = make([]byte, 16) outerCrypt, err = aes.NewCipher(encrypted.KeySetRSA[outer].aesKey) if err != nil { return } innerCrypt, err = aes.NewCipher(encrypted.KeySetRSA[inner].aesKey) if err != nil { return } innerCrypt.Encrypt(keyBytes, clearKey) outerCrypt.Encrypt(keyBytes, keyBytes) return } if len(access.Names) > 0 { // Generate a random AES key for each user and RSA/ECIES encrypt it encrypted.KeySetRSA = make(map[string]SingleWrappedKey) for _, name := range access.Names { encrypted.KeySetRSA[name], err = generateRandomKey(name) if err != nil { return err } } // encrypt file key with every combination of two keys encrypted.KeySet = make([]MultiWrappedKey, 0) for i := 0; i < len(access.Names); i++ { for j := i + 1; j < len(access.Names); j++ { keyBytes, err := encryptKey(access.Names[i], access.Names[j], clearKey) if err != nil { return err } out := MultiWrappedKey{ Name: []string{access.Names[i], access.Names[j]}, Key: keyBytes, } encrypted.KeySet = append(encrypted.KeySet, out) } } } else if len(access.LeftNames) > 0 && len(access.RightNames) > 0 { // Generate a random AES key for each user and RSA/ECIES encrypt it encrypted.KeySetRSA = make(map[string]SingleWrappedKey) for _, name := range access.LeftNames { encrypted.KeySetRSA[name], err = generateRandomKey(name) if err != nil { return err } } for _, name := range access.RightNames { encrypted.KeySetRSA[name], err = generateRandomKey(name) if err != nil { return err } } // encrypt file key with every combination of one left key and one right key encrypted.KeySet = make([]MultiWrappedKey, 0) for _, leftName := range access.LeftNames { for _, rightName := range access.RightNames { if leftName == rightName { continue } keyBytes, err := encryptKey(leftName, rightName, clearKey) if err != nil { return err } out := MultiWrappedKey{ Name: []string{leftName, rightName}, Key: keyBytes, } encrypted.KeySet = append(encrypted.KeySet, out) } } } else if len(access.Predicate) > 0 { encrypted.KeySetRSA = make(map[string]SingleWrappedKey) sss, err := msp.StringToMSP(access.Predicate) if err != nil { return err } db := msp.UserDatabase(UserDatabase{records: records}) shareSet, err := sss.DistributeShares(clearKey, &db) if err != nil { return err } for name, _ := range shareSet { encrypted.KeySetRSA[name], err = generateRandomKey(name) if err != nil { return err } crypt, err := aes.NewCipher(encrypted.KeySetRSA[name].aesKey) if err != nil { return err } for i, _ := range shareSet[name] { tmp := make([]byte, 16) crypt.Encrypt(tmp, shareSet[name][i]) shareSet[name][i] = tmp } } encrypted.ShareSet = shareSet encrypted.Predicate = access.Predicate } else { return errors.New("Invalid access structure.") } return nil }