github.com/rajasrinivasan/spm@v0.0.0-20200125100127-755649755f3f/src/pkg/crypt.go (about)

     1  package pkg
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/aes"
     6  	"crypto/cipher"
     7  	"crypto/rand"
     8  	"crypto/sha256"
     9  	"errors"
    10  	"io"
    11  	"io/ioutil"
    12  	"log"
    13  	"os"
    14  )
    15  
    16  const salt = "How razorback-jumping frogs can level six piqued gymnasts!"
    17  
    18  func generateKey(passphrase string) []byte {
    19  	salted := passphrase + salt
    20  	hash := sha256.New()
    21  	hash.Write([]byte(salted))
    22  	return hash.Sum(nil)
    23  }
    24  
    25  func generateInitVector() []byte {
    26  	iv := make([]byte, aes.BlockSize)
    27  	_, err := rand.Read(iv)
    28  	if err != nil {
    29  		log.Printf("%s\n", err)
    30  	}
    31  	if Verbose {
    32  		log.Printf("IV: %x\n", iv)
    33  	}
    34  	return iv
    35  }
    36  
    37  func Encrypt(passphrase string, from string, to string) error {
    38  	log.Printf("Encrypt from: %s to %s passphrase %s\n", from, to, passphrase)
    39  
    40  	ofile, err := os.Create(to)
    41  	if err != nil {
    42  		log.Fatal(err)
    43  	}
    44  	defer ofile.Close()
    45  
    46  	ifile, err := os.Open(from)
    47  	if err != nil {
    48  		log.Fatal(err)
    49  	}
    50  	defer ifile.Close()
    51  
    52  	secret := generateKey(passphrase)
    53  	encalg, err := aes.NewCipher(secret)
    54  	if err != nil {
    55  		log.Printf("%s\n", err)
    56  		return err
    57  	}
    58  
    59  	iv := generateInitVector()
    60  
    61  	ofile.Write(secret)
    62  	ofile.Write(iv)
    63  
    64  	str := cipher.NewOFB(encalg, iv)
    65  
    66  	idata, _ := ioutil.ReadAll(ifile)
    67  	odata := make([]byte, len(idata))
    68  	str.XORKeyStream(odata, idata)
    69  
    70  	ofile.Write(odata)
    71  
    72  	return nil
    73  }
    74  
    75  func Decrypt(passphrase string, from string, to string) error {
    76  	log.Printf("Decrypt from: %s to %s passphrase %s\n", from, to, passphrase)
    77  
    78  	ofile, err := os.Create(to)
    79  	if err != nil {
    80  		log.Fatal(err)
    81  	}
    82  	defer ofile.Close()
    83  
    84  	ifile, err := os.Open(from)
    85  	if err != nil {
    86  		log.Fatal(err)
    87  	}
    88  	defer ifile.Close()
    89  
    90  	secret := generateKey(passphrase)
    91  	filepass := make([]byte, len(secret))
    92  	bytesin, err := io.ReadFull(ifile, filepass)
    93  	if err != nil {
    94  		log.Fatal(err)
    95  	}
    96  	if Verbose {
    97  		log.Printf("%d bytes read for password\n", bytesin)
    98  	}
    99  	res := bytes.Compare(secret, filepass)
   100  	if res != 0 {
   101  		log.Printf("Passphrase comparison failed\n")
   102  		return errors.New("Passphrase comparison failed")
   103  	}
   104  
   105  	iv := make([]byte, aes.BlockSize)
   106  	bytesin, err = io.ReadFull(ifile, iv)
   107  	if err != nil {
   108  		log.Fatal(err)
   109  	}
   110  	if Verbose {
   111  		log.Printf("%d bytes read for IV\n", bytesin)
   112  		log.Printf("IV: %x\n", iv)
   113  	}
   114  	encalg, err := aes.NewCipher(filepass)
   115  	if err != nil {
   116  		log.Printf("%s\n", err)
   117  		return err
   118  	}
   119  	st, _ := os.Stat(from)
   120  	buf := make([]byte, int(st.Size())-len(secret)-len(iv))
   121  	nbytesin, err := io.ReadFull(ifile, buf)
   122  	if err != nil {
   123  		log.Fatal(err)
   124  	}
   125  	if Verbose {
   126  		log.Printf("%d bytes read\n", nbytesin)
   127  	}
   128  	obuf := make([]byte, len(buf))
   129  
   130  	str := cipher.NewOFB(encalg, iv)
   131  	str.XORKeyStream(obuf, buf)
   132  
   133  	nbytesout, err := ofile.Write(obuf)
   134  	if err != nil {
   135  		log.Fatal(err)
   136  	}
   137  	if Verbose {
   138  		log.Printf("%d bytes written\n", nbytesout)
   139  	}
   140  	ofile.Close()
   141  	return nil
   142  }