-
-
Save jeruyyap/8cc375a1d50abdf234e7 to your computer and use it in GitHub Desktop.
DO NOT use these as-is for anything important! | |
These are only very basic examples and they are missing much of what would be needed for a real-world use case. | |
These are snippets for matching encrypt and decrypt (Rijndael-128 in CBC mode with PKCS7 padding) in C#.NET, PHP, and Python. | |
I cobbled these together from various existing examples because at the time it seemed like a lot of existing examples out there for different languages/platforms did not quite match and would require quite a bit more work before they would encrypt/decrypt identically. | |
Each of these take Keys and IVs that are 16 character strings encoded in base64. |
public class Rijndael128Encryptor | |
{ | |
/* | |
* Encrypt method | |
* Both Keys and IVs need to be 16 characters encoded in base64. | |
*/ | |
public String AES_encrypt(String Input, String AES_Key, String AES_IV) | |
{ | |
// Create encryptor | |
var aes = new RijndaelManaged(); | |
aes.KeySize = 128; | |
aes.BlockSize = 128; | |
aes.Padding = PaddingMode.PKCS7; | |
aes.Key = Convert.FromBase64String(AES_Key); | |
aes.IV = Convert.FromBase64String(AES_IV); | |
var encrypt = aes.CreateEncryptor(aes.Key, aes.IV); | |
// Encrypt Input | |
byte[] xBuff = null; | |
using (var ms = new MemoryStream()) | |
{ | |
// Convert from UTF-8 String to byte array, write to memory stream and encrypt, then convert to byte array | |
using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write)) | |
{ | |
byte[] xXml = Encoding.UTF8.GetBytes(Input); | |
cs.Write(xXml, 0, xXml.Length); | |
} | |
xBuff = ms.ToArray(); | |
} | |
// Convert from byte array to base64 string then return | |
String Output = Convert.ToBase64String(xBuff); | |
return Output; | |
} | |
/* | |
* Decrypt method | |
* Both Keys and IVs need to be 16 characters encoded in base64. | |
*/ | |
public String AES_decrypt(String Input, String AES_Key, String AES_IV) | |
{ | |
// Create decryptor | |
RijndaelManaged aes = new RijndaelManaged(); | |
aes.KeySize = 128; | |
aes.BlockSize = 128; | |
aes.Mode = CipherMode.CBC; | |
aes.Padding = PaddingMode.PKCS7; | |
aes.Key = Convert.FromBase64String(AES_Key); | |
aes.IV = Convert.FromBase64String(AES_IV); | |
var decrypt = aes.CreateDecryptor(); | |
// Decrypt Input | |
byte[] xBuff = null; | |
using (var ms = new MemoryStream()) | |
{ | |
// Convert from base64 string to byte array, write to memory stream and decrypt, then convert to byte array. | |
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write)) | |
{ | |
byte[] xXml = Convert.FromBase64String(Input); | |
cs.Write(xXml, 0, xXml.Length); | |
} | |
xBuff = ms.ToArray(); | |
} | |
// Convert from byte array to UTF-8 string then return | |
String Output = Encoding.UTF8.GetString(xBuff); | |
return Output; | |
} | |
} |
<?php | |
class Rijndael128Encryptor{ | |
/* | |
* Adds PKCS7 padding | |
*/ | |
private function addpadding($inputstring) | |
{ | |
$blocksize = 16; | |
$len = strlen($inputstring); | |
$pad = $blocksize - ($len % $blocksize); | |
$inputstring .= str_repeat(chr($pad), $pad); | |
return $inputstring; | |
} | |
/* | |
* Strips PKCS7 padding | |
*/ | |
private function strippadding($inputstring) | |
{ | |
$slast = ord(substr($inputstring, -1)); | |
$slastc = chr($slast); | |
if(preg_match("/$slastc{".$slast."}/", $inputstring)){ | |
$inputstring = substr($inputstring, 0, strlen($inputstring)-$slast); | |
return $inputstring; | |
} else { | |
return false; | |
} | |
} | |
/* | |
* Encrypt method | |
* Both Keys and IVs need to be 16 characters encoded in base64. | |
*/ | |
public function encrypt($inputstring, $inputkey, $inputiv) | |
{ | |
$key = base64_decode($inputkey); | |
$iv = base64_decode($inputiv); | |
// Pad text and encrypt | |
$padded_string = $this->addpadding($inputstring); | |
$encrypted_string = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $padded_string, MCRYPT_MODE_CBC, $iv); | |
// Encode to base64 and return | |
return base64_encode($encrypted_string); | |
} | |
/* | |
* Decrypt method | |
* Both Keys and IVs need to be 16 characters encoded in base64. | |
*/ | |
public function decrypt($inputstring, $inputkey, $inputiv) | |
{ | |
$key = base64_decode($inputkey); | |
$iv = base64_decode($inputiv); | |
// Decode from base64 and decrypt | |
$decoded_string = base64_decode($inputstring); | |
$decrypted_string = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $decoded_string, MCRYPT_MODE_CBC, $iv); | |
// Unpad text and return | |
return $this->strippadding($decrypted_string); | |
} | |
} | |
?> |
from Crypto.Cipher import AES | |
import base64 | |
class RijndaelEncryptor(object): | |
""" | |
Encrypts text using Rijndael 128 in CBC mode and using PKCS7 padding | |
""" | |
def __init__(self, k=16): | |
self.k = k #sets block size of 16 for padding, NOT FOR CIPHER | |
def _pkcs7decode(self, text): | |
""" | |
Remove PKCS7 padding from text | |
""" | |
val = text[-1] | |
if val > self.k: | |
raise ValueError('Input is not padded or padding is corrupt') | |
l = len(text) - val | |
return (text[:l]).decode(encoding="UTF-8") | |
def _pkcs7encode(self, text): | |
""" | |
Add PKCS7 padding to text | |
""" | |
l = len(text) | |
val = self.k - (l % self.k) | |
return text + bytearray([val] * val).decode(encoding="UTF-8") | |
def encrypt(self, text, input_key, input_iv): | |
""" | |
Encrypt method | |
Both Keys and IVs need to be 16 characters encoded in base64. | |
""" | |
# Create aes object | |
key = base64.b64decode(input_key) | |
iv = base64.b64decode(input_iv) | |
aes = AES.new(key, AES.MODE_CBC, iv) | |
# Pad text and encrypt | |
pad_text = self._pkcs7encode(text) | |
cipher_text = aes.encrypt(pad_text) | |
# Encode to base64 and return | |
return base64.b64encode(cipher_text) | |
def decrypt(self, text, input_key, input_iv): | |
""" | |
Decrypt method | |
Both Keys and IVs need to be 16 characters encoded in base64. | |
""" | |
# Create aes object | |
key = base64.b64decode(input_key) | |
iv = base64.b64decode(input_iv) | |
aes = AES.new(key, AES.MODE_CBC, iv) | |
# Decode from base64 and decrypt | |
decode_text = base64.b64decode(text) | |
pad_text = aes.decrypt(decode_text) | |
# Unpad text and return | |
return self._pkcs7decode(pad_text) |
@anonymouz4, the code works perfectly on Python 3 and above, your patch is for older versions.
the decrypt code doesnt work in PHP... Please can u help me?
@kenvanhuffel
What happens when you try to use it more specifically?
Also to reiterate, this snippet exists entirely as a simple demo.
I would strongly discourage using it in any real-world application as it is effectively obsolete and missing many vital components a real-world encryption solution would need.
I can program php and mysql and jquery and api and all that.
but all this encrypt code isnt my thing. so I really dont know what fails. It just gives an empty return back.
Infact the return is false instead of receiving a string.
I also use salting keys and variable salts included, so its pretty safe.
The reason why i dont use other encryption is bcoz I need encryption to work on 3 platforms: c#, powershell and php.
Can U recommend another opensource script thats better and runs the 3 platforms with same results?
can u help me out on the php decrypt?
It seems it fails on the strippadding method.
I still get a string in de decrypt method. but at the final decrupt line it calls the strppadding, thats where it fails and return false
@kenvanhuffel
Unfortunately I don't have a good way to recreate the issue at the moment and I don't have the time to commit to this at the moment.
Unless you're doing this as an academic exercise, you really need to look at using some kind of wrapper (SSH Tunnel or VPN?) or some existing protocol (TLS/SSL, Double Ratchet, PGP?), and rather than using the algorithms directly.
If you really need to make your own encryption protocol, I would strongly recommend looking into using a much more modern library such as libsodium and its related libraries.
Python decryption doesn't work.
Encrypting works, if I then try to decrypt the value with the SAME params it fails:
Input is not padded or padding is corrupt
It works if you replace the content of
def _pkcs7decode(self, text):
with: