-
-
Save willshiao/f4b03650e5a82561a460b4a15789cfa1 to your computer and use it in GitHub Desktop.
package main | |
import ( | |
"crypto/aes" | |
"crypto/cipher" | |
"crypto/rand" | |
"crypto/sha256" | |
"encoding/base64" | |
"fmt" | |
"io" | |
) | |
func keyEncrypt(keyStr string, cryptoText string) string { | |
keyBytes := sha256.Sum256([]byte(keyStr)) | |
return encrypt(keyBytes[:], cryptoText) | |
} | |
// encrypt string to base64 crypto using AES | |
func encrypt(key []byte, text string) string { | |
plaintext := []byte(text) | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
panic(err) | |
} | |
// 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) | |
} | |
stream := cipher.NewCFBEncrypter(block, iv) | |
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) | |
return base64.StdEncoding.EncodeToString(ciphertext) | |
} | |
func keyDecrypt(keyStr string, cryptoText string) string { | |
keyBytes := sha256.Sum256([]byte(keyStr)) | |
return decrypt(keyBytes[:], cryptoText) | |
} | |
// decrypt from base64 to decrypted string | |
func decrypt(key []byte, cryptoText string) string { | |
ciphertext, err := base64.StdEncoding.DecodeString(cryptoText) | |
if err != nil { | |
panic(err) | |
} | |
block, err := aes.NewCipher(key) | |
if err != nil { | |
panic(err) | |
} | |
// The IV needs to be unique, but not secure. Therefore it's common to | |
// include it at the beginning of the ciphertext. | |
if len(ciphertext) < aes.BlockSize { | |
panic("ciphertext too short") | |
} | |
iv := ciphertext[:aes.BlockSize] | |
ciphertext = ciphertext[aes.BlockSize:] | |
stream := cipher.NewCFBDecrypter(block, iv) | |
// XORKeyStream can work in-place if the two arguments are the same. | |
stream.XORKeyStream(ciphertext, ciphertext) | |
return fmt.Sprintf("%s", ciphertext) | |
} | |
func main() { | |
encrypted := "lIR3JIHpomC5Zm8sjy29D/xFcXUX0c/4vQ==" | |
fmt.Println(encrypted) | |
fmt.Println(keyDecrypt("SecretKey", encrypted)) | |
} |
'use strict'; | |
const crypto = require('crypto'); | |
const algorithm = 'aes-256-cfb'; | |
function encryptText(keyStr, text) { | |
const hash = crypto.createHash('sha256'); | |
hash.update(keyStr); | |
const keyBytes = hash.digest(); | |
const iv = crypto.randomBytes(16); | |
const cipher = crypto.createCipheriv(algorithm, keyBytes, iv); | |
console.log('IV:', iv); | |
let enc = [iv, cipher.update(text, 'utf8')]; | |
enc.push(cipher.final()); | |
return Buffer.concat(enc).toString('base64'); | |
} | |
function decryptText(keyStr, text) { | |
const hash = crypto.createHash('sha256'); | |
hash.update(keyStr); | |
const keyBytes = hash.digest(); | |
const contents = Buffer.from(text, 'base64'); | |
const iv = contents.slice(0, 16); | |
const textBytes = contents.slice(16); | |
const decipher = crypto.createDecipheriv(algorithm, keyBytes, iv); | |
let res = decipher.update(textBytes, '', 'utf8'); | |
res += decipher.final('utf8'); | |
return res; | |
} | |
const encrypted = encryptText('SecretKey', 'It works!'); | |
console.log('Encrypted: ', encrypted); | |
const decrypted = decryptText('SecretKey', encrypted); | |
console.log('Decrypted: ', decrypted); |
import base64 | |
import hashlib | |
from Crypto.Cipher import AES | |
from Crypto import Random | |
def encrypt(keyStr, text): | |
private_key = hashlib.sha256(keyStr.encode()).digest() | |
rem = len(text) % 16 | |
padded = str.encode(text) + (b'\0' * (16 - rem)) if rem > 0 else str.encode(text) | |
iv = Random.new().read(AES.block_size) | |
cipher = AES.new(private_key, AES.MODE_CFB, iv, segment_size=128) | |
enc = cipher.encrypt(padded)[:len(text)] | |
return base64.b64encode(iv + enc).decode() | |
def decrypt(keyStr, text): | |
private_key = hashlib.sha256(keyStr.encode()).digest() | |
text = base64.b64decode(text) | |
iv, value = text[:16], text[16:] | |
rem = len(value) % 16 | |
padded = value + (b'\0' * (16 - rem)) if rem > 0 else value | |
cipher = AES.new(private_key, AES.MODE_CFB, iv, segment_size=128) | |
return (cipher.decrypt(padded)[:len(value)]).decode() | |
def main(): | |
encrypted = 'lIR3JIHpomC5Zm8sjy29D/xFcXUX0c/4vQ==' | |
print(encrypted) | |
print(decrypt('SecretKey', encrypted)) | |
if __name__== '__main__': | |
main() |
Hey, Thanks a lot for this. Can we have a solution for python also. What i need is a way of encryption which I can decrypt using python, go and node all.
+1. It would be great to have for all languages so you can use in many different apps
Hey, Thanks a lot for this. Can we have a solution for python also. What i need is a way of encryption which I can decrypt using python, go and node all.
Added a compatible Python implementation.
Line 10 of aes.py should be padded = str.encode(text) + (b'\0' * (16 - rem)) if rem > 0 else str.encode(text)
.
Line 10 of aes.py should be
padded = str.encode(text) + (b'\0' * (16 - rem)) if rem > 0 else str.encode(text)
.
You are correct. I just edited the implementation above to include this change.
Thanks a lot for this.
Thank a lot for this program 😇😇
Thanks for this, you seems to be the only one knowing what you are doing on internet about crypting stuff
but if we decrypt with invalid cipher in nodejs return look like this value. ,{!�ߺ`�KQ��mh�
So how do I make sure it's a invalid cipher text ? because both success and failed scenarios return a string
with JAVA
i use the lib : implementation('commons-codec:commons-codec:1.15')
other,You can change hex encoding to base64 encoding
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Arrays;
public class AesUtil {
static String key = "SecretKey";
private static byte[] decrypt(byte[] payload, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, InvalidKeyException {
SecretKeySpec key_spec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
int block_size = cipher.getBlockSize();
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(payload, block_size));
byte[] decryption_data = Arrays.copyOfRange(payload, block_size, payload.length);
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
return cipher.doFinal(decryption_data);
}
public static String decrypt(String payload) {
try {
byte[] decrypt = new byte[0];
try {
decrypt = decrypt(Hex.decodeHex(payload), sha256(key));
} catch (DecoderException e) {
e.printStackTrace();
}
return new String(decrypt);
} catch (NoSuchPaddingException | NoSuchAlgorithmException | IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException | InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
private static byte[] encrypt(byte[] encoded_payload, byte[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, ShortBufferException {
SecureRandom rand = new SecureRandom();
SecretKeySpec key_spec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
int block_size = cipher.getBlockSize();
byte[] buffer = new byte[block_size];
rand.nextBytes(buffer);
IvParameterSpec iv = new IvParameterSpec(buffer);
buffer = Arrays.copyOf(buffer, block_size + encoded_payload.length);
cipher.init(Cipher.ENCRYPT_MODE, key_spec, iv);
cipher.doFinal(encoded_payload, 0, encoded_payload.length, buffer, block_size);
return buffer;
}
public static String encrypt(String text) {
try {
byte[] encrypted = encrypt(text.getBytes(StandardCharsets.UTF_8), sha256(key));
return Hex.encodeHexString(encrypted);
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (ShortBufferException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
//String encrypted = encrypt("123345");
String decrypt = decrypt("25ae775850d949f1d6b1161180d23c10e4f5646e2635b8d7cd");
System.out.println(decrypt);
}
public static byte[] sha256(String value) {
if (value == null || value.length() == 0) {
return null;
}
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("sha-256");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte[] buffer = value.getBytes(StandardCharsets.UTF_8);
buffer = messageDigest.digest(buffer);
return buffer;
}
}
Thanks a lot! I had to do both encryption and decryption with js and python, and this code was very helpful.
Only one point needed to be fixed in the py code.
enc = cipher.encrypt(padded)[:len(text)]
change to
enc = cipher.encrypt(padded)[:len(str.encode(text)]
By changing this, multi-byte characters can be properly encrypted and decrypted.
this is how to do it with crypto-js
. Very painful for me to find it our
import CryptoJS from 'crypto-js';
export function encryptText(keyStr, text) {
const private_key = CryptoJS.SHA256(keyStr).toString(CryptoJS.enc.Latin1);
const rem = text.length % 16;
const padded = CryptoJS.enc.Latin1.parse(text.padEnd(text.length + (16 - rem), '\0'));
const iv = CryptoJS.lib.WordArray.random(16);
const cipher = CryptoJS.AES.encrypt(padded, CryptoJS.enc.Latin1.parse(private_key), {
iv: iv,
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.NoPadding,
segmentSize: 128,
});
const ciphertext = iv.concat(cipher.ciphertext);
return ciphertext.toString(CryptoJS.enc.Base64);
}
export const decryptText = (keyStr, text) => {
const private_key = CryptoJS.SHA256(keyStr).toString(CryptoJS.enc.Latin1);
const encrypted = CryptoJS.enc.Base64.parse(text);
const iv = encrypted.clone().words.slice(0, 4);
const ciphertext = encrypted.clone().words.slice(4);
const cipherParams = {
ciphertext: CryptoJS.lib.WordArray.create(ciphertext),
};
const decrypted = CryptoJS.AES.decrypt(cipherParams, CryptoJS.enc.Latin1.parse(private_key), {
iv: CryptoJS.lib.WordArray.create(iv),
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.ZeroPadding,
segmentSize: 128,
});
const decryptedText = CryptoJS.enc.Utf8.stringify(decrypted);
return decryptedText;
};
How can i write this in python?
function encryptAES(plaintext, key, iv) {
var keyUtf8 = CryptoJS.enc.Utf8.parse(key);
var encrypted = CryptoJS.AES.encrypt(plaintext, keyUtf8, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return iv.concat(encrypted.ciphertext).toString(CryptoJS.enc.Base64);
};
var iv1 = CryptoJS.lib.WordArray.random(16);
var iv2 = CryptoJS.lib.WordArray.random(16);
iv1.words[0] &= 0xFF00FFFF;
iv2.words[0] &= 0xFF00FFFF;
loginDetails.username = encryptAES(email, captchaKey, iv1);
loginDetails.password = encryptAES(password, captchaKey, iv2);
Hey, Thanks a lot for this. Can we have a solution for python also. What i need is a way of encryption which I can decrypt using python, go and node all.