Пример #1
0
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)
		}
	}
}
Пример #2
0
// 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
}
Пример #3
0
// 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])
	}
}
Пример #6
0
Файл: eme.go Проект: ncw/rclone
// 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
	}
}
Пример #7
0
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
}
Пример #8
0
// 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]
}
Пример #9
0
// 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[:])
}
Пример #10
0
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
}
Пример #11
0
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
}
Пример #12
0
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
}
Пример #13
0
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
}
Пример #14
0
// 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
}
Пример #15
0
Файл: eme.go Проект: ncw/rclone
// 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
}
Пример #16
0
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)
	}
}
Пример #17
0
// 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
}
Пример #18
0
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])
	}
}
Пример #19
0
// 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
}
Пример #20
0
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
}
Пример #21
0
// 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
}
Пример #22
0
// 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
}
Пример #23
0
// 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
}
Пример #24
0
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
}
Пример #25
0
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
}
Пример #26
0
// 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
}
Пример #27
0
// 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
}
Пример #28
0
// 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
}