OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / openpgp / packet / ocfb.go
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 }