blowfish.go (3493B)
1 // Copyright 2013 TLH and dsp. 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 package mapfs 6 7 import ( 8 "bufio" 9 "bytes" 10 "code.google.com/p/go.crypto/blowfish" 11 "encoding/gob" 12 "fmt" 13 "io" 14 "log" 15 "os" 16 ) 17 18 type BlowfishMap struct { 19 cache map[int]blowfishVal 20 cipher *blowfish.Cipher 21 } 22 23 type blowfishVal struct { 24 dirty bool 25 buf []byte // Actual encrypted data 26 siz int // Length of decrypted data 27 } 28 29 type hdr struct { 30 Magic string 31 Len int 32 Data []byte 33 } 34 35 func NewBlowfishMap(key string) *BlowfishMap { 36 c, err := blowfish.NewCipher([]byte(key)) 37 if err != nil { 38 log.Fatal(err) 39 } 40 return &BlowfishMap{ 41 cache: make(map[int]blowfishVal), 42 cipher: c, 43 } 44 } 45 46 func (b *BlowfishMap) rawRead(path string) ([]byte, error) { 47 fi, err := os.Open(path) 48 if err != nil { 49 return nil, err 50 } 51 defer fi.Close() 52 r := bufio.NewReader(fi) 53 g := gob.NewDecoder(r) 54 h := new(hdr) 55 err = g.Decode(h) 56 if err != nil { 57 if err != io.EOF { 58 return nil, err 59 } 60 } 61 pt := b.decryptBuf(h.Data) 62 return pt[0:h.Len], nil 63 } 64 65 func (b *BlowfishMap) rawWrite(path string, buf []byte) error { 66 fo, err := os.Create(path) 67 if err != nil { 68 return err 69 } 70 defer fo.Close() 71 ct := b.encryptBuf(buf) 72 w := bufio.NewWriter(fo) 73 h := &hdr{"BENC", len(buf), ct} 74 g := gob.NewEncoder(w) 75 err = g.Encode(*h) 76 if err != nil { 77 return err 78 } 79 err = w.Flush() 80 if err != nil { 81 return err 82 } 83 return nil 84 } 85 86 func (b *BlowfishMap) get(key int) ([]byte, error) { 87 val, ok := b.cache[key] 88 if !ok { 89 return nil, fmt.Errorf("No entry with key: %d", key) 90 } 91 return val.buf, nil 92 } 93 94 func (b *BlowfishMap) put(key int, buf []byte) error { 95 _, ok := b.cache[key] 96 if ok { 97 return fmt.Errorf("Key %d already in use", key) 98 } 99 b.cache[key] = blowfishVal{true, buf, len(buf)} 100 return nil 101 } 102 103 func (b *BlowfishMap) add(buf []byte) (int, error) { 104 key := len(b.cache) 105 b.cache[key] = blowfishVal{true, buf, len(buf)} 106 return key, nil 107 } 108 109 func (b *BlowfishMap) countMatches(buf []byte) int { 110 i := 0 111 for _, v := range b.cache { 112 if bytes.Equal(v.buf, buf) { 113 i++ 114 } 115 } 116 return i 117 } 118 119 func (b *BlowfishMap) virtSync() error { 120 for k, v := range b.cache { 121 b.cache[k] = blowfishVal{false, v.buf, v.siz} 122 } 123 return nil 124 } 125 126 func (b *BlowfishMap) syncEntry(path string, key int) error { 127 val, ok := b.cache[key] 128 if !ok { 129 return fmt.Errorf("No entry with key: %d", key) 130 } 131 if val.dirty { 132 b.rawWrite(path, val.buf) 133 } 134 return nil 135 } 136 137 func (b *BlowfishMap) size() int { 138 return len(b.cache) 139 } 140 141 func (b *BlowfishMap) string() string { 142 s := "" 143 for k, v := range b.cache { 144 dirty := "" 145 if v.dirty { 146 dirty = "yes" 147 } else { 148 dirty = "no" 149 } 150 s += fmt.Sprintf("k: %d - dirty: %s\n", 151 k, dirty) 152 } 153 return s 154 } 155 156 func (b *BlowfishMap) encryptBuf(a []byte) []byte { 157 padded := a 158 diff := len(a) % blowfish.BlockSize 159 if diff != 0 { 160 diff = blowfish.BlockSize - diff 161 } 162 for i := 0; i < diff; i++ { 163 padded = append(padded, byte(0x0)) 164 } 165 ct := make([]byte, len(padded)) 166 for i := 0; i < len(a); i += blowfish.BlockSize { 167 if i+blowfish.BlockSize > len(a) { 168 b.cipher.Encrypt(ct[i:], padded[i:]) 169 return ct 170 } 171 b.cipher.Encrypt(ct[i:i+blowfish.BlockSize], 172 padded[i:i+blowfish.BlockSize]) 173 } 174 return ct 175 } 176 177 func (b *BlowfishMap) decryptBuf(a []byte) []byte { 178 pt := make([]byte, len(a)) 179 for i := 0; i < len(a); i += blowfish.BlockSize { 180 b.cipher.Decrypt(pt[i:i+blowfish.BlockSize], 181 a[i:i+blowfish.BlockSize]) 182 } 183 return pt 184 }