I am trying to encrypt a string then covert it into a base64_encode string to be passed to a website so that it can decrypt it.
My functions below dont seem to be working correctly and it won't decrypt the base64_encode string back to the original string.
Anyone see the problem?
Thanks
public static string EncryptToString(string data, string KeyString, string IVString)
{
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] Data = encoding.GetBytes(data);
byte[] Key = encoding.GetBytes(KeyString);
byte[] IV = encoding.GetBytes(IVString);
try
{
MemoryStream fStream = new MemoryStream(Data);
// Set Rijndael object mode.
Rijndael RijndaelAlg;
RijndaelAlg = Rijndael.Create();
RijndaelAlg.Mode = CipherMode.CBC;
// Create a CryptoStream using the FileStream
// and the passed key and initialization vector (IV).
CryptoStream cStream = new CryptoStream(fStream,
RijndaelAlg.CreateEncryptor(Key, IV),
CryptoStreamMode.Read);
// Create a StreamReader using the CryptoStream.
StreamReader sReader = new StreamReader(cStream);
string encryptedString = null;
try
{
// Read the data from the stream
// to decrypt it.
encryptedString = sReader.ReadToEnd();
// Convert result into a base64-encoded string.
byte[] bytes = encoding.GetBytes(encryptedString);
encryptedString = Convert.ToBase64String(bytes, 0, bytes.Length);
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
// Close the streams and
// close the file.
sReader.Close();
cStream.Close();
fStream.Close();
RijndaelAlg.Dispose();
}
// Return the string.
return encryptedString;
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
}
public static string DecryptToString(string data, string KeyString, string IVString)
{
ASCIIEncoding encoding = new ASCIIEncoding();
// Convert result from a base64-encoded to string.
byte[] Data = Convert.FromBase64String(data);
byte[] Key = encoding.GetBytes(KeyString);
byte[] IV = encoding.GetBytes(IVString);
try
{
MemoryStream fStream = new MemoryStream(Data);
// Set Rijndael object mode.
Rijndael RijndaelAlg;
RijndaelAlg = Rijndael.Create();
RijndaelAlg.Mode = CipherMode.CBC;
// Create a CryptoStream using the FileStream
// and the passed key and initialization vector (IV).
CryptoStream cStream = new CryptoStream(fStream,
RijndaelAlg.CreateDecryptor(Key, IV),
CryptoStreamMode.Read);
// Create a StreamReader using the CryptoStream.
StreamReader sReader = new StreamReader(cStream);
string decryptedString = null;
try
{
// Read the data from the stream
// to decrypt it.
decryptedString = sReader.ReadToEnd();
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
// Close the streams and
// close the file.
sReader.Close();
cStream.Close();
fStream.Close();
RijndaelAlg.Dispose();
}
// Return the string.
return decryptedString;
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
}
I'm not sure exactly where it is going wrong, but when I was doing this I had some strange issues too. I'll share with you the code I wrote to get this working properly:
static public String EncryptString(String message)
{
String sRet = "";
RijndaelManaged rj = new RijndaelManaged();
try
{
rj.Key = Key;
rj.IV = IV;
MemoryStream ms = new MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(message);
}
}
byte[] encoded = ms.ToArray();
sRet = Convert.ToBase64String(encoded);
}
finally
{
rj.Clear();
}
return sRet;
}
static public String DecryptString(String cypher)
{
String sRet = "";
RijndaelManaged rj = new RijndaelManaged();
try
{
byte[] message = Convert.FromBase64String(cypher);
rj.Key = Key;
rj.IV = IV;
MemoryStream ms = new MemoryStream(message);
using (CryptoStream cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
sRet = sr.ReadToEnd();
}
}
}
finally
{
rj.Clear();
}
return sRet;
}
Key and IV are static byte[] contained in the class.
Related
When encrypting and decrypting text files, the code works fine.
But when encrypting binary and zip files, file size almost doubled after decryption. For example, a 2.06mb bin.exe became 3.69mb after decryption; a 4mb zip file became 7+mb after decryption.
Is this because of the PaddingMode? What PaddingMode should I set to work with all types of files? How to solve this problem?
private async Task RunEncrypt(string srcfile)
{
string data;
using (StreamReader sr = new StreamReader(srcfile))
{
data = sr.ReadToEnd();
}
byte[] enc_data = await Program.myEncrypt(data);
}
static async Task<byte[]> myEncrypt(string toEncStr)
{
byte[] encrypted;
using (Aes encaes = Aes.Create())
{
try
{
//store key to key.txt
FileStream fs = new FileStream("key.txt", FileMode.OpenOrCreate);
fs.Write(encaes.Key, 0, encaes.Key.Length);
fs.Write(encaes.IV, 0, encaes.IV.Length);
fs.Close();
}
catch ( Exception e)
{
Console.WriteLine("Recording encryption keys failed!{0}.", e.Message);
Environment.Exit(0);
}
encaes.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = encaes.CreateEncryptor(encaes.Key, encaes.IV);
try
{
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(toEncStr);
}
}
encrypted = msEncrypt.ToArray();
}
return encrypted;
}
catch (Exception e)
{
Console.WriteLine("Encryption failed!{0}.", e.Message);
return Encoding.UTF8.GetBytes("null");
}
}
}
private async Task RunDecrypt(byte[] inbytes)
{
try
{
string write_data = await myDecrypt(inbytes);
using (StreamWriter sw = new StreamWriter("test.exe", true))
{
sw.Write(write_data);
sw.Close();
}
}
catch (Exception e)
{
}
}
async Task<string> myDecrypt(byte[] toDecBytes)
{
try
{
string decrypted;
using (Aes dec = Aes.Create())
{
byte[] Key = new byte[dec.Key.Length];
byte[] IV = new byte[dec.IV.Length];
//read key from key.txt
FileStream fsread = new FileStream("key.txt", FileMode.Open);
fsread.Read(Key, 0, Key.Length);
fsread.Read(IV, 0, IV.Length);
fsread.Close();
dec.Key = Key;
dec.IV = IV;
dec.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = dec.CreateDecryptor(dec.Key, dec.IV);
using (MemoryStream msDecrypt = new MemoryStream(toDecBytes))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
decrypted = srDecrypt.ReadToEnd();
return decrypted;
}
}
}
}
}
catch (Exception e)
{
Console.WriteLine("Decryption failed! {0}.", e.Message);
return #"null";
}
}
By using a StreamReader and StreamWriter, you are treating the file content as text. To support binary files, read/write directly from/to the source/target stream instead.
I want encrypt in C# and decrypt in c++ but I have some Encoding problem :
example variables :
Key : gOtIPaLver—vS5UAnJbPqsDZSf,yJ1
IVString : gOtIPaLver—vS5
my c# code :
public static string EncryptString(string message, string KeyString, string IVString)
{
byte[] Key = UTF8Encoding.UTF8.GetBytes(KeyString.Substring(0,32));
byte[] IV = UTF8Encoding.UTF8.GetBytes(IVString);
string encrypted = null;
RijndaelManaged rj = new RijndaelManaged();
rj.Key = Key;
rj.IV = IV;
rj.Mode = CipherMode.CBC;
rj.Padding = PaddingMode.PKCS7;
try
{
MemoryStream ms = new MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(message);
sw.Close();
}
cs.Close();
}
byte[] encoded = ms.ToArray();
encrypted = Convert.ToBase64String(encoded);
ms.Close();
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
rj.Clear();
}
return encrypted;
}
When I try encrypt and my Key have some not ASCII char - count of bytes is more than lenght of string .
How Encoding I shound use ? In C++ I use EVP (default padding is PKCS7) .
static string decryptEX(string KS, string ctext)
{
EVP_CIPHER_CTX* ctx;
ctx = EVP_CIPHER_CTX_new();
string IV = KS.substr(0, 16);
int rc = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, (byte*)&KS[0], (byte*)&IV[0]);
std::string rtext;
rtext.resize(ctext.size());
int out_len1 = (int)rtext.size();
rc = EVP_DecryptUpdate(ctx, (byte*)&rtext[0], &out_len1, (const byte*)&ctext[0], (int)ctext.size());
int out_len2 = (int)rtext.size() - out_len1;
rc = EVP_DecryptFinal_ex(ctx, (byte*)&rtext[0] + out_len1, &out_len2);
try
{
rtext.resize(out_len1 + out_len2);
}
catch (exception e)
{
}
return rtext;
}
Your call to
byte[] Key = UTF8Encoding.UTF8.GetBytes(KeyString.Substring(0,32));
fails because there are not 32 characters in that string. Yes, there would be 32 bytes if the string is encoded as UTF8. But Substring takes a count of characters.
Changing that line to
byte[] Key = UTF8Encoding.UTF8.GetBytes(KeyString);
gives a 32-byte long key.
Since you can't count on getting proper input for the KeyString, you could validate after this point that your key length is long enough.
byte[] Key = UTF8Encoding.UTF8.GetBytes(KeyString);
if (Key.Length < 32)
throw new KeyLengthException("some useful info as to why this was thrown"); // or some other appropriate Exception type you create or resuse.
If I'm correct in assuming which key, IV, and block sizes you require, this should do what you need:
public static string EncryptString(string message, string KeyString, string IVString)
{
byte[] Key = UTF8Encoding.UTF8.GetBytes(KeyString).Take(32).ToArray();
if (Key.Length < 32)
throw new Exception("KeyString not at least 32 bytes.");
byte[] IV = UTF8Encoding.UTF8.GetBytes(IVString).Take(16).ToArray();
if (Key.Length < 32)
throw new Exception("IVString not at least 16 bytes.");
string encrypted = null;
RijndaelManaged rj = new RijndaelManaged();
rj.KeySize = 128;
rj.BlockSize = 128;
rj.Key = Key;
rj.IV = IV;
rj.Mode = CipherMode.CBC;
rj.Padding = PaddingMode.PKCS7;
try
{
MemoryStream ms = new MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(message);
sw.Close();
}
cs.Close();
}
byte[] encoded = ms.ToArray();
encrypted = Convert.ToBase64String(encoded);
ms.Close();
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
rj.Clear();
}
return encrypted;
}
I'm new to C# and I really need help. I need to encrypt/decrypt a string with AES-256-CBC in C#, I found this to encrypt a string:
public static string EncryptString(string message, string KeyString, string IVString)
{
byte[] Key = ASCIIEncoding.UTF8.GetBytes(KeyString);
byte[] IV = ASCIIEncoding.UTF8.GetBytes(IVString);
string encrypted = null;
RijndaelManaged rj = new RijndaelManaged();
rj.Key = Key;
rj.IV = IV;
rj.Mode = CipherMode.CBC;
try
{
MemoryStream ms = new MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(message);
sw.Close();
}
cs.Close();
}
byte[] encoded = ms.ToArray();
encrypted = Convert.ToBase64String(encoded);
ms.Close();
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
rj.Clear();
}
return encrypted;
}
I tried to write a decrypt function base on the above code, the following code is what I did:
// Decrypt a byte array into a byte array using a key and an IV
private byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
{
byte[] decryptedData;
//string plaintext = null;
//MemoryStream ms = new MemoryStream(cipherData);
RijndaelManaged alg = new RijndaelManaged();
alg.KeySize = 256;
alg.BlockSize = 128;
alg.Key = Key;
alg.IV = IV;
alg.Mode = CipherMode.CBC;
alg.Padding = PaddingMode.Zeros;
//Array.Copy(Key, 0, IV, 0, IV.Length);
ICryptoTransform decryptor = alg.CreateDecryptor(alg.Key, alg.IV);
using(MemoryStream ms = new MemoryStream(cipherData))
{
using (CryptoStream csDecrypt = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sw = new StreamReader(csDecrypt))
{
sw.ReadToEnd();
sw.Close();
}
csDecrypt.Close();
decryptedData = ms.ToArray();
}
}
//byte[] decryptedData = System.Text.Encoding.Unicode.GetBytes(plaintext);
return decryptedData;
}
But it's nonsense, it can't decrypt anything. I'm really confused and need help. Thank you for any help!
P/s: Please don't give me other similar answered questions, I already take a look at them. Their encrypt function doesn't have the same output like the above encrypt function, while I need to decrypt string which MUST be encrypt by the above function. I have two friend who wrote decrypt function in PHP and objective-C, which matched with the above encrypt function, it's bad to have them do it again.
Looking at your encryption, something like this should do it, passing the resulting string from your encryption in should give the original string back;
// Decrypt a string into a string using a key and an IV
public static string Decrypt(string cipherData, string keyString, string ivString)
{
byte[] key = Encoding.UTF8.GetBytes(keyString);
byte[] iv = Encoding.UTF8.GetBytes(ivString);
try
{
using (var rijndaelManaged =
new RijndaelManaged {Key = key, IV = iv, Mode = CipherMode.CBC})
using (var memoryStream =
new MemoryStream(Convert.FromBase64String(cipherData)))
using (var cryptoStream =
new CryptoStream(memoryStream,
rijndaelManaged.CreateDecryptor(key, iv),
CryptoStreamMode.Read))
{
return new StreamReader(cryptoStream).ReadToEnd();
}
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
// You may want to catch more exceptions here...
}
A small note; you're getting the key using UTF8 encoding from the key string, UTF8 encoding may give you multiple bytes back for international characters, which may give a key or IV of the wrong length for encryption/decryption. Also, using the small range of passwords/keys with 8 characters and printable characters will not give you very secure encryption, you may want to run the string though SHA1 or similar before using it as a key (which will sadly make it incompatible with the current encryption)
I have a problem related to AES decryption on my server side.
When encrypting data in the android client and sending it to the WCF server, the server always return an exception like
System.Security.Cryptography.CryptographicException: Padding is
invalid and cannot be removed. at
System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[]
block, Int32 offset, Int32 count) at
System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[]
inputBuffer, Int32 inputOffset, Int32 inputCount) at
System.Security.Cryptography.CryptoStream.FlushFinalBlock() at
WindowsFormsApplication1.Form1.Decrypt(Byte[] p_EncryptedMsg, Byte[]
p_key, Byte[] p_iv) in c:\users\omr\documents\visual studio
2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:line
76 at WindowsFormsApplication1.Form1.button1_Click(Object sender,
EventArgs e) in c:\users\omr\documents\visual studio
2010\Projects\WindowsFormsApplication1\WindowsFormsApplication1\Form1.cs:line
94}
my android encryption is
public static String enc(String message) {
byte[] keyInBytes = KEY.getBytes();
byte[] encryptedData = null;
KeyGenerator kgen;
try {
kgen = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(keyInBytes);
kgen.init(256, secureRandom);
SecretKey skey = kgen.generateKey();
key = skey.getEncoded();
try {
encryptedData = encrypt(key, message.getBytes());
Log.w("ENC ", new String(encryptedData));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return Base64.encodeToString(encryptedData, Base64.DEFAULT);
// return message;
}
private static byte[] encrypt(byte[] raw, byte[] testMessage)
throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, /* "PBEWithSHA1And128BitAES-CBC-BC" */
"AES");
final byte[] iv = KEY.getBytes();
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(testMessage);
try {
decrypt(raw, encrypted);
} catch (Exception e) {
e.getMessage();
// TODO: handle exception
}
return encrypted;
}
and my C# code is
public String Decrypt(byte[] p_EncryptedMsg, byte[] p_key, byte[] p_iv)
{
m_key = new byte[32];
m_iv = new byte[16];
Array.Clear(m_key, 0, 32);
Array.Clear(m_iv, 0, 16);
Array.Copy(p_key, m_key, p_key.Length > 32 ? 32 : p_key.Length);
Array.Copy(p_iv, m_iv, p_iv.Length > 16 ? 16 : p_iv.Length);
if (m_key == null || m_iv == null)
throw new ArgumentNullException("Key or IV is equal to null");
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
aesProvider.Key = m_key;
aesProvider.IV = m_iv;
aesProvider.Mode = CipherMode.CBC;
aesProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream memStream = new MemoryStream())
{
CryptoStream decStream = new CryptoStream(memStream, aesProvider.CreateDecryptor(), CryptoStreamMode.Write);
decStream.Write(p_EncryptedMsg, 0, p_EncryptedMsg.Length);
decStream.FlushFinalBlock();
String res = System.Text.Encoding.Default.GetString(memStream.ToArray());
return res;
}
}
}
NOTE:
I can encrypt and decrypt the text again correctly in the android side.
Well, one problem I see is that your CipherMode on the .Net side should be ECB to match the Java side. Give that a shot and see if that works.
i found that the problem happened as a result of using SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
as the server side take only the keyInBytes from me not the randomized one, so he can't generate the correct decryption key.
C# code example
using (AesCryptoServiceProvider aesCryptoServiceProvider = new AesCryptoServiceProvider())
{
aesCryptoServiceProvider.Key = key;
aesCryptoServiceProvider.IV = iv;
aesCryptoServiceProvider.Mode = CipherMode.CBC;
aesCryptoServiceProvider.Padding = PaddingMode.PKCS7;
using (MemoryStream memoryStream = new MemoryStream())
{
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesCryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Write);
cryptoStream.Write(p_EncryptedMsg, 0, encryptedMsg.Length);
cryptoStream.FlushFinalBlock();
return memoryStream.ToArray();
}
}
I've seen a few posts about this, but yet I can't seem to get this to work, any ideas?
RESULTS:
C# Encrypted string test = O6qzYiLPCpbXUf8PjMHpcg==
php Encrypted string test = SdS1dN1ugyAVYGFzHiTayg==
C# Code
public static string EncryptString(string message, string KeyString, string IVString)
{
byte[] Key = ASCIIEncoding.UTF8.GetBytes(KeyString);
byte[] IV = ASCIIEncoding.UTF8.GetBytes(IVString);
string encrypted = null;
RijndaelManaged rj = new RijndaelManaged();
rj.Key = Key;
rj.IV = IV;
rj.Mode = CipherMode.CBC;
try
{
MemoryStream ms = new MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(message);
sw.Close();
}
cs.Close();
}
byte[] encoded = ms.ToArray();
encrypted = Convert.ToBase64String(encoded);
ms.Close();
}
catch (CryptographicException e)
{
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("A file error occurred: {0}", e.Message);
return null;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: {0}", e.Message);
}
finally
{
rj.Clear();
}
return encrypted;
}
string enctext = EncryptString("test", "qwertyuiopasdfghjklzxcvbnmqwerty", _"1234567890123456");
PHP
function aesenc($message, $keystring, $ivstring){
$IV_UTF = mb_convert_encoding($ivstring, 'UTF-8');
$KEY_UTF = mb_convert_encoding($keystring, 'UTF-8');
return base64_encode( mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $KEY_UTF, $message, MCRYPT_MODE_CBC, $IV_UTF));
}
$enctext = aesenc("test", "qwertyuiopasdfghjklzxcvbnmqwerty", _"1234567890123456");
Found the answer, needed to add padding to the $message in php
function aesenc($message, $keystring, $ivstring){
$IV_UTF = mb_convert_encoding($ivstring, 'UTF-8');
$KEY_UTF = $keystring;
return base64_encode( mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $KEY_UTF, addpadding($message), MCRYPT_MODE_CBC, $IV_UTF));
}
function addpadding($string, $blocksize = 16)
{
$len = strlen($string);
$pad = $blocksize - ($len % $blocksize);
$string .= str_repeat(chr($pad), $pad);
return $string;
}