Last active
August 4, 2023 09:04
-
-
Save sunary/a9edeea337450040769253de1e4eae08 to your computer and use it in GitHub Desktop.
aes256 CBC & CFB
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" | |
"crypto/sha256" | |
"encoding/base64" | |
"errors" | |
"fmt" | |
"io" | |
"strings" | |
"golang.org/x/crypto/pbkdf2" | |
) | |
const BlockSize = 32 | |
func deriveKey(passphrase string, salt []byte) []byte { | |
// http://www.ietf.org/rfc/rfc2898.txt | |
if salt == nil { | |
salt = make([]byte, 8) | |
// rand.Read(salt) | |
} | |
return pbkdf2.Key([]byte(passphrase), salt, 1000, BlockSize, sha256.New) | |
} | |
func addBase64Padding(value string) string { | |
m := len(value) % 4 | |
if m != 0 { | |
value += strings.Repeat("=", 4-m) | |
} | |
return value | |
} | |
func removeBase64Padding(value string) string { | |
return strings.Replace(value, "=", "", -1) | |
} | |
func Pad(src []byte) []byte { | |
padding := aes.BlockSize - len(src)%aes.BlockSize | |
padtext := bytes.Repeat([]byte{byte(padding)}, padding) | |
return append(src, padtext...) | |
} | |
func Unpad(src []byte) ([]byte, error) { | |
length := len(src) | |
unpadding := int(src[length-1]) | |
if unpadding > length { | |
return nil, errors.New("unpad error. This could happen when incorrect encryption key is used") | |
} | |
return src[:(length - unpadding)], nil | |
} | |
func encrypt(key []byte, text string) (string, error) { | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
return "", err | |
} | |
msg := Pad([]byte(text)) | |
ciphertext := make([]byte, aes.BlockSize+len(msg)) | |
iv := ciphertext[:aes.BlockSize] | |
if _, err := io.ReadFull(rand.Reader, iv); err != nil { | |
return "", err | |
} | |
// cfb := cipher.NewCFBEncrypter(block, iv) | |
// cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(msg)) | |
cbc := cipher.NewCBCEncrypter(block, iv) | |
cbc.CryptBlocks(ciphertext[aes.BlockSize:], []byte(msg)) | |
finalMsg := removeBase64Padding(base64.URLEncoding.EncodeToString(ciphertext)) | |
return finalMsg, nil | |
} | |
func decrypt(key []byte, text string) (string, error) { | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
return "", err | |
} | |
decodedMsg, err := base64.URLEncoding.DecodeString(addBase64Padding(text)) | |
if err != nil { | |
return "", err | |
} | |
if (len(decodedMsg) % aes.BlockSize) != 0 { | |
return "", errors.New("blocksize must be multipe of decoded message length") | |
} | |
iv := decodedMsg[:aes.BlockSize] | |
msg := decodedMsg[aes.BlockSize:] | |
// cfb := cipher.NewCFBDecrypter(block, iv) | |
// cfb.XORKeyStream(msg, msg) | |
cbc := cipher.NewCBCDecrypter(block, iv) | |
cbc.CryptBlocks(msg, msg) | |
unpadMsg, err := Unpad(msg) | |
if err != nil { | |
return "", err | |
} | |
return string(unpadMsg), nil | |
} | |
func main() { | |
key := deriveKey("password", []byte("salt")) | |
encryptMsg, _ := encrypt(key, "Hello World") | |
fmt.Println(encryptMsg) | |
msg, _ := decrypt(key, encryptMsg) | |
fmt.Println(msg) | |
} |
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
using System; | |
using System.IO; | |
using System.Text; | |
using System.Security.Cryptography; | |
public class rfc2898test | |
{ | |
const string saltStr = "pjico@)!^"; | |
const string password = "pjico@2020"; | |
public static string EncryptString(string text) | |
{ | |
try | |
{ | |
byte[] baPwd = Encoding.UTF8.GetBytes(password); | |
// Hash the password with SHA256 | |
byte[] baPwdHash = SHA256Managed.Create().ComputeHash(baPwd); | |
byte[] baText = Encoding.UTF8.GetBytes(text); | |
var baEncrypted = AES_Encrypt(baText, baPwdHash); | |
string result = Convert.ToBase64String(baEncrypted); | |
return result; | |
} | |
catch (Exception ex) | |
{ | |
return string.Empty; | |
} | |
} | |
private static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes) | |
{ | |
byte[] encryptedBytes = null; | |
// Set your salt here, change it to meet your flavor: | |
// The salt bytes must be at least 8 bytes. | |
byte[] saltBytes = Encoding.UTF8.GetBytes(saltStr); | |
using (MemoryStream ms = new MemoryStream()) | |
{ | |
using (RijndaelManaged AES = new RijndaelManaged()) | |
{ | |
AES.KeySize = 256; | |
AES.BlockSize = 128; | |
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); | |
AES.Key = key.GetBytes(AES.KeySize / 8); | |
AES.IV = key.GetBytes(AES.BlockSize / 8); | |
AES.Mode = CipherMode.CBC; | |
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write)) | |
{ | |
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length); | |
cs.Close(); | |
} | |
encryptedBytes = ms.ToArray(); | |
} | |
} | |
return encryptedBytes; | |
} | |
public static string DecryptString(string text) | |
{ | |
try | |
{ | |
byte[] baPwd = Encoding.UTF8.GetBytes(password); | |
// Hash the password with SHA256 | |
byte[] baPwdHash = SHA256Managed.Create().ComputeHash(baPwd); | |
byte[] baText = Convert.FromBase64String(text); | |
byte[] baDecrypted = AES_Decrypt(baText, baPwdHash); | |
string result = Encoding.UTF8.GetString(baDecrypted); | |
return result; | |
} | |
catch (Exception ex) | |
{ | |
return string.Empty; | |
} | |
} | |
private static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes) | |
{ | |
byte[] decryptedBytes = null; | |
// Set your salt here, change it to meet your flavor: | |
// The salt bytes must be at least 8 bytes. | |
byte[] saltBytes = Encoding.UTF8.GetBytes(saltStr); | |
using (MemoryStream ms = new MemoryStream()) | |
{ | |
using (RijndaelManaged AES = new RijndaelManaged()) | |
{ | |
AES.KeySize = 256; | |
AES.BlockSize = 128; | |
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); | |
AES.Key = key.GetBytes(AES.KeySize / 8); | |
AES.IV = key.GetBytes(AES.BlockSize / 8); | |
Console.WriteLine("key: {0}", Convert.ToBase64String(AES.Key)); | |
Console.WriteLine("IV: {0}", Convert.ToBase64String(AES.IV)); | |
AES.Padding = PaddingMode.None; | |
//AES.Padding = PaddingMode.Zeros; | |
AES.Mode = CipherMode.CBC; | |
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write)) | |
{ | |
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length); | |
cs.Close(); | |
} | |
decryptedBytes = ms.ToArray(); | |
} | |
} | |
return decryptedBytes; | |
} | |
public static void Main() | |
{ | |
string enc = EncryptString("Hello World"); | |
Console.WriteLine(enc); | |
Console.WriteLine(DecryptString(enc)); | |
} | |
} | |
// run at: https://dotnetfiddle.net/ |
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/sha256" | |
"encoding/base64" | |
"errors" | |
"fmt" | |
"strings" | |
"golang.org/x/crypto/pbkdf2" | |
) | |
const ( | |
pw = "pjico@2020" | |
st = "pjico@)!^" | |
) | |
func deriveKey(passphrase string, salt []byte, l int) []byte { | |
// http://www.ietf.org/rfc/rfc2898.txt | |
if salt == nil { | |
salt = make([]byte, 8) | |
// rand.Read(salt) | |
} | |
return pbkdf2.Key([]byte(passphrase), salt, 1000, l, sha256.New) | |
} | |
func addBase64Padding(value string) string { | |
m := len(value) % 4 | |
if m != 0 { | |
value += strings.Repeat("=", 4-m) | |
} | |
return value | |
} | |
func Pad(src []byte) []byte { | |
padding := aes.BlockSize - len(src)%aes.BlockSize | |
padtext := bytes.Repeat([]byte{byte(padding)}, padding) | |
return append(src, padtext...) | |
} | |
func Unpad(src []byte) ([]byte, error) { | |
length := len(src) | |
if length == 0 { | |
return nil, errors.New("Emtpy src") | |
} | |
unpadding := int(src[length-1]) | |
if unpadding > length { | |
return nil, errors.New("unpad error. This could happen when incorrect encryption key is used") | |
} | |
return src[:(length - unpadding)], nil | |
} | |
func encrypt(text string) (string, error) { | |
key := deriveKey(pw, []byte(st), 32) | |
iv := deriveKey(pw, []byte(st), 16) | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
return "", err | |
} | |
msg := Pad([]byte(text)) | |
ciphertext := make([]byte, len(msg)) | |
// cfb := cipher.NewCFBEncrypter(block, iv) | |
// cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(msg)) | |
cbc := cipher.NewCBCEncrypter(block, iv) | |
cbc.CryptBlocks(ciphertext, []byte(msg)) | |
finalMsg := base64.StdEncoding.EncodeToString(ciphertext) | |
return finalMsg, nil | |
} | |
func decrypt(text string) (string, error) { | |
key := deriveKey(pw, []byte(st), 32) | |
iv := deriveKey(pw, []byte(st), 16) | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
return "", err | |
} | |
decodedMsg, err := base64.StdEncoding.DecodeString(addBase64Padding(text)) | |
if err != nil { | |
return "", err | |
} | |
if (len(decodedMsg) % aes.BlockSize) != 0 { | |
return "", errors.New("blocksize must be multipe of decoded message length") | |
} | |
msg := decodedMsg | |
// cfb := cipher.NewCFBDecrypter(block, iv) | |
// cfb.XORKeyStream(msg, msg) | |
cbc := cipher.NewCBCDecrypter(block, iv) | |
cbc.CryptBlocks(msg, msg) | |
unpadMsg, err := Unpad(msg) | |
if err != nil { | |
return "", err | |
} | |
return string(unpadMsg), nil | |
} | |
func decryptWithKey(text, kk, ii string) (string, error) { | |
key, _ := base64.StdEncoding.DecodeString(addBase64Padding(kk)) | |
iv, _ := base64.StdEncoding.DecodeString(addBase64Padding(ii)) | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
return "", err | |
} | |
decodedMsg, err := base64.StdEncoding.DecodeString(addBase64Padding(text)) | |
if err != nil { | |
return "", err | |
} | |
if (len(decodedMsg) % aes.BlockSize) != 0 { | |
return "", errors.New("blocksize must be multipe of decoded message length") | |
} | |
msg := decodedMsg | |
// cfb := cipher.NewCFBDecrypter(block, iv) | |
// cfb.XORKeyStream(msg, msg) | |
cbc := cipher.NewCBCDecrypter(block, iv) | |
cbc.CryptBlocks(msg, msg) | |
unpadMsg, err := Unpad(msg) | |
if err != nil { | |
return "", err | |
} | |
return string(unpadMsg), nil | |
} | |
func main() { | |
encryptMsg, _ := encrypt("Hello World") | |
fmt.Println(encryptMsg) | |
msg, err := decrypt(encryptMsg) | |
if err != nil { | |
fmt.Printf("1 decrypt err: %s\n", err.Error()) | |
} | |
fmt.Println(msg) | |
sampleKey := "5/3J1iJsIaTtqJ1OrNYf4I9lBNqn4eL8+CKbFK2DkuQ=" | |
sampleIV := "YPfPbCE2hV1iTZJLqq3H+w==" | |
desMsg := "S0UyKrmw4YO+zhGs4b//nA==" | |
fmt.Println(desMsg) | |
msg, err = decryptWithKey(desMsg, sampleKey, sampleIV) | |
if err != nil { | |
fmt.Printf("2 decrypt err: %s\n", err.Error()) | |
} | |
fmt.Println(msg) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment