|
|
- package Seeder
-
- // THIS FILE IS ONLY USED FOR SEEDING DATA DURING DEVELOPMENT
-
- import (
- "bytes"
- "crypto/aes"
- "crypto/cipher"
- "crypto/hmac"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha256"
- "encoding/base64"
- "fmt"
- "hash"
-
- "golang.org/x/crypto/pbkdf2"
- )
-
- type aesKey struct {
- Key []byte
- Iv []byte
- }
-
- func (key aesKey) encode() string {
- return base64.StdEncoding.EncodeToString(key.Key)
- }
-
- // Appends padding.
- func pkcs7Padding(data []byte, blocklen int) ([]byte, error) {
- var (
- padlen int = 1
- pad []byte
- )
- if blocklen <= 0 {
- return nil, fmt.Errorf("invalid blocklen %d", blocklen)
- }
-
- for ((len(data) + padlen) % blocklen) != 0 {
- padlen = padlen + 1
- }
-
- pad = bytes.Repeat([]byte{byte(padlen)}, padlen)
- return append(data, pad...), nil
- }
-
- // pkcs7strip remove pkcs7 padding
- func pkcs7strip(data []byte, blockSize int) ([]byte, error) {
- var (
- length int
- padLen int
- ref []byte
- )
-
- length = len(data)
- if length == 0 {
- return nil, fmt.Errorf("pkcs7: Data is empty")
- }
-
- if (length % blockSize) != 0 {
- return nil, fmt.Errorf("pkcs7: Data is not block-aligned")
- }
-
- padLen = int(data[length-1])
- ref = bytes.Repeat([]byte{byte(padLen)}, padLen)
-
- if padLen > blockSize || padLen == 0 || !bytes.HasSuffix(data, ref) {
- return nil, fmt.Errorf("pkcs7: Invalid padding")
- }
-
- return data[:length-padLen], nil
- }
-
- func GenerateAesKey() (aesKey, error) {
- var (
- saltBytes []byte = []byte{}
- password []byte
- seed []byte
- iv []byte
- err error
- )
-
- password = make([]byte, 64)
- _, err = rand.Read(password)
- if err != nil {
- return aesKey{}, err
- }
-
- seed = make([]byte, 64)
- _, err = rand.Read(seed)
- if err != nil {
- return aesKey{}, err
- }
-
- iv = make([]byte, 16)
- _, err = rand.Read(iv)
- if err != nil {
- return aesKey{}, err
- }
-
- return aesKey{
- Key: pbkdf2.Key(
- password,
- saltBytes,
- 1000,
- 32,
- func() hash.Hash { return hmac.New(sha256.New, seed) },
- ),
- Iv: iv,
- }, nil
- }
-
- func (key aesKey) AesEncrypt(plaintext []byte) ([]byte, error) {
- var (
- bPlaintext []byte
- ciphertext []byte
- block cipher.Block
- err error
- )
-
- bPlaintext, err = pkcs7Padding(plaintext, 16)
-
- block, err = aes.NewCipher(key.Key)
- if err != nil {
- return []byte{}, err
- }
-
- ciphertext = make([]byte, len(bPlaintext))
- mode := cipher.NewCBCEncrypter(block, key.Iv)
- mode.CryptBlocks(ciphertext, bPlaintext)
-
- ciphertext = append(key.Iv, ciphertext...)
-
- return ciphertext, nil
- }
-
- func (key aesKey) AesDecrypt(ciphertext []byte) ([]byte, error) {
- var (
- plaintext []byte
- iv []byte
- block cipher.Block
- err error
- )
-
- iv = ciphertext[:aes.BlockSize]
- plaintext = ciphertext[aes.BlockSize:]
-
- block, err = aes.NewCipher(key.Key)
- if err != nil {
- return []byte{}, err
- }
-
- decMode := cipher.NewCBCDecrypter(block, iv)
- decMode.CryptBlocks(plaintext, plaintext)
-
- return plaintext, nil
- }
-
- // EncryptWithPublicKey encrypts data with public key
- func EncryptWithPublicKey(msg []byte, pub *rsa.PublicKey) []byte {
- var (
- hash hash.Hash
- )
-
- hash = sha256.New()
- ciphertext, err := rsa.EncryptOAEP(hash, rand.Reader, pub, msg, nil)
- if err != nil {
- panic(err)
- }
- return ciphertext
- }
-
- // DecryptWithPrivateKey decrypts data with private key
- func decryptWithPrivateKey(ciphertext []byte, priv *rsa.PrivateKey) ([]byte, error) {
- var (
- hash hash.Hash
- plaintext []byte
- err error
- )
-
- hash = sha256.New()
-
- plaintext, err = rsa.DecryptOAEP(hash, rand.Reader, priv, ciphertext, nil)
- if err != nil {
- return plaintext, err
- }
- return plaintext, nil
- }
|