...

Source file src/golang.org/x/crypto/openpgp/packet/ocfb.go

Documentation: golang.org/x/crypto/openpgp/packet

     1  // Copyright 2010 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
     6  
     7  package packet
     8  
     9  import (
    10  	"crypto/cipher"
    11  )
    12  
    13  type ocfbEncrypter struct {
    14  	b       cipher.Block
    15  	fre     []byte
    16  	outUsed int
    17  }
    18  
    19  // An OCFBResyncOption determines if the "resynchronization step" of OCFB is
    20  // performed.
    21  type OCFBResyncOption bool
    22  
    23  const (
    24  	OCFBResync   OCFBResyncOption = true
    25  	OCFBNoResync OCFBResyncOption = false
    26  )
    27  
    28  // NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
    29  // cipher feedback mode using the given cipher.Block, and an initial amount of
    30  // ciphertext.  randData must be random bytes and be the same length as the
    31  // cipher.Block's block size. Resync determines if the "resynchronization step"
    32  // from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
    33  // this point.
    34  func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
    35  	blockSize := block.BlockSize()
    36  	if len(randData) != blockSize {
    37  		return nil, nil
    38  	}
    39  
    40  	x := &ocfbEncrypter{
    41  		b:       block,
    42  		fre:     make([]byte, blockSize),
    43  		outUsed: 0,
    44  	}
    45  	prefix := make([]byte, blockSize+2)
    46  
    47  	block.Encrypt(x.fre, x.fre)
    48  	for i := 0; i < blockSize; i++ {
    49  		prefix[i] = randData[i] ^ x.fre[i]
    50  	}
    51  
    52  	block.Encrypt(x.fre, prefix[:blockSize])
    53  	prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
    54  	prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
    55  
    56  	if resync {
    57  		block.Encrypt(x.fre, prefix[2:])
    58  	} else {
    59  		x.fre[0] = prefix[blockSize]
    60  		x.fre[1] = prefix[blockSize+1]
    61  		x.outUsed = 2
    62  	}
    63  	return x, prefix
    64  }
    65  
    66  func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
    67  	for i := 0; i < len(src); i++ {
    68  		if x.outUsed == len(x.fre) {
    69  			x.b.Encrypt(x.fre, x.fre)
    70  			x.outUsed = 0
    71  		}
    72  
    73  		x.fre[x.outUsed] ^= src[i]
    74  		dst[i] = x.fre[x.outUsed]
    75  		x.outUsed++
    76  	}
    77  }
    78  
    79  type ocfbDecrypter struct {
    80  	b       cipher.Block
    81  	fre     []byte
    82  	outUsed int
    83  }
    84  
    85  // NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
    86  // cipher feedback mode using the given cipher.Block. Prefix must be the first
    87  // blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
    88  // block size. If an incorrect key is detected then nil is returned. On
    89  // successful exit, blockSize+2 bytes of decrypted data are written into
    90  // prefix. Resync determines if the "resynchronization step" from RFC 4880,
    91  // 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
    92  func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
    93  	blockSize := block.BlockSize()
    94  	if len(prefix) != blockSize+2 {
    95  		return nil
    96  	}
    97  
    98  	x := &ocfbDecrypter{
    99  		b:       block,
   100  		fre:     make([]byte, blockSize),
   101  		outUsed: 0,
   102  	}
   103  	prefixCopy := make([]byte, len(prefix))
   104  	copy(prefixCopy, prefix)
   105  
   106  	block.Encrypt(x.fre, x.fre)
   107  	for i := 0; i < blockSize; i++ {
   108  		prefixCopy[i] ^= x.fre[i]
   109  	}
   110  
   111  	block.Encrypt(x.fre, prefix[:blockSize])
   112  	prefixCopy[blockSize] ^= x.fre[0]
   113  	prefixCopy[blockSize+1] ^= x.fre[1]
   114  
   115  	if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
   116  		prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
   117  		return nil
   118  	}
   119  
   120  	if resync {
   121  		block.Encrypt(x.fre, prefix[2:])
   122  	} else {
   123  		x.fre[0] = prefix[blockSize]
   124  		x.fre[1] = prefix[blockSize+1]
   125  		x.outUsed = 2
   126  	}
   127  	copy(prefix, prefixCopy)
   128  	return x
   129  }
   130  
   131  func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
   132  	for i := 0; i < len(src); i++ {
   133  		if x.outUsed == len(x.fre) {
   134  			x.b.Encrypt(x.fre, x.fre)
   135  			x.outUsed = 0
   136  		}
   137  
   138  		c := src[i]
   139  		dst[i] = x.fre[x.outUsed] ^ src[i]
   140  		x.fre[x.outUsed] = c
   141  		x.outUsed++
   142  	}
   143  }
   144  

View as plain text