123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- // Copyright 2010 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
- package packet
- import (
- "crypto/cipher"
- )
- type ocfbEncrypter struct {
- b cipher.Block
- fre []byte
- outUsed int
- }
- // An OCFBResyncOption determines if the "resynchronization step" of OCFB is
- // performed.
- type OCFBResyncOption bool
- const (
- OCFBResync OCFBResyncOption = true
- OCFBNoResync OCFBResyncOption = false
- )
- // 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 (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
- for i := 0; i < len(src); i++ {
- if x.outUsed == len(x.fre) {
- x.b.Encrypt(x.fre, x.fre)
- x.outUsed = 0
- }
- x.fre[x.outUsed] ^= src[i]
- dst[i] = x.fre[x.outUsed]
- x.outUsed++
- }
- }
- type ocfbDecrypter struct {
- b cipher.Block
- fre []byte
- outUsed int
- }
- // 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
- }
- func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
- for i := 0; i < len(src); i++ {
- if x.outUsed == len(x.fre) {
- x.b.Encrypt(x.fre, x.fre)
- x.outUsed = 0
- }
- c := src[i]
- dst[i] = x.fre[x.outUsed] ^ src[i]
- x.fre[x.outUsed] = c
- x.outUsed++
- }
- }
|