I need to port a C# encrypt/decrypt class using 3DES with PKCS7 padding in HEX (with static key and IV) to Ruby or Python but seems the output is totally different.
Here is the C# snippets of the code:
public CryptoDES3()
{
this.objCryptoProvider = new TripleDESCryptoServiceProvider();
this.CipherMode = CipherMode.CBC;
this.PaddingMode = PaddingMode.PKCS7;
this.EncodingType = CryptoDES3.EncodingTypeEnum.Hex;
}
/* ----- */
public string Encrypt(string strValue, string strKey, string strIV, CryptoDES3.EncodingTypeEnum intEncodingType)
{
string str = "";
if (strValue.Length > 0)
{
this.objCryptoProvider.Mode = this.CipherMode;
this.objCryptoProvider.Padding = this.PaddingMode;
byte[] bytes1 = Encoding.Default.GetBytes(CryptoDES3.HexDecode(strKey));
byte[] bytes2 = Encoding.Default.GetBytes(CryptoDES3.HexDecode(strIV));
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, this.objCryptoProvider.CreateEncryptor(bytes1, bytes2), CryptoStreamMode.Write);
StreamWriter streamWriter = new StreamWriter((Stream) cryptoStream);
streamWriter.Write(strValue);
streamWriter.Flush();
cryptoStream.FlushFinalBlock();
string strValue1 = Encoding.Default.GetString(memoryStream.GetBuffer(), 0, checked ((int) memoryStream.Length));
switch (intEncodingType)
{
case CryptoDES3.EncodingTypeEnum.Hex:
str = CryptoDES3.HexEncode(strValue1);
break;
case CryptoDES3.EncodingTypeEnum.Base64:
str = CryptoDES3.Base64Encode(strValue1);
break;
default:
str = strValue1;
break;
}
}
return str;
}
public string Decrypt(string strValue, string strKey, string strIV, CryptoDES3.EncodingTypeEnum intEncodingType)
{
string str = "";
if (strValue.Length > 0)
{
this.objCryptoProvider.Mode = this.CipherMode;
this.objCryptoProvider.Padding = this.PaddingMode;
byte[] bytes1 = Encoding.Default.GetBytes(CryptoDES3.HexDecode(strKey));
byte[] bytes2 = Encoding.Default.GetBytes(CryptoDES3.HexDecode(strIV));
string s;
switch (intEncodingType)
{
case CryptoDES3.EncodingTypeEnum.Hex:
s = CryptoDES3.HexDecode(strValue);
break;
case CryptoDES3.EncodingTypeEnum.Base64:
s = CryptoDES3.Base64Decode(strValue);
break;
default:
s = strValue;
break;
}
str = new StreamReader((Stream) new CryptoStream((Stream) new MemoryStream(Encoding.Default.GetBytes(s)), this.objCryptoProvider.CreateDecryptor(bytes1, bytes2), CryptoStreamMode.Read)).ReadToEnd();
}
return str;
}
/* ----- */
internal const string DES3_KEY = "A0498F07C46808173894BB976F9726477CC0913D87DE912A";
internal const string DES3_IV = "0A9B11D6FEE830A9";
Here is the Ruby code with it's output to console:
#!/usr/bin/env ruby
require 'digest'
require 'openssl'
ALG = "DES-EDE3-CBC"
KEY = "\xA0\x49\x8F\x07\xC4\x68\x08\x17\x38\x94\xBB\x97\x6F\x97\x26\x47\x7C\xC0\x91\x3D\x87\xDE\x91\x2A"
IV = "\x0A\x9B\x11\xD6\xFE\xE8\x30\xA9"
def encode(data)
cipher = OpenSSL::Cipher::Cipher.new(ALG)
cipher.key = KEY
cipher.iv = IV
cipher.encrypt
result = cipher.update(data)
result << cipher.final
result = result.unpack('H*')
end
def decode(data)
cipher = OpenSSL::Cipher::Cipher.new(ALG)
cipher.key = KEY
cipher.iv = IV
cipher.decrypt
data = data.pack('H*')
result = cipher.update(data)
result << cipher.final
end
data = "test"
encoded = encode(data)
decoded = decode(encoded)
puts "Encrypted: #{encoded[0]}"
puts "Decrypted: #{decoded}"
output:
$ ./3des.rb
Encrypted: 33fd6ee287c0f46f
Decrypted: test
Python code:
#!/usr/bin/env python
import pyDes
k = pyDes.triple_des('A0498F07C46808173894BB976F9726477CC0913D87DE912A'.decode('hex'), mode=pyDes.CBC, IV="0A9B11D6FEE830A9".decode('hex'), pad=None, padmode=pyDes.PAD_PKCS5)
d = k.encrypt("test")
print "Encrypted: " + d.encode('hex')
print "Decrypted: " + k.decrypt(d)
output:
$ ./3des.py
Encrypted: 33fd6ee287c0f46f
Decrypted: test
Same output in Python using chilkat.CkCrypt2().
Does MS C# TripleDESCryptoServiceProvider() differ to Ruby,Python,OpenSSL?
Any idea how can I get the same results?
Made it work on C# also:
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Threading.Tasks;
namespace _3DES
{
class Program
{
public static string Encrypt(string strValue)
{
const string DES3_KEY = "A0498F07C46808173894BB976F9726477CC0913D87DE912A";
const string DES3_IV = "0A9B11D6FEE830A9";
TripleDESCryptoServiceProvider objCryptoProvider;
string str = "";
if (strValue.Length > 0)
{
objCryptoProvider = new TripleDESCryptoServiceProvider();
objCryptoProvider.Mode = CipherMode.CBC;
objCryptoProvider.Padding = PaddingMode.PKCS7;
byte[] bytes1 = Encoding.Default.GetBytes(HexDecode(DES3_KEY));
byte[] bytes2 = Encoding.Default.GetBytes(HexDecode(DES3_IV));
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, objCryptoProvider.CreateEncryptor(bytes1, bytes2), CryptoStreamMode.Write);
StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream);
streamWriter.Write(strValue);
streamWriter.Flush();
cryptoStream.FlushFinalBlock();
string strValue1 = Encoding.Default.GetString(memoryStream.GetBuffer(), 0, checked((int)memoryStream.Length));
str = HexEncode(strValue1);
}
return str;
}
public static string Decrypt(string strValue)
{
const string DES3_KEY = "A0498F07C46808173894BB976F9726477CC0913D87DE912A";
const string DES3_IV = "0A9B11D6FEE830A9";
TripleDESCryptoServiceProvider objCryptoProvider;
string str = "";
if (strValue.Length > 0)
{
objCryptoProvider = new TripleDESCryptoServiceProvider();
objCryptoProvider.Mode = CipherMode.CBC;
objCryptoProvider.Padding = PaddingMode.PKCS7;
byte[] bytes1 = Encoding.Default.GetBytes(HexDecode(DES3_KEY));
byte[] bytes2 = Encoding.Default.GetBytes(HexDecode(DES3_IV));
string s;
s = HexDecode(strValue);
str = new StreamReader((Stream)new CryptoStream((Stream)new MemoryStream(Encoding.Default.GetBytes(s)), objCryptoProvider.CreateDecryptor(bytes1, bytes2), CryptoStreamMode.Read)).ReadToEnd();
}
return str;
}
public static string HexEncode(string strValue)
{
string str = "";
if (strValue.Length > 0)
{
byte[] bytes = Encoding.Default.GetBytes(strValue);
int num = 0;
int upperBound = bytes.GetUpperBound(0);
int index = num;
while (index <= upperBound)
{
str += Conversion.Hex(bytes[index]).PadLeft(2, '0');
checked { ++index; }
}
}
return str;
}
public static string HexDecode(string strValue)
{
string str = "";
if (strValue.Length > 0)
{
strValue = strValue.ToUpper();
int num1 = 0;
int num2 = checked(strValue.Length - 2);
int startIndex = num1;
while (startIndex <= num2)
{
str += Conversions.ToString(Strings.Chr(Conversions.ToInteger("&H" + strValue.Substring(startIndex, 2))));
checked { startIndex += 2; }
}
}
return str;
}
static void Main(string[] args)
{
String encoded = Encrypt("test");
Console.WriteLine(encoded);
String plain = Decrypt(encoded);
Console.WriteLine(plain);
}
}
}
output:
C:\> 3DES.exe
33FD6EE287C0F46F
test
Related
Want to encrypt and decrypt Persian text in C# (.net framework 8) it works fine in English alphabets but when I use Persian/Arabic text, some characters have been removed from the end of the result, what's wrong with my codes?
public class AES256
{
private static RijndaelManaged rijndaelManaged;
private static byte[] key, pwd, ivBytes, iv;
private enum EncryptMode { ENCRYPT, DECRYPT };
public static string Encrypt(string _plainText, string _key, string _initVector)
{
InitAES256();
return Process(_plainText, _key, EncryptMode.ENCRYPT, _initVector);
}
public static string Decrypt(string _encryptedText, string _key, string _initVector)
{
InitAES256();
return Process(_encryptedText, _key, EncryptMode.DECRYPT, _initVector);
}
private static void InitAES256()
{
rijndaelManaged = new RijndaelManaged();
rijndaelManaged.Mode = CipherMode.CBC;
rijndaelManaged.Padding = PaddingMode.PKCS7;
rijndaelManaged.KeySize = 256;
rijndaelManaged.BlockSize = 128;
key = new byte[32];
iv = new byte[rijndaelManaged.BlockSize / 8];
ivBytes = new byte[16];
}
private static string Process(string _inputText, string _encryptionKey, EncryptMode _mode, string _initVector)
{
string _out = string.Empty;
pwd = Encoding.UTF8.GetBytes(_encryptionKey);
ivBytes = Encoding.UTF8.GetBytes(_initVector);
int len = pwd.Length;
if (len > key.Length)
{
len = key.Length;
}
int ivLenth = ivBytes.Length;
if (ivLenth > iv.Length)
{
ivLenth = iv.Length;
}
Array.Copy(pwd, key, len);
Array.Copy(ivBytes, iv, ivLenth);
rijndaelManaged.Key = key;
rijndaelManaged.IV = iv;
if (_mode.Equals(EncryptMode.ENCRYPT))
{
byte[] plainText = rijndaelManaged.CreateEncryptor().TransformFinalBlock(Encoding.UTF8.GetBytes(_inputText), 0, _inputText.Length);
_out = Convert.ToBase64String(plainText);
}
else if (_mode.Equals(EncryptMode.DECRYPT))
{
byte[] plainText = rijndaelManaged.CreateDecryptor().TransformFinalBlock(Convert.FromBase64String(_inputText), 0, Convert.FromBase64String(_inputText).Length);
_out = Encoding.UTF8.GetString(plainText);
}
rijndaelManaged.Dispose();
return _out;
}
}
Using:
string initVector = "123";
string SyncGetKey = "2587";
string result = AES256.Encrypt("داود", SyncGetKey, initVector);
result = AES256.Decrypt(h, SyncGetKey, initVector);
The result is "دا" and "ود" has been removed from the end (as an example).
I am making backend system for mine game (server & client). I use following code to generate first part of signature (this one is corrupted one):
#example data
string Url = "https://example.com/api/test/example.php";
Dictionary<string, string> RequestBody = new Dictionary<string, string>() { { "example_value", "test" } };
string CreateFirstHash()
{
string Combined = "";
foreach(KeyValuePair<string, string> BodyPart in RequestBody)
{
Combined += BodyPart.Key + "-" + BodyPart.Value + ".";
}
string HashedCombined = Encryption.SHA1(Combined);
string EncodedUrl = Encryption.Base64Encode(this.Url);
string PlainText = HashedCombined + ":" + EncodedUrl + ":" + 'ACBANE8AX98FT7JY6YVWKAMTMJHMYH3E2C582FCYJBTQLU4UZVSJ2E67CPB7BG75NDASGS3BAMR34UVUZN2SSPCV35A8VJPKPPCGGVEH5U9JM47GLUKRZSH3T65MBVZ2RY78C69ZGMC7JG998HRBY6U9TLQH6JDCVRE5YAR8D3TUJ3H2LBE2C598M7VNDSME5WM2YX2449Q8Z923QWGPFLCXXXCC4CETTKUJ28RYSHN372WP2KCXH6V7ZNZNJRAE';
return Encryption.SHA256(PlainText);
}
Here is Encryption class:
using System;
using System.Security.Cryptography;
using System.Text;
public class Encryption
{
private static readonly Encoding enc = Encoding.UTF8;
public static string MD5(string input)
{
byte[] inputBytes = enc.GetBytes(input);
using(System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] hashBytes = md5.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach(byte hashByte in hashBytes)
{
sb.Append(hashByte.ToString("x2"));
}
return sb.ToString();
}
}
public static string SHA1(string input)
{
byte[] inputBytes = enc.GetBytes(input);
using(SHA1Managed sha = new SHA1Managed())
{
byte[] hashBytes = sha.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach(byte hashByte in hashBytes)
{
sb.Append(hashByte.ToString("x2"));
}
return sb.ToString();
}
}
public static string SHA256(string input)
{
byte[] inputBytes = enc.GetBytes(input);
using (SHA256Managed sha = new SHA256Managed())
{
byte[] hashBytes = sha.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach (byte hashByte in hashBytes)
{
sb.Append(hashByte.ToString("x2"));
}
return sb.ToString();
}
}
public static string SHA512(string input)
{
byte[] inputBytes = enc.GetBytes(input);
using (SHA512Managed sha = new SHA512Managed())
{
byte[] hashBytes = sha.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
foreach (byte hashByte in hashBytes)
{
sb.Append(hashByte.ToString("x2"));
}
return sb.ToString();
}
}
public static string HMAC512(string input, string secret)
{
byte[] inputBytes = enc.GetBytes(input);
byte[] secretBytes = enc.GetBytes(secret);
using(HMACSHA512 hmac = new HMACSHA512(secretBytes))
{
byte[] hashBytes = hmac.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
public static string Base64Encode(string input)
{
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
return Convert.ToBase64String(inputBytes);
}
}
Server validates data by making same hash, with the same data and finally checks if generated signature is equal to input one. This is server implementation for CreateFirstHash() function:
#example data
public $requestBody = array('example_value' => 'test');
public $url = 'https://example.com/api/test/example.php';
public $scope = 'game'; #this is not important, you can disregard it
private static function generateFirstHash($requestBody, $url, $scope)
{
$combined = "";
foreach ($requestBody as $key => $value)
{
$combined .= $key . '-' . $value . ".";
}
$combined = sha1($combined);
$encodedUrl = base64_encode($url);
$plainString = $combined . ':' . $encodedUrl . ':' . 'ACBANE8AX98FT7JY6YVWKAMTMJHMYH3E2C582FCYJBTQLU4UZVSJ2E67CPB7BG75NDASGS3BAMR34UVUZN2SSPCV35A8VJPKPPCGGVEH5U9JM47GLUKRZSH3T65MBVZ2RY78C69ZGMC7JG998HRBY6U9TLQH6JDCVRE5YAR8D3TUJ3H2LBE2C598M7VNDSME5WM2YX2449Q8Z923QWGPFLCXXXCC4CETTKUJ28RYSHN372WP2KCXH6V7ZNZNJRAE';
return hash('sha256', $plainString);
}
All data from input were the same (checked manually). This is list what was the same in debug (step by step):
Combined string: same
SHA-1 hash of combined string: same
Encoded URL: same
Plain text: same
Final SHA-256 hash: invalid
Can anyone knows what is wrong and how can I make this valid?
Edit 1
Added example input data.
Thanks for adding some sample data but your C#-code is not running directly as some functions are missing.
I run your PHP-code and could extract the input to the SHA256-function:
plainString: d4a1466c15dc46dd6f7533b172313660eab1aba5:aHR0cHM6Ly9leGFtcGxlLmNvbS9hcGkvdGVzdC9leGFtcGxlLnBocA==:ACBANE8AX98FT7JY6YVWKAMTMJHMYH3E2C582FCYJBTQLU4UZVSJ2E67CPB7BG75NDASGS3BAMR34UVUZN2SSPCV35A8VJPKPPCGGVEH5U9JM47GLUKRZSH3T65MBVZ2RY78C69ZGMC7JG998HRBY6U9TLQH6JDCVRE5YAR8D3TUJ3H2LBE2C598M7VNDSME5WM2YX2449Q8Z923QWGPFLCXXXCC4CETTKUJ28RYSHN372WP2KCXH6V7ZNZNJRAE
With this input the PHP-SHA256 is:
hash: dced08719b7da56f69f70204122a498f5eda5090ad6b5a90691eb73731cc4c15
Test the plainString-value with an online-tool (https://emn178.github.io/online-tools/sha256.html) gives the same result:
dced08719b7da56f69f70204122a498f5eda5090ad6b5a90691eb73731cc4c15
Last but not least I tested your C#-implementation of SHA256 after fixing the missing
byte[] inputBytes = **enc.GetBytes**(input);
and got the result:
dced08719b7da56f69f70204122a498f5eda5090ad6b5a90691eb73731cc4c15
So in the end - there is no difference in SHA256-results between C# and PHP.
I am attempting to test a simple class to encrypt and decrypt data in C#.
`
{ [TestFixture]
public class CryptTest
{
[Test]
public void TestMethod()
{
String text = "Hello World!";
String crypt = EncryptionService.Encrypt(text, Config.KEY_STRING);
Console.WriteLine(crypt);
String clear = EncryptionService.Decrypt(crypt, Config.KEY_STRING);
Console.WriteLine(clear);
Assert.That(clear, Is.EqualTo(text));
}
`However, I am receiving the following exception:
Message: System.Security.Cryptography.CryptographicException : Padding is invalid and cannot be removed.
with the stack:
StackTrace " at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count)\r\n at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)\r\n at System.Security.Cryptography.CryptoStream.Read(Byte[] buffer, Int32 offset, Int32 count)\r\n at System.IO.StreamReader.ReadBuffer()\r\n at System.IO.StreamReader.ReadToEnd()\r\n at InsuranceMidAm.Services.EncryptionService.Decrypt(String cipher, String key) in C:\\Visual Studio Projects\\InsuranceMidAm\\InsuranceMidAm\\Services\\EncryptionService.cs:line 72\r\n at InsuranceMidAm.Tests.CryptTest.TestMethod() in C:\\Visual Studio Projects\\InsuranceMidAm\\InsuranceMidAm.Tests\\CryptTest.cs:line 20" string
This is the class under test:
namespace InsuranceMidAm.Services
{
public class EncryptionService
{
// Reference: https://stackoverflow.com/questions/273452/using-aes-encryption-in-c-sharp
public static String Encrypt(String text, String key)
{
byte[] value = UTF8Encoding.UTF8.GetBytes(text);
byte[] crypt;
byte[] iv;
using (Aes myAes = Aes.Create())
{
myAes.KeySize = 256;
myAes.Mode = CipherMode.CBC;
myAes.Key = HexToBin(key);
myAes.GenerateIV();
myAes.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, myAes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(value, 0, value.Length);
cs.FlushFinalBlock();
crypt = ms.ToArray();
}
}
iv = myAes.IV;
myAes.Clear();
}
return ByteArrayToString(crypt) + ":" + ByteArrayToString(iv);
}
public static string Decrypt(String cipher, String key)
{
String outputString = "";
byte[] ivBytes = HexToBin(getIV(cipher));
byte[] valBytes = HexToBin(getSSN(cipher));
using (Aes myAes = Aes.Create())
{
int size = valBytes.Count();
myAes.KeySize = 256;
myAes.Mode = CipherMode.CBC;
myAes.Key = HexToBin(key);
myAes.IV = ivBytes;
myAes.Padding = PaddingMode.PKCS7;
char[] output = new char[256];
ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV);
using (MemoryStream memory = new MemoryStream(ivBytes))
{
using (CryptoStream cryptStream = new CryptoStream(memory, myDecrypter, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(cryptStream))
{
outputString = reader.ReadToEnd();
}
return outputString;
}
}
}
}
private static byte[] HexToBin(String hexString)
{
int charCount = hexString.Length;
byte[] output = new byte[charCount / 2];
for (int i = 0; i < charCount; i += 2)
{
output[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16);
}
return output;
}
private static String getSSN(String cipher)
{
int delimiterIndex = cipher.IndexOf(":");
String SSN = cipher.Substring(0, delimiterIndex);
return SSN;
}
private static String getIV(String cipher)
{
int delimiterIndex = cipher.IndexOf(":");
String IV = cipher.Substring(delimiterIndex + 1);
return IV;
}
// Reference: https://stackoverflow.com/questions/311165/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-and-vice-versa
private static string ByteArrayToString(byte[] ba)
{
string hex = BitConverter.ToString(ba);
return hex.Replace("-", "");
}
}
}
Line 73 (where the exception is encountered) is the end of the using block for the StreamReader in the decrypt method:
using (StreamReader reader = new StreamReader(cryptStream))
{
outputString = reader.ReadToEnd();
}
I referenced the following question, but could not resolve my issue.
Originally, the data was encrypted in a PHP application, and decrypted using a C# application (using nearly exactly the same decrypt method above). Now, I am wanting to both encrypt and decrypt the data using C#; however, I must still be able to properly decrypt the existing data (that was encrypted using PHP), so I would rather not modify the decrypt method too much.
Any advice would be appreciated.
You have minor mistake here:
ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV);
using (MemoryStream memory = new MemoryStream(ivBytes))
You pass your IV value to decrypt, instead of actually encrypted bytes. Fix:
ICryptoTransform myDecrypter = myAes.CreateDecryptor(myAes.Key, myAes.IV);
using (MemoryStream memory = new MemoryStream(valBytes))
I'm trying to decrypt a string which is also base64 encoded, but I am receiving an when I try to decrypt the string.
The error I am receiving is:
{System.FormatException: Invalid length for a Base-64 char array or string.
at this line in the decrypt function below:
MemoryStream ms = new MemoryStream(Convert.FromBase64String(inString));
Encrpyt/Decrypt functions:
//ENCRYPT
public static bool stringEncrypt(string inString,ref string outstring)
{
try
{
if(String.IsNullOrEmpty(inString)){return false;}
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms,provider.CreateEncryptor(PWbytes,PWbytes),CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(cs);
sw.Write(inString);
sw.Flush();
cs.FlushFinalBlock();
sw.Flush();
outstring = Convert.ToBase64String(ms.GetBuffer(),0,(int)ms.Length);
return true;
}
catch(Exception ex)
{
clsCommonBase.AppendToExceptionFile("Encrypt : " + ex.Message);
return false;
}
}
//DECRPYT
public static bool stringDecrypt(string inString,ref string outstring)
{
try
{
if(String.IsNullOrEmpty(inString)){return false;};
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream(Convert.FromBase64String(inString));
CryptoStream cs = new CryptoStream(ms, provider.CreateDecryptor(PWbytes,PWbytes),CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cs);
outstring = sr.ReadToEnd();
return true;
}
catch(Exception ex)
{
clsCommonBase.AppendToExceptionFile("Decrypt : " + ex.Message);
return false;
}
}
Solved using the simple solution in the following link
How do I encode and decode a base64 string?
Also added some code in the encoding function to ensure the plain text string will be converted to a valid length base64 string.
Code:
public static string Base64Encode(string plainText)
{
//check plain text string and pad if needed
int mod4 = plainText.Length % 4;
if (mod4 > 0)
{
plainText += new string('=', 4 - mod4);
}
//convert to base64 and return
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
public static string Base64Decode(string base64EncodedData)
{
//decode base64 and return as string
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
I have some issues translating this PHP code into C#:
$hash = hash('sha384', $string_to_hash, true);
$base64Hash = strtr(base64_encode($hash), '+/', '-_');
Could you please help me?
Thanks!
Edit: I am updating this post with the whole PHP code to translate to C# because I can't get the same hashed Token with both Languages
$host = "100.200.100.200";
$url= "http://".$host.":1935/";
$stream = "vod/_definst_/test.smil";
$start = time();
$end = strtotime("+30 minutes");
$secret = "abcde";
$tokenName = "wowzatoken";
$hash = hash('sha384', $stream."?".$secret."&{$tokenName}endtime=".$end."&{$tokenName}starttime=".$start, true);
$base64Hash = strtr(base64_encode($hash), '+/', '-_');
$params = array("{$tokenName}starttime=".$start, "{$tokenName}endtime=".$end, "{$tokenName}hash=".$base64Hash);
$playbackURL = $url.$stream."/playlist.m3u8?";
foreach($params as $entry){
$playbackURL.= $entry."&";
}
$playbackURL = preg_replace("/(\&)$/","", $playbackURL);
echo $playbackURL;
I am not good at PHP, So I am not sure about strtr function. But I have tried to resolve your issue and give the some code below. try it.
class Program
{
public static string Base64Decode(string base64EncodedData)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
public static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
public static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
static void Main(string[] args)
{
string code = "SecretCode";
byte[] data = new byte[code.Length];
byte[] result;
data = GetBytes(code);
SHA384 shaM = new SHA384Managed();
result = shaM.ComputeHash(data);
string encodedString = GetString(result);
string ans = Base64Encode(encodedString);
ans = ans.Replace('+','-').Replace('/','_');
Console.Write(ans);
Console.Read();
}
}