Created
May 31, 2017 07:44
-
-
Save huyinghuan/7bf174017bf54efb91ece04a48589b22 to your computer and use it in GitHub Desktop.
golang encrypt with pkcs5 and pkcs7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"crypto/aes" | |
"crypto/cipher" | |
"crypto/rand" | |
"errors" | |
"io" | |
"io/ioutil" | |
"os" | |
) | |
func encrypt(aeskey string, filename string) { | |
plaintext, err := ioutil.ReadFile(filename) | |
if err != nil { | |
panic(err.Error()) | |
} | |
key := []byte(aeskey) | |
// Create the AES cipher | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
panic(err) | |
} | |
plaintext, _ = pkcs7Pad(plaintext, block.BlockSize()) | |
// The IV needs to be unique, but not secure. Therefore it's common to | |
// include it at the beginning of the ciphertext. | |
ciphertext := make([]byte, aes.BlockSize+len(plaintext)) | |
iv := ciphertext[:aes.BlockSize] | |
if _, err := io.ReadFull(rand.Reader, iv); err != nil { | |
panic(err) | |
} | |
bm := cipher.NewCBCEncrypter(block, iv) | |
bm.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) | |
//stream := cipher.NewCFBEncrypter(block, iv) | |
//stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) | |
// create a new file for saving the encrypted data. | |
f, err := os.Create(filename + ".aes") | |
if err != nil { | |
panic(err.Error()) | |
} | |
_, err = io.Copy(f, bytes.NewReader(ciphertext)) | |
if err != nil { | |
panic(err.Error()) | |
} | |
} | |
func PKCS5Padding(ciphertext []byte, blockSize int) []byte { | |
padding := blockSize - len(ciphertext)%blockSize | |
padtext := bytes.Repeat([]byte{byte(padding)}, padding) | |
return append(ciphertext, padtext...) | |
} | |
func PKCS5Trimming(encrypt []byte) []byte { | |
padding := encrypt[len(encrypt)-1] | |
return encrypt[:len(encrypt)-int(padding)] | |
} | |
func decrypt(aesKey string, inputFile string) { | |
ciphertext, err := ioutil.ReadFile(inputFile) | |
if err != nil { | |
panic(err.Error()) | |
} | |
// Key | |
key := []byte(aesKey) | |
// Create the AES cipher | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
panic(err) | |
} | |
iv := ciphertext[:aes.BlockSize] | |
ciphertext = ciphertext[aes.BlockSize:] | |
bm := cipher.NewCBCDecrypter(block, iv) | |
bm.CryptBlocks(ciphertext, ciphertext) | |
ciphertext, _ = pkcs7Unpad(ciphertext, aes.BlockSize) | |
f, err := os.Create(inputFile + ".ts") | |
if err != nil { | |
panic(err.Error()) | |
} | |
_, err = io.Copy(f, bytes.NewReader(ciphertext)) | |
if err != nil { | |
panic(err.Error()) | |
} | |
} | |
var ( | |
// ErrInvalidBlockSize indicates hash blocksize <= 0. | |
ErrInvalidBlockSize = errors.New("invalid blocksize") | |
// ErrInvalidPKCS7Data indicates bad input to PKCS7 pad or unpad. | |
ErrInvalidPKCS7Data = errors.New("invalid PKCS7 data (empty or not padded)") | |
// ErrInvalidPKCS7Padding indicates PKCS7 unpad fails to bad input. | |
ErrInvalidPKCS7Padding = errors.New("invalid padding on input") | |
) | |
// pkcs7Pad right-pads the given byte slice with 1 to n bytes, where | |
// n is the block size. The size of the result is x times n, where x | |
// is at least 1. | |
func pkcs7Pad(b []byte, blocksize int) ([]byte, error) { | |
if blocksize <= 0 { | |
return nil, ErrInvalidBlockSize | |
} | |
if b == nil || len(b) == 0 { | |
return nil, ErrInvalidPKCS7Data | |
} | |
n := blocksize - (len(b) % blocksize) | |
pb := make([]byte, len(b)+n) | |
copy(pb, b) | |
copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n)) | |
return pb, nil | |
} | |
// pkcs7Unpad validates and unpads data from the given bytes slice. | |
// The returned value will be 1 to n bytes smaller depending on the | |
// amount of padding, where n is the block size. | |
func pkcs7Unpad(b []byte, blocksize int) ([]byte, error) { | |
if blocksize <= 0 { | |
return nil, ErrInvalidBlockSize | |
} | |
if b == nil || len(b) == 0 { | |
return nil, ErrInvalidPKCS7Data | |
} | |
if len(b)%blocksize != 0 { | |
return nil, ErrInvalidPKCS7Padding | |
} | |
c := b[len(b)-1] | |
n := int(c) | |
if n == 0 || n > len(b) { | |
return nil, ErrInvalidPKCS7Padding | |
} | |
for i := 0; i < n; i++ { | |
if b[len(b)-n+i] != c { | |
return nil, ErrInvalidPKCS7Padding | |
} | |
} | |
return b[:len(b)-n], nil | |
} | |
func main() { | |
key := "0123456789123456" | |
encrypt(key, "1.ts") | |
decrypt(key, "1.ts.aes") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment