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.
5
// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
13
type ocfbEncrypter struct {
19
// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
21
type OCFBResyncOption bool
24
OCFBResync OCFBResyncOption = true
25
OCFBNoResync OCFBResyncOption = false
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
34
func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
35
blockSize := block.BlockSize()
36
if len(randData) != blockSize {
42
fre: make([]byte, blockSize),
45
prefix := make([]byte, blockSize+2)
47
block.Encrypt(x.fre, x.fre)
48
for i := 0; i < blockSize; i++ {
49
prefix[i] = randData[i] ^ x.fre[i]
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]
57
block.Encrypt(x.fre, prefix[2:])
59
x.fre[0] = prefix[blockSize]
60
x.fre[1] = prefix[blockSize+1]
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)
73
x.fre[x.outUsed] ^= src[i]
74
dst[i] = x.fre[x.outUsed]
79
type ocfbDecrypter struct {
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 {
100
fre: make([]byte, blockSize),
103
prefixCopy := make([]byte, len(prefix))
104
copy(prefixCopy, prefix)
106
block.Encrypt(x.fre, x.fre)
107
for i := 0; i < blockSize; i++ {
108
prefixCopy[i] ^= x.fre[i]
111
block.Encrypt(x.fre, prefix[:blockSize])
112
prefixCopy[blockSize] ^= x.fre[0]
113
prefixCopy[blockSize+1] ^= x.fre[1]
115
if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
116
prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
121
block.Encrypt(x.fre, prefix[2:])
123
x.fre[0] = prefix[blockSize]
124
x.fre[1] = prefix[blockSize+1]
127
copy(prefix, prefixCopy)
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)
139
dst[i] = x.fre[x.outUsed] ^ src[i]