snippets

More or less useful code snippets
Log | Files | Refs

simcrypt.go (2044B)


      1 package main
      2 
      3 import (
      4 	"bytes"
      5 	"crypto/aes"
      6 	"crypto/cipher"
      7 	"crypto/rand"
      8 	"crypto/sha256"
      9 	"filippo.io/age"
     10 	"io"
     11 )
     12 
     13 func sha256Sum(password []byte) []byte {
     14 	pwSha := sha256.Sum256(password)
     15 	return pwSha[:]
     16 }
     17 
     18 // Simple password-based encryption functions,
     19 // AES-GCM (faster) and scrypt via `age` (more secure).
     20 
     21 // Symmetric encryption for extra private key protection
     22 func encrypt(plaintext, encryptionKey []byte) ([]byte, error) {
     23 	keyHash := sha256Sum(encryptionKey)
     24 	block, err := aes.NewCipher(keyHash)
     25 	if err != nil {
     26 		return nil, err
     27 	}
     28 	aesgcm, err := cipher.NewGCM(block)
     29 	if err != nil {
     30 		return nil, err
     31 	}
     32 	nonce := make([]byte, aesgcm.NonceSize())
     33 	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
     34 		return nil, err
     35 	}
     36 	ciphertext := aesgcm.Seal(nonce, nonce, []byte(plaintext), nil)
     37 	return ciphertext, nil
     38 }
     39 
     40 func decrypt(cipherbundle, encryptionKey []byte) ([]byte, error) {
     41 	keyHash := sha256Sum(encryptionKey)
     42 	block, err := aes.NewCipher(keyHash)
     43 	if err != nil {
     44 		return nil, err
     45 	}
     46 	aesgcm, err := cipher.NewGCM(block)
     47 	if err != nil {
     48 		return nil, err
     49 	}
     50 	nonce := cipherbundle[:aesgcm.NonceSize()]
     51 	ciphertext := cipherbundle[aesgcm.NonceSize():]
     52 	return aesgcm.Open(nil, nonce, ciphertext, nil)
     53 }
     54 
     55 func ageEncrypt(plain, encryptionKey []byte) ([]byte, error) {
     56 	if len(plain) == 0 {
     57 		return []byte{}, nil
     58 	}
     59 	sr, err := age.NewScryptRecipient(string(encryptionKey))
     60 	if err != nil {
     61 		return nil, err
     62 	}
     63 	var b bytes.Buffer
     64 	ew, err := age.Encrypt(&b, sr)
     65 	if err != nil {
     66 		return nil, err
     67 	}
     68 	_, err = ew.Write(plain)
     69 	if err != nil {
     70 		return nil, err
     71 	}
     72 	err = ew.Close()
     73 	return b.Bytes(), err
     74 }
     75 
     76 func ageDecrypt(cipher, encryptionKey []byte) ([]byte, error) {
     77 	if len(cipher) == 0 {
     78 		return []byte{}, nil
     79 	}
     80 	sr, err := age.NewScryptIdentity(string(encryptionKey))
     81 	if err != nil {
     82 		return nil, err
     83 	}
     84 	var b bytes.Buffer
     85 	ew, err := age.Decrypt(&b, sr)
     86 	if err != nil {
     87 		return nil, err
     88 	}
     89 	_, err = ew.Read(cipher)
     90 	return b.Bytes(), err
     91 }
     92 
     93 func main() {
     94 	// TODO: read args etc...
     95 }