-
-
Save mrgcohen/81a847960013d1252b58666b0358b18a to your computer and use it in GitHub Desktop.
AES 256-CFB in Node.js, Go, and Python
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 ( | |
"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)) | |
} |
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
'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); |
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
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 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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment