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();
}
}
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 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
I have written the following code in swift to try and replicate something I have working in C#. I know I have gone wrong but I'm not exactly sure where.
The code is meant to encrypt a string and return an encrypted string. The encrypted string should remain the same every time. Unfortunately the webservice that this app connects to is a bit old and I have no control to change it.
Thank you for any assistance!
Swift code:
enum HMACAlgorithm {
case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
func toCCHmacAlgorithm() -> CCHmacAlgorithm {
var result: Int = 0
switch self {
case .MD5:
result = kCCHmacAlgMD5
case .SHA1:
result = kCCHmacAlgSHA1
case .SHA224:
result = kCCHmacAlgSHA224
case .SHA256:
result = kCCHmacAlgSHA256
case .SHA384:
result = kCCHmacAlgSHA384
case .SHA512:
result = kCCHmacAlgSHA512
}
return CCHmacAlgorithm(result)
}
func digestLength() -> Int {
var result: CInt = 0
switch self {
case .MD5:
result = CC_MD5_DIGEST_LENGTH
case .SHA1:
result = CC_SHA1_DIGEST_LENGTH
case .SHA224:
result = CC_SHA224_DIGEST_LENGTH
case .SHA256:
result = CC_SHA256_DIGEST_LENGTH
case .SHA384:
result = CC_SHA384_DIGEST_LENGTH
case .SHA512:
result = CC_SHA512_DIGEST_LENGTH
}
return Int(result)
}
}
class ViewController: UIViewController {
//Encypt Outlet
#IBOutlet weak var stringToEn: UITextField!
#IBOutlet weak var outputEn: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func encyptPressed(_ sender: Any) {
let input = stringToEn.text
let hmacResult: String = input!.hmac(algorithm: HMACAlgorithm.SHA1, key: "GVDev789")
outputEn.text = hmacResult
}
}
extension String{
func hmac(algorithm: HMACAlgorithm, key: String) -> String {
let cKey = key.cString(using: String.Encoding.utf8)
let cData = self.cString(using: String.Encoding.utf8)
var result = [CUnsignedChar](repeating: 0, count: Int(algorithm.digestLength()))
CCHmac(algorithm.toCCHmacAlgorithm(), cKey!, 1000, cData!, 1000, &result)
// cchmac Int(strlen(cKey!)) Int(strlen(cData!))
let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength())))
let hmacBase64 = hmacData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength76Characters)
return String(hmacBase64)
}
}
What is working in C#
public static string getEncryptedText(string input)
{
return EncryptText(input);
}
private static string EncryptText(string strText)
{
PasswordDeriveBytes pdbPassword = default(PasswordDeriveBytes);
PasswordDeriveBytes pdbIV = default(PasswordDeriveBytes);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
byte[] salt = {
(byte)Strings.Asc("G"),
(byte)Strings.Asc("V"),
(byte)Strings.Asc("D"),
(byte)Strings.Asc("e"),
(byte)Strings.Asc("v"),
(byte)Strings.Asc("7"),
(byte)Strings.Asc("8"),
(byte)Strings.Asc("9")
};
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = default(CryptoStream);
string plainText = strText;
byte[] plainBytes = null;
plainBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
pdbPassword = new PasswordDeriveBytes("Password", salt);
pdbPassword.HashName = "SHA1";
pdbPassword.IterationCount = 1000;
DES.Key = pdbPassword.GetBytes(8);
pdbIV = new PasswordDeriveBytes("PbeIv", salt);
pdbIV.HashName = "SHA1";
pdbIV.IterationCount = 1000;
DES.IV = pdbIV.GetBytes(8);
cs = new CryptoStream(ms, DES.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(plainBytes, 0, plainBytes.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
}
}
I use Login control and membership asp.net 4. and create user with passwrod = "12345678", my password hash in database is "h8A5hga0Cy93JsKxYnJl/U2AluU=" and passwordsalt is "UhVlqavmEX9CiKcUXkSwCw==".
Then I use this code for hash password in other project:
public string HashPassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Encoding.Unicode.GetBytes(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
private void button2_Click(object sender, EventArgs e)
{
textBox2.Text = HashPassword("12345678", "UhVlqavmEX9CiKcUXkSwCw==");
}
textBox2.Text = "YM/JNwFqlL+WA3SINQp48BIxZRI=". But textBox2.Text != my password hashed with login control in database. it is "h8A5hga0Cy93JsKxYnJl/U2AluU=".
Edit:
It is algorithm hash with login control?
public string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Convert.FromBase64String(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
MD5 and SHA1 are not encryption algorithms. They are hashing algorithms.
It is a one way formula. Running MD5 or SHA1 on a particular string gives a hash that is always the same. It isn't possible to reverse the function to get back to the original string.
so, you can not decrypt.
if you want encrypt & decrypt, you can use below methods.
public class Encryption
{
private const string _defaultKey = "*3ld+43j";
public static string Encrypt(string toEncrypt, string key)
{
var des = new DESCryptoServiceProvider();
var ms = new MemoryStream();
VerifyKey(ref key);
des.Key = HashKey(key, des.KeySize / 8);
des.IV = HashKey(key, des.KeySize / 8);
byte[] inputBytes = Encoding.UTF8.GetBytes(toEncrypt);
var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputBytes, 0, inputBytes.Length);
cs.FlushFinalBlock();
return HttpServerUtility.UrlTokenEncode(ms.ToArray());
}
public static string Decrypt(string toDecrypt, string key)
{
var des = new DESCryptoServiceProvider();
var ms = new MemoryStream();
VerifyKey(ref key);
des.Key = HashKey(key, des.KeySize / 8);
des.IV = HashKey(key, des.KeySize / 8);
byte[] inputBytes = HttpServerUtility.UrlTokenDecode(toDecrypt);
var cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputBytes, 0, inputBytes.Length);
cs.FlushFinalBlock();
var encoding = Encoding.UTF8;
return encoding.GetString(ms.ToArray());
}
/// <summary>
/// Make sure key is exactly 8 characters
/// </summary>
/// <param name="key"></param>
private static void VerifyKey(ref string key)
{
if (string.IsNullOrEmpty(key))
key = _defaultKey;
key = key.Length > 8 ? key.Substring(0, 8) : key;
if (key.Length < 8)
{
for (int i = key.Length; i < 8; i++)
{
key += _defaultKey[i];
}
}
}
private static byte[] HashKey(string key, int length)
{
var sha = new SHA1CryptoServiceProvider();
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
byte[] hash = sha.ComputeHash(keyBytes);
byte[] truncateHash = new byte[length];
Array.Copy(hash, 0, truncateHash, 0, length);
return truncateHash;
}
}
try
private static string CreateSalt()
{
//Generate a cryptographic random number.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buff = new byte[32];
rng.GetBytes(buff);
//Return a Base64 string representation of the random number.
return Convert.ToBase64String(buff);
}
private static string CreatePasswordHash(string pwd, string salt)
{
string saltAndPwd = String.Concat(pwd, salt);
string hashedPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "sha1");
return hashedPwd;
}
Login control doesn't encode or decode password. Instead, it is MembershipProvider's job.
Here is the Hash Algorithm used by new ASP.Net Universal Provider.
private static string GenerateSalt()
{
byte[] numArray = new byte[16];
(new RNGCryptoServiceProvider()).GetBytes(numArray);
string base64String = Convert.ToBase64String(numArray);
return base64String;
}
private string EncodePassword(string pass, int passwordFormat, string salt)
{
byte[] numArray;
byte[] numArray1;
string base64String;
bool length = passwordFormat != 0;
if (length)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] numArray2 = Convert.FromBase64String(salt);
byte[] numArray3 = null;
HashAlgorithm hashAlgorithm = HashAlgorithm.Create(Membership.HashAlgorithmType);
if (hashAlgorithm as KeyedHashAlgorithm == null)
{
numArray1 = new byte[(int) numArray2.Length + (int) bytes.Length];
Buffer.BlockCopy(numArray2, 0, numArray1, 0, (int) numArray2.Length);
Buffer.BlockCopy(bytes, 0, numArray1, (int) numArray2.Length, (int) bytes.Length);
numArray3 = hashAlgorithm.ComputeHash(numArray1);
}
else
{
KeyedHashAlgorithm keyedHashAlgorithm = (KeyedHashAlgorithm) hashAlgorithm;
if (keyedHashAlgorithm.Key.Length != numArray2.Length)
{
if (keyedHashAlgorithm.Key.Length >= (int) numArray2.Length)
{
numArray = new byte[(int) keyedHashAlgorithm.Key.Length];
int num = 0;
while (true)
{
length = num < (int) numArray.Length;
if (!length)
{
break;
}
int num1 = Math.Min((int) numArray2.Length, (int) numArray.Length - num);
Buffer.BlockCopy(numArray2, 0, numArray, num, num1);
num = num + num1;
}
keyedHashAlgorithm.Key = numArray;
}
else
{
numArray = new byte[(int) keyedHashAlgorithm.Key.Length];
Buffer.BlockCopy(numArray2, 0, numArray, 0, (int) numArray.Length);
keyedHashAlgorithm.Key = numArray;
}
}
else
{
keyedHashAlgorithm.Key = numArray2;
}
numArray3 = keyedHashAlgorithm.ComputeHash(bytes);
}
base64String = Convert.ToBase64String(numArray3);
}
else
{
base64String = pass;
}
return base64String;
}
I am trying to write a function to take a string and sha512 it like so?
public string SHA512(string input)
{
string hash;
~magic~
return hash;
}
What should the magic be?
Your code is correct, but you should dispose of the SHA512Managed instance:
using (SHA512 shaM = new SHA512Managed())
{
hash = shaM.ComputeHash(data);
}
512 bits are 64 bytes.
To convert a string to a byte array, you need to specify an encoding. UTF8 is okay if you want to create a hash code:
var data = Encoding.UTF8.GetBytes("text");
using (...
This is from one of my projects:
public static string SHA512(string input)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(input);
using (var hash = System.Security.Cryptography.SHA512.Create())
{
var hashedInputBytes = hash.ComputeHash(bytes);
// Convert to text
// StringBuilder Capacity is 128, because 512 bits / 8 bits in byte * 2 symbols for byte
var hashedInputStringBuilder = new System.Text.StringBuilder(128);
foreach (var b in hashedInputBytes)
hashedInputStringBuilder.Append(b.ToString("X2"));
return hashedInputStringBuilder.ToString();
}
}
Please, note:
SHA512 object is disposed ('using' section), so we do not have any resource leaks.
StringBuilder is used for efficient hex string building.
512/8 = 64, so 64 is indeed the correct size. Perhaps you want to convert it to hexadecimal after the SHA512 algorithm.
See also: How do you convert Byte Array to Hexadecimal String, and vice versa?
You might try these lines:
public static string GenSHA512(string s, bool l = false)
{
string r = "";
try
{
byte[] d = Encoding.UTF8.GetBytes(s);
using (SHA512 a = new SHA512Managed())
{
byte[] h = a.ComputeHash(d);
r = BitConverter.ToString(h).Replace("-", "");
}
r = (l ? r.ToLowerInvariant() : r);
}
catch
{
}
return r;
}
It is disposed at the end
It's safe
Supports lower case
Instead of WinCrypt-API using System.Security.Cryptography, you can also use BouncyCastle:
public static byte[] SHA512(string text)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(text);
Org.BouncyCastle.Crypto.Digests.Sha512Digest digester = new Org.BouncyCastle.Crypto.Digests.Sha512Digest();
byte[] retValue = new byte[digester.GetDigestSize()];
digester.BlockUpdate(bytes, 0, bytes.Length);
digester.DoFinal(retValue, 0);
return retValue;
}
If you need the HMAC-version (to add authentication to the hash)
public static byte[] HmacSha512(string text, string key)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
var hmac = new Org.BouncyCastle.Crypto.Macs.HMac(new Org.BouncyCastle.Crypto.Digests.Sha512Digest());
hmac.Init(new Org.BouncyCastle.Crypto.Parameters.KeyParameter(System.Text.Encoding.UTF8.GetBytes(key)));
byte[] result = new byte[hmac.GetMacSize()];
hmac.BlockUpdate(bytes, 0, bytes.Length);
hmac.DoFinal(result, 0);
return result;
}
Keeping it simple:
using (SHA512 sha512 = new SHA512Managed())
{
password = Encoding.UTF8.GetString(sha512.ComputeHash(Encoding.UTF8.GetBytes(password)));
}
I'm not sure why you are expecting 128.
8 bits in a byte. 64 bytes. 8 * 64 = 512 bit hash.
From the MSDN Documentation:
The hash size for the SHA512Managed algorithm is 512 bits.
You could use the System.Security.Cryptography.SHA512 class
MSDN on SHA512
Here is an example, straigt from the MSDN
byte[] data = new byte[DATA_SIZE];
byte[] result;
SHA512 shaM = new SHA512Managed();
result = shaM.ComputeHash(data);
UnicodeEncoding UE = new UnicodeEncoding();
byte[] message = UE.GetBytes(password);
SHA512Managed hashString = new SHA512Managed();
string hexNumber = "";
byte[] hashValue = hashString.ComputeHash(message);
foreach (byte x in hashValue)
{
hexNumber += String.Format("{0:x2}", x);
}
string hashData = hexNumber;
I used the following
public static string ToSha512(this string inputString)
{
if (string.IsNullOrWhiteSpace(inputString)) return string.Empty;
using (SHA512 shaM = new SHA512Managed())
{
return Convert.ToBase64String(shaM.ComputeHash(Encoding.UTF8.GetBytes(inputString)));
}
}
Made it into an extension method in my ExtensionUtility.cs class
public static string SHA512(this string plainText)
{
using (SHA512 shaM = new SHA512Managed())
{
var buffer = Encoding.UTF8.GetBytes(plainText);
var hashedInputBytes = shaM.ComputeHash(buffer);
return BitConverter.ToString(hashedInputBytes).Replace("-", "");
}
}