kunt

golang IRC bot
git clone git://git.2f30.org/kunt
Log | Files | Refs | LICENSE

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 }