Convert php decryption function to C# responds differently result - c#

I created a service that encrypts and stores keys using PHP. The Service returns an encrypted response to the client. The client program will need to decrypt the encrypted data. But the decrypt function I wrote in PHP responds differently in C#.
So my php Function:
<?php
$key = 12;
$string = "rVOlpZOlp6RUa2RhY11UpKeUlZalpFRrpqOnll5TlpKmklRrrVOempWQm5VUa2NdVJKnpZqgpFNsU4FYnaWTnlKKk6Knk6GnVF1UoKSYk5+bq5Olm6CgkKCSn5ZUa1R+e35ziVKEgXeGiHODd1F5g4GGglNeU6GjmZKgmqySppqhn5GWn5KbnVRrVKSnoaKgpKVynpuek6mZo6Gmol+VoJ9TXlOho5mSoJqskqaaoZ+RoZqgoJZUa1SFk6SanJefplF1mqaqVF1UnZuUkZaqoZujl5VUa1RjYmNnXmNiX2NkUWJhbGFia2JhVF1UnZuUl5+llpGUpJaTpZeVVGtUY2JjZF5iYl9iZFNeU56alZagpJeQl6mimqSWllNsU2RhZGZfYmNeZGNUXVSVl6eblJeQnpqfmqZTbGJirl5Tn5alpJOYl1NsU4ugp6NSnZuUl5+lllKcl6pSkpWlm6eTpZeVVK4=";
$result = '';
$string = base64_decode($string);
for ($i = 0, $k = strlen($string); $i < $k; $i++) {
$char = substr($string, $i, 1);
$keyChar = substr($key, ($i % strlen($key)) - 1, 1);
$char = chr(ord($char) - ord($keyChar));
$result .= $char;
}
echo $result;
?>
It returns:
{"status":201,"success":true,"data":{"lic_id":1,"author":"Author Name","organization_name":"XXXXX XXXXXX GROUP","organization_email":"support#xxxxxx.com","organization_phone":"City/City","lic_expired":"2025-11-22 00:00:00","license_created":"2022-01-12","license_expired":"2025-11-22","device_limit":10},"message":"Your license key activated"}
Now I have converted the above function to C #. The result is strange.
My C# code:
static void Main(string[] args)
{
string key = "rVOlpZOlp6RUa2RhY11UpKeUlZalpFRrpqOnll5TlpKmklRrrVOempWQm5VUa2NdVJKnpZqgpFNsU4FYnaWTnlKKk6Knk6GnVF1UoKSYk5+bq5Olm6CgkKCSn5ZUa1R+e35ziVKEgXeGiHODd1F5g4GGglNeU6GjmZKgmqySppqhn5GWn5KbnVRrVKSnoaKgpKVynpuek6mZo6Gmol+VoJ9TXlOho5mSoJqskqaaoZ+RoZqgoJZUa1SFk6SanJefplF1mqaqVF1UnZuUkZaqoZujl5VUa1RjYmNnXmNiX2NkUWJhbGFia2JhVF1UnZuUl5+llpGUpJaTpZeVVGtUY2JjZF5iYl9iZFNeU56alZagpJeQl6mimqSWllNsU2RhZGZfYmNeZGNUXVSVl6eblJeQnpqfmqZTbGJirl5Tn5alpJOYl1NsU4ugp6NSnZuUl5+lllKcl6pSkpWlm6eTpZeVVK4=";
Console.WriteLine(DecryptIt(key));
}
static string DecryptIt (string key)
{
/// <summary>
/// Decrypt key using custom algarithm
/// </summary>
///
string keyLength = "12";
string result = "";
byte[] data = Convert.FromBase64String(key);
key = Encoding.UTF8.GetString(data);
for (int i = 0; i < key.Length; i++)
{
int res = (i % keyLength.Length) - 1;
int res2 = res < 0 ? keyLength.Length + res : res;
//Console.WriteLine(res2.ToString());
//Console.WriteLine(key.Length);
char ch = key.Substring(i, 1).ToCharArray()[0];
char KeyChar = keyLength.Substring(res2, 1).ToCharArray()[0];
ch = (char)((byte)ch - KeyChar);
result += ch.ToString();
}
return result;
}
}
It returns:
E"EIEIEI":201,"IEIEIEI":EIEI,"EIEI":E"EIEIEI":1,"IEIEIE":"E'EIEI IEIEIEI","IEIEIEIEIEIEIEIEI":"MIMAI IEFEIAIE GIEIE","EIEIEIEIEIEIEIEIEI":"IEIEIEI#IEIEIEIEIE.EIE","EIEIEIEIEIEIEIEIEI":"IEIEIEIE CIEI","IEIEIEIEIEI":"2025-11-22 00:00:00","IEIEIEIEIEIEIEI":"2022-01-12","EIEIEIEIEIEIEIE":"2025-11-22","IEIEIEIEIEIE":10I,"EIEIEIE":"EIEI IEIEIEI IEI IEIEIEIEI"I
I can't understand where I'm making a mistake. The letters are completely different.
If I do it like this:
ch = (char)((char)ch - (char)KeyChar);
It returns:
?"??????":201,"???????":????,"????":?"??????":1,"??????":"?'???? ???????","?????????????????":"MIMA? ??F??A?E G????","??????????????????":"???????#??????????.???","??????????????????":"???????? C???","???????????":"2025-11-22 00:00:00","???????????????":"2022-01-12","???????????????":"2025-11-22","????????????":10?,"???????":"???? ??????? ??? ?????????"?
Can anyone help to solve this problem?

The line:
key = Encoding.UTF8.GetString(data);
is incorrect, you want to deal with bytes directly, not converting it to a utf-8 string.
In fact, the decoded base64 is not even a valid UTF-8 string.
Working Python port:
#!/usr/bin/env python3
import base64
a = "rVOlpZOlp6RUa2RhY11UpKeUlZalpFRrpqOnll5TlpKmklRrrVOempWQm5VUa2NdVJKnpZqgpFNsU4FYnaWTnlKKk6Knk6GnVF1UoKSYk5+bq5Olm6CgkKCSn5ZUa1R+e35ziVKEgXeGiHODd1F5g4GGglNeU6GjmZKgmqySppqhn5GWn5KbnVRrVKSnoaKgpKVynpuek6mZo6Gmol+VoJ9TXlOho5mSoJqskqaaoZ+RoZqgoJZUa1SFk6SanJefplF1mqaqVF1UnZuUkZaqoZujl5VUa1RjYmNnXmNiX2NkUWJhbGFia2JhVF1UnZuUl5+llpGUpJaTpZeVVGtUY2JjZF5iYl9iZFNeU56alZagpJeQl6mimqSWllNsU2RhZGZfYmNeZGNUXVSVl6eblJeQnpqfmqZTbGJirl5Tn5alpJOYl1NsU4ugp6NSnZuUl5+lllKcl6pSkpWlm6eTpZeVVK4="
s = base64.b64decode(a)
key = b'12'
result = ''
for i in range(len(s)):
char = s[i]
pos = (i % len(key)) - 1
if pos < 0:
pos += len(key)
keychar = key[(i % len(key)) - 1]
result += chr((char) - (keychar))
print(result)
UPDATE: C#
using System;
using System.Text;
class Untitled
{
static void Main(string[] args)
{
string key = "rVOlpZOlp6RUa2RhY11UpKeUlZalpFRrpqOnll5TlpKmklRrrVOempWQm5VUa2NdVJKnpZqgpFNsU4FYnaWTnlKKk6Knk6GnVF1UoKSYk5+bq5Olm6CgkKCSn5ZUa1R+e35ziVKEgXeGiHODd1F5g4GGglNeU6GjmZKgmqySppqhn5GWn5KbnVRrVKSnoaKgpKVynpuek6mZo6Gmol+VoJ9TXlOho5mSoJqskqaaoZ+RoZqgoJZUa1SFk6SanJefplF1mqaqVF1UnZuUkZaqoZujl5VUa1RjYmNnXmNiX2NkUWJhbGFia2JhVF1UnZuUl5+llpGUpJaTpZeVVGtUY2JjZF5iYl9iZFNeU56alZagpJeQl6mimqSWllNsU2RhZGZfYmNeZGNUXVSVl6eblJeQnpqfmqZTbGJirl5Tn5alpJOYl1NsU4ugp6NSnZuUl5+lllKcl6pSkpWlm6eTpZeVVK4=";
Console.WriteLine(DecryptIt(key));
}
static string DecryptIt (string key)
{
/// <summary>
/// Decrypt key using custom algarithm
/// </summary>
///
byte[] data = Convert.FromBase64String(key);
byte[] keyLength = new byte[] {0x31, 0x32}; //"12"
byte[] result = new byte[data.Length];
for (int i = 0; i < data.Length; i++)
{
int res = (i % keyLength.Length) - 1;
int res2 = res < 0 ? keyLength.Length + res : res;
//Console.WriteLine(res2.ToString());
//Console.WriteLine(key.Length);
byte ch = data[i];
byte KeyChar = keyLength[res2];
ch = (byte)(ch - KeyChar);
result[i] = ch;
}
return Encoding.UTF8.GetString(result);
}
}
Ideone

Related

Android base64 hash mismatch with server side hash using C# script

I am creating base64 hash using HMAC SHA256 in my Android application. and send it on server for match with server side hash.
Following this tutorial.
Working Android code:
public String getHash(String data,String key)
{
try
{
String secret = key;
String message = data;
Mac sha256_HMAC = Mac.getInstance("HmacMD5");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacMD5");
sha256_HMAC.init(secret_key);
String hash = Base64.encodeBase64String(sha256_HMAC.doFinal(message.getBytes()));
System.out.println(hash);
return hash;
}
catch (Exception e){
System.out.println("Error");
}
}
server code is in C# script and its as per below
using System.Security.Cryptography;
namespace Test
{
public class MyHmac
{
private string CreateToken(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
}
}
but hash key generated at android side is not match with server side and below is objective c code which generate same as C# code
objective c code:
#import "AppDelegate.h"
#import <CommonCrypto/CommonHMAC.h>
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSString* key = #"secret";
NSString* data = #"Message";
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *hash = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSLog(#"%#", hash);
NSString* s = [AppDelegate base64forData:hash];
NSLog(s);
}
+ (NSString*)base64forData:(NSData*)theData
{
const uint8_t* input = (const uint8_t*)[theData bytes];
NSInteger length = [theData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) { value |= (0xFF & input[j]);
}
}
NSInteger theIndex = (i / 3) * 4; output[theIndex + 0] = table[(value >> 18) & 0x3F];
output[theIndex + 1] = table[(value >> 12) & 0x3F];
output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
#end
please help me to sove out this issue,
Thanks in advance.
I have solved this issue by changing HmacSHA256 to HmacMD5 and its give same hash value as given by C# code.
I have updated my question with working code. check it
I suspect this is an encoding issue.
In one sample you specify the string should be encoded using ASCII when converting the string to a byte array. In the other sample you do not specify an encoding.
If the default encoding is anything other than ASCII that means the byte arrays will be different, leading to different hash results.
In android secret.getBytes may get UTF-16 bytes, check the length of the result. In general separate such functions out into separate statements for easier debugging.
Not the answer, rather a demonstration of a simpler Obj-C implementation and provides the hash and Base64 vaules:
NSString* key = #"secret";
NSString* data = #"Message";
NSData *keyData = [key dataUsingEncoding:NSASCIIStringEncoding];
NSData *dataData = [data dataUsingEncoding:NSASCIIStringEncoding];
NSMutableData *hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, keyData.bytes, keyData.length , dataData.bytes, dataData.length, hash.mutableBytes);
NSLog(#"hash: %#", hash);
NSString* s = [hash base64EncodedStringWithOptions:0];
NSLog(#"s: %#", s);
Output:
hash: <aa747c50 2a898200 f9e4fa21 bac68136 f886a0e2 7aec70ba 06daf2e2 a5cb5597>
s: qnR8UCqJggD55PohusaBNviGoOJ67HC6Btry4qXLVZc=

How to encrypt a string using public key cryptography

I am trying to implement my own RSA encryption engine. Given these RSA algorithm values:
p = 61. // A prime number.
q = 53. // Also a prime number.
n = 3233. // p * q.
totient = 3120. // (p - 1) * (q - 1)
e = 991. // Co-prime to the totient (co-prime to 3120).
d = 1231. // d * e = 1219921, which is equal to the relation where 1 + k * totient = 1219921 when k = 391.
I am trying to write a method to encrypt each byte in a string and return back an encrypted string:
public string Encrypt(string m, Encoding encoding)
{
byte[] bytes = encoding.GetBytes(m);
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = (byte)BigInteger.ModPow(bytes[i], e, n);
}
string encryptedString = encoding.GetString(bytes);
Console.WriteLine("Encrypted {0} as {1}.", m, encryptedString);
return encryptedString;
}
The obvious issue here is that BigInteger.ModPow(bytes[i], e, n) may be too large to fit into a byte-space; it could result in values over 8 bits in size. How do you get around this issue while still being able to decrypt an encrypted string of bytes back into a regular string?
Update: Even encrypting from byte[] to byte[], you reach a case where encrypting that byte using the RSA algorithm goes beyond the size limit of a byte:
public byte[] Encrypt(string m, Encoding encoding)
{
byte[] bytes = encoding.GetBytes(m);
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = (byte)BigInteger.ModPow(bytes[i], e, n);
}
return bytes;
}
Update: My issue is that encryption would cause a greater number of bytes than the initial input string had:
public byte[] Encrypt(string m, Encoding encoding)
{
byte[] bytes = encoding.GetBytes(m);
byte[] returnBytes = new byte[0];
for (int i = 0; i < bytes.Length; i++)
{
byte[] result = BigInteger.ModPow(bytes[i], (BigInteger)e, n).ToByteArray();
int preSize = returnBytes.Length;
Array.Resize(ref returnBytes, returnBytes.Length + result.Length);
result.CopyTo(returnBytes, preSize);
}
return returnBytes;
}
public string Decrypt(byte[] c, Encoding encoding)
{
byte[] returnBytes = new byte[0];
for (int i = 0; i < c.Length; i++)
{
byte[] result = BigInteger.ModPow(c[i], d, n).ToByteArray();
int preSize = returnBytes.Length;
Array.Resize(ref returnBytes, returnBytes.Length + result.Length);
result.CopyTo(returnBytes, preSize);
}
string decryptedString = encoding.GetString(returnBytes);
return decryptedString;
}
If you ran this code like this:
byte[] encryptedBytes = engine.Encrypt("Hello, world.", Encoding.UTF8);
Console.WriteLine(engine.Decrypt(encryptedBytes, Encoding.UTF8));
The output would be this:
?♥D
?♥→☻►♦→☻►♦oD♦8? ?♠oj?♠→☻►♦;♂?♠♂♠?♠
Obviously, the output is not the original string because I can't just try decrypting each byte at a time, since sometimes two or more bytes of the cypher-text represent the value of one integer that I need to decrypt back to one byte of the original string...so I want to know what the standard mechanism for handling this is.
Your basic code for encrypting and decrypting each byte - the call to ModPow - is working, but you're going about the "splitting the message up and encrypting each piece" inappropriately.
To show that the ModPow part - i.e. the maths - is fine, here's code based on yours, which encrypts a string to a BigInteger[] and back:
using System;
using System.Linq;
using System.Numerics;
using System.Text;
class Test
{
const int p = 61;
const int q = 53;
const int n = 3233;
const int totient = 3120;
const int e = 991;
const int d = 1231;
static void Main()
{
var encrypted = Encrypt("Hello, world.", Encoding.UTF8);
var decrypted = Decrypt(encrypted, Encoding.UTF8);
Console.WriteLine(decrypted);
}
static BigInteger[] Encrypt(string text, Encoding encoding)
{
byte[] bytes = encoding.GetBytes(text);
return bytes.Select(b => BigInteger.ModPow(b, (BigInteger)e, n))
.ToArray();
}
static string Decrypt(BigInteger[] encrypted, Encoding encoding)
{
byte[] bytes = encrypted.Select(bi => (byte) BigInteger.ModPow(bi, d, n))
.ToArray();
return encoding.GetString(bytes);
}
}
Next you need to read more about how a byte[] is encrypted into another byte[] using RSA, including all the different padding schemes etc. There's a lot more to it than just calling ModPow on each byte.
But to reiterate, you should not be doing this to end up with a production RSA implementation. The chances of you doing that without any security flaws are very slim indeed. It's fine to do this for academic interest, to learn more about the principles of cryptography, but leave the real implementations to experts. (I'm far from an expert in this field - there's no way I'd start implementing my own encryption...)
Note: I updated this answer. Please scroll down to the update for how it should actually be implemented because this first way of doing it is not the correct way of doing RSA encryption.
One way I can think to do it is like this (but may not be compliant to standards), and also, note this does not pad:
public byte[] Encrypt(string m, Encoding encoding)
{
byte[] bytes = encoding.GetBytes(m);
byte[] returnBytes = new byte[0];
for (int i = 0; i < bytes.Length; i++)
{
byte[] result = BigInteger.ModPow(bytes[i], (BigInteger)e, n).ToByteArray();
int preSize = returnBytes.Length;
Array.Resize(ref returnBytes, returnBytes.Length + result.Length + 1);
(new byte[] { (byte)(result.Length) }).CopyTo(returnBytes, preSize);
result.CopyTo(returnBytes, preSize + 1);
}
return returnBytes;
}
public string Decrypt(byte[] c, Encoding encoding)
{
byte[] returnBytes = new byte[0];
for (int i = 0; i < c.Length; i++)
{
int dataLength = (int)c[i];
byte[] result = new byte[dataLength];
for (int j = 0; j < dataLength; j++)
{
i++;
result[j] = c[i];
}
BigInteger integer = new BigInteger(result);
byte[] integerResult = BigInteger.ModPow(integer, d, n).ToByteArray();
int preSize = returnBytes.Length;
Array.Resize(ref returnBytes, returnBytes.Length + integerResult.Length);
integerResult.CopyTo(returnBytes, preSize);
}
string decryptedString = encoding.GetString(returnBytes);
return decryptedString;
}
This has the potential of being cross-platform because you have the option of using a different datatype to represent e or n and pass it to a C# back-end service like that. Here is a test:
string stringToEncrypt = "Mary had a little lamb.";
Console.WriteLine("Encrypting the string: {0}", stringToEncrypt);
byte[] encryptedBytes = engine.Encrypt(stringToEncrypt, Encoding.UTF8);
Console.WriteLine("Encrypted text: {0}", Encoding.UTF8.GetString(encryptedBytes));
Console.WriteLine("Decrypted text: {0}", engine.Decrypt(encryptedBytes, Encoding.UTF8));
Output:
Encrypting the string: Mary had a little lamb.
Encrypted text: ☻6☻1♦☻j☻☻&♀☻g♦☻t☻☻1♦☻? ☻g♦☻1♦☻g♦☻?♥☻?☻☻7☺☻7☺☻?♥☻?♂☻g♦☻?♥☻1♦☻$☺☻
c ☻?☻
Decrypted text: Mary had a little lamb.
Update: Everything I said earlier is completely wrong in the implementation of RSA. Wrong, wrong, wrong! This is the correct way to do RSA encryption:
Convert your string to a BigInteger datatype.
Make sure your integer is smaller than the value of n that you've calculated for your algorithm, otherwise you won't be able to decypher it.
Encrypt the integer. RSA works on integer encryption only. This is clear.
Decrypt it from the encrypted integer.
I can't help but wonder that the BigInteger class was mostly created for cryptography.
As an example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace BytePadder
{
class Program
{
const int p = 61;
const int q = 53;
const int n = 3233;
const int totient = 3120;
const int e = 991;
const int d = 1231;
static void Main(string[] args)
{
// ---------------------- RSA Example I ----------------------
// Shows how an integer gets encrypted and decrypted.
BigInteger integer = 1000;
BigInteger encryptedInteger = Encrypt(integer);
Console.WriteLine("Encrypted Integer: {0}", encryptedInteger);
BigInteger decryptedInteger = Decrypt(encryptedInteger);
Console.WriteLine("Decrypted Integer: {0}", decryptedInteger);
// --------------------- RSA Example II ----------------------
// Shows how a string gets encrypted and decrypted.
string unencryptedString = "A";
BigInteger integer2 = new BigInteger(Encoding.UTF8.GetBytes(unencryptedString));
Console.WriteLine("String as Integer: {0}", integer2);
BigInteger encryptedInteger2 = Encrypt(integer2);
Console.WriteLine("String as Encrypted Integer: {0}", encryptedInteger2);
BigInteger decryptedInteger2 = Decrypt(encryptedInteger2);
Console.WriteLine("String as Decrypted Integer: {0}", decryptedInteger2);
string decryptedIntegerAsString = Encoding.UTF8.GetString(decryptedInteger2.ToByteArray());
Console.WriteLine("Decrypted Integer as String: {0}", decryptedIntegerAsString);
Console.ReadLine();
}
static BigInteger Encrypt(BigInteger integer)
{
if (integer < n)
{
return BigInteger.ModPow(integer, e, n);
}
throw new Exception("The integer must be less than the value of n in order to be decypherable!");
}
static BigInteger Decrypt(BigInteger integer)
{
return BigInteger.ModPow(integer, d, n);
}
}
}
Example output:
Encrypted Integer: 1989
Decrypted Integer: 1000
String as Integer: 65
String as Encrypted Integer: 1834
String as Decrypted Integer: 65
Decrypted Integer as String: A
If you are looking to use RSA encryption in C# then you should not be attempting to build your own. For starters the prime numbers you have chosen are probably to small. P and Q are supposed to be large prime numbers.
You should check out some other question/answers:
how to use RSA to encrypt files (huge data) in C#
RSA Encryption of large data in C#
And other references:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.encrypt(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx

Try To Code HMAC-SHA256 using C#.Net

i try to coding HMAC-SHA256 Algorithm as Function
HMAC (K,m) = H((K ⊕ opad) ∥ H((K ⊕ ipad) ∥ m))
where
H is a cryptographic hash function,
K is a secret key padded to the right with extra zeros to the input block size of the hash function, or the hash of the original key if it's longer than that block size,
m is the message to be authenticated,
∥ denotes concatenation,
⊕ denotes exclusive or (XOR),
opad is the outer padding (0x5c5c5c…5c5c, one-block-long hexadecimal constant),
ipad is the inner padding(0x363636…3636, one-block-long hexadecimal constant).
and this my code
public static string MyHMACHash(string key , string message)
{
Encoding encoding = Encoding.UTF8;
//var md = System.Security.Cryptography.MD5CryptoServiceProvider.Create();
SHA256 hash = SHA256Managed.Create();
byte[] trans_5C = new byte[32];
byte[] trans_36 = new byte[32];
byte[] b_key = encoding.GetBytes(key);
// TODO: also check if key is to short
if (b_key.Length > 32)
b_key = hash.ComputeHash(b_key);
for (int i = 0; i < 32; i++)
{
trans_5C[i] = 92;
trans_36[i] = 54;
if (i < key.Length)
{
trans_5C[i] ^= b_key[i];
trans_36[i] ^= b_key[i];
}
}
byte[] inner = hash.ComputeHash(trans_36.Concat(encoding.GetBytes(message)).ToArray());
var Fhash = hash.ComputeHash(trans_5C.Concat(inner).ToArray());
StringBuilder sb = new StringBuilder();
foreach (byte b in Fhash)
sb.Append(b.ToString("x2"));
string result = sb.ToString(); // = 9036a1a3f654aefeab426e9f7e17288e
return result;
}
but when i try to test this code the result Non-conforming to standard HMAC-SHA256 hashing on the standard internet web sites
Here is the modified version with custom HMAC generation. Main thing to consider is that Input Block Size referred in the K, is the hash algorithm block size; not returned hashed byte length. For SHA256, block size is 64 bytes. I believe you were using 32byte block size. You can find different block size references here: http://en.wikipedia.org/wiki/Secure_Hash_Algorithm.
public static string MyHMACHash(string key, string message)
{
Encoding encoding = Encoding.UTF8;
//Reference http://en.wikipedia.org/wiki/Secure_Hash_Algorithm
//SHA256 block size is 512 bits => 64 bytes.
const int HashBlockSize = 64;
var keyBytes = encoding.GetBytes(key);
var opadKeySet = new byte[HashBlockSize];
var ipadKeySet = new byte[HashBlockSize];
if (keyBytes.Length > HashBlockSize)
{
keyBytes = GetHash(keyBytes);
}
// This condition is independent of previous
// condition. If previous was true
// we still need to execute this to make keyBytes same length
// as blocksize with 0 padded if its less than block size
if (keyBytes.Length < HashBlockSize)
{
var newKeyBytes = new byte[HashBlockSize];
keyBytes.CopyTo(newKeyBytes, 0);
keyBytes = newKeyBytes;
}
for (int i = 0; i < keyBytes.Length; i++)
{
opadKeySet[i] = (byte)(keyBytes[i] ^ 0x5C);
ipadKeySet[i] = (byte)(keyBytes[i] ^ 0x36);
}
var hash = GetHash(ByteConcat(opadKeySet,
GetHash(ByteConcat(ipadKeySet, encoding.GetBytes(message)))));
// Convert to standard hex string
return hash.Select<byte, string>(a => a.ToString("x2"))
.Aggregate<string>((a, b) => string.Format("{0}{1}", a, b));
}
public static byte[] GetHash(byte[] bytes)
{
using (var hash = new SHA256Managed())
{
return hash.ComputeHash(bytes);
}
}
public static byte[] ByteConcat(byte[] left, byte[] right)
{
if (null == left)
{
return right;
}
if (null == right)
{
return left;
}
byte[] newBytes = new byte[left.Length + right.Length];
left.CopyTo(newBytes, 0);
right.CopyTo(newBytes, left.Length);
return newBytes;
}

Byte array cryptography in C#

I want to create a nice cryptography using bitwise operators.
However I fail to do so.
I want it to have bitwise operators using a byte array to encrypt and decrypt my byte array.
public class Cryptographer
{
private byte[] Keys { get; set; }
public Cryptographer(string password)
{
Keys = Encoding.ASCII.GetBytes(password);
}
public void Encrypt(byte[] data)
{
for(int i = 0; i < data.Length; i++)
{
data[i] = (byte) (data[i] & Keys[i]);
}
}
public void Decrypt(byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = (byte)(Keys[i] & data[i]);
}
}
}
I know this is wrong, thats why I need help.
I simply want it to use 1 string to encrypt and decrypt all data.
This is what is sometimes known as 'craptography', because it provides the illusion of security while being functionally useless in protecting anything. Use the framework classes if you want to do cryptography right, because it's extremely difficult to roll your own.
Take a look at this for advice on what you are trying to do (encrypt/decrypt) - http://msdn.microsoft.com/en-us/library/e970bs09.aspx. Really your requirements should determine what classes you decide to use. This has good background: http://msdn.microsoft.com/en-us/library/92f9ye3s.aspx
For simple encrypt/decrypt (if this is what you need) DPAPI may be the simplest way.
You seem to be trying to implement the XOR cipher. XOR is ^ in C#:
public void Crypt(byte[] data)
{
for(int i = 0; i < data.Length; i++)
{
data[i] = (byte) (data[i] ^ Keys[i]);
} ↑
}
Since the Encrypt and Decrypt method do exactly the same, you need only one method.
Note, however, that this is just a toy and not suitable to secure data in real-world scenarios. Have a look at the System.Security.Cryptography Namespace which provides many implementations of proven algorithms. Using these correctly is still hard to get right though.
Use Xor ^ operator and not And &. Also you should not assume that data and key are the same length.
public class Cryptographer
{
private byte[] Keys { get; set; }
public Cryptographer(string password)
{
Keys = Encoding.ASCII.GetBytes(password);
}
public void Encrypt(byte[] data)
{
for(int i = 0; i < data.Length; i++)
{
data[i] = (byte) (data[i] ^ Keys[i % Keys.Length]);
}
}
public void Decrypt(byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = (byte)(Keys[i % Keys.Length] ^ data[i]);
}
}
}
static void Main(string[] args)
{
Int32 a = 138;
Console.WriteLine("first int: " + a.ToString());
byte[] bytes = BitConverter.GetBytes(a);
var bits = new BitArray(bytes);
String lol = ToBitString(bits);
Console.WriteLine("bit int: " + lol);
lol = lol.Substring(1, lol.Length - 1) + lol[0];
Console.WriteLine("left : " + lol);
byte[] bytes_new = GetBytes(lol);
byte[] key = { 12, 13, 24, 85 };
var bits2 = new BitArray(key);
String lol2 = ToBitString(bits2);
Console.WriteLine("key : " + lol2);
byte[] cryptedBytes = Crypt(bytes_new, key);
var bits3 = new BitArray(cryptedBytes);
String lol3 = ToBitString(bits3);
Console.WriteLine(" XOR: " + lol3);
byte[] deCryptedBytes = Crypt(cryptedBytes, key);
var bits4 = new BitArray(cryptedBytes);
String lol4 = ToBitString(bits4);
Console.WriteLine(" DEXOR: " + lol4);
int a_new = BitConverter.ToInt32(bytes_new, 0);
Console.WriteLine("and int: " + a_new.ToString());
Console.ReadLine();
}
public static byte[] Crypt(byte[] data, byte[] key)
{
byte[] toCrypt = data;
for (int i = 0; i < toCrypt.Length; i++)
{
toCrypt[i] = (byte)(toCrypt[i] ^ key[i]);
}
return toCrypt;
}
private static String ToBitString(BitArray bits)
{
var sb = new StringBuilder();
for (int i = bits.Count - 1; i >= 0; i--)
{
char c = bits[i] ? '1' : '0';
sb.Append(c);
}
return sb.ToString();
}
private static byte[] GetBytes(string bitString)
{
byte[] result = Enumerable.Range(0, bitString.Length / 8).
Select(pos => Convert.ToByte(
bitString.Substring(pos * 8, 8),
2)
).ToArray();
List<byte> mahByteArray = new List<byte>();
for (int i = result.Length - 1; i >= 0; i--)
{
mahByteArray.Add(result[i]);
}
return mahByteArray.ToArray();
}
Remember, there is no such thing as a 'secure' cipher. Any encryption method that can be written can be broken.
With that being said, using simple bitwise techniques for encryption is inviting a not too bright hacker to break your encryption. There are guys/gals that sit around all day long with nothing better to do.
Use one of the encryption libraries that uses a large key and do something 'unusual' to that key before using it. Even so, remember, there are people employed and not employed to do nothing but break cryptographic messages all around the world; 24 by 7.
The Germans thought they had an un-breakable system in WW II. They called it Enigma. Do some reading on it and you will discover that it was broken even before the war broke out!

Convert PHP encryption code to C#

I'm trying to convert this piece of code from PHP to C#. It's part of a Captive Portal. Could somebody explain what it does?
$hexchal = pack ("H32", $challenge);
if ($uamsecret) {
$newchal = pack ("H*", md5($hexchal . $uamsecret));
} else {
$newchal = $hexchal;
}
$response = md5("\0" . $password . $newchal);
$newpwd = pack("a32", $password);
$pappassword = implode ("", unpack("H32", ($newpwd ^ $newchal)));
I also encountered the need of php's pack-unpack functions in c# but did not get any good resource.
So i thought to do it myself. I have verified the function's input with pack/unpack/md5 methods found at onlinephpfunctions.com. Since i have done code only as per my requirements. This can be extended for other formats
Pack
private static string pack(string input)
{
//only for H32 & H*
return Encoding.Default.GetString(FromHex(input));
}
public static byte[] FromHex(string hex)
{
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
MD5
private static string md5(string input)
{
byte[] asciiBytes = Encoding.Default.GetBytes(input);
byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
return hashedString;
}
Unpack
private static string unpack(string p1, string input)
{
StringBuilder output = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
string a = Convert.ToInt32(input[i]).ToString("X");
output.Append(a);
}
return output.ToString();
}
Eduardo,
if you take a look at the pack manual, pack is used to convert a string in (hex, octal, binary )to his number representation.
so
$hexcal = pack('H32', $challenge);
would convert a string like 'cca86bc64ec5889345c4c3d8dfc7ade9' to the actual 0xcca... de9
if $uamsecret exist do the same things with the MD5 of hexchal concacteate with the uamsecret.
if ($uamsecret) {
$newchal = pack ("H*", md5($hexchal . $uamsecret));
} else {
$newchal = $hexchal;
}
$response = md5("\0" . $password . $newchal);
MD% '\0' + $password + $newchal
$newpwd = pack("a32", $password);
pad password to 32 byte
$pappassword = implode ("", unpack("H32", ($newpwd ^ $newchal)));
do a xor newpwd and newchal and convert it to a hexadecimal string, I don't get the implode() maybe it's to convert to string to an array of character.

Categories

Resources