Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save jeruyyap/8cc375a1d50abdf234e7 to your computer and use it in GitHub Desktop.
Save jeruyyap/8cc375a1d50abdf234e7 to your computer and use it in GitHub Desktop.
Matching Encrypt/Decrypt Methods With Rijndael-128, CBC Mode, PKCS7 Padding in C#.NET, PHP, And Python
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
Copy link

anonymouz4 commented Jan 31, 2019

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:

	pad = ord(text[-1])
	return text[:-pad]

@leonardorame
Copy link

@anonymouz4, the code works perfectly on Python 3 and above, your patch is for older versions.

@kenvanhuffel
Copy link

the decrypt code doesnt work in PHP... Please can u help me?

@jeruyyap
Copy link
Author

jeruyyap commented Mar 10, 2020

@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.

@kenvanhuffel
Copy link

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?

@kenvanhuffel
Copy link

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

@jeruyyap
Copy link
Author

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment