I'm trying to decrypt xor string with key in c# but decrypting is wrong and i'm getting wrong value.
string text = "xorhash";
string key = "xorkey";
var result = new StringBuilder();
for (int c = 0; c < text.Length; c++)
result.Append((char)((uint)text[c] ^ (uint)key[c % key.Length]));
return result.ToString();
I've get it from this python code, which working good.
def xor(message, key):
return "".join(chr(ord(message[i]) ^ ord(key[i % len(key)])) for i in xrange(len(message)))
key = "my_xor_key"
message = "my_xor_hash".decode("hex")
print xor(message, key)
as soon as your input string is actually hex representation of codes, c# code should look like this:
for (int c = 0; c < text.Length; c+=2)
result.Append((char)(Convert.ToUInt16(text.Substring(c, 2), 16) ^ (ushort)key[ (c/2) % key.Length]));
private static string xor(string text, string key) {
var result = new StringBuilder();
for (int c = 0; c < text.Length; c++)
result.Append((char)((uint)text[c] ^ (uint)key[c % key.Length]));
return result.ToString();
}
string text = "my_xor_hash";
string key = "my_xor_key";
string encrypt = xor(text, key);
string decrypt = xor(encrypt, key);
System.Console.Write("Encrypt " + encrypt);
System.Console.Write("Decrypt " + decrypt);
Prints:
Encrypt
Decrypt my_xor_hash
And I didn't change a single line, only indentation.
Edit:
private static string xor(string text, string key) {
var result = new StringBuilder();
for (int c = 0; c < text.Length; c++)
result.Append((char)((uint)text[c] ^ (uint)key[c % key.Length]));
return result.ToString();
}
private static string FromHex(string hex) {
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 Encoding.ASCII.GetString(raw);
}
public static void Main() {
string text = FromHex("xor_hash");
string key = "xor_key";
string decrypt = xor(text, key);
System.Console.Write("Decrypt " + decrypt);
}
Prints:
Decrypt HARPERS
public static byte[] EncryptOrDecrypt(byte[] text, byte[] key)
{
byte[] xor = new byte[text.Length];
for (int i = 0; i < text.Length; i++)
{
xor[i] = (byte)(text[i] ^ key[i % key.Length]);
}
return xor;
}
static void Main(string[] args){
string input;
byte[] inputBytes;
string inputKey;
byte[] key;
do
{
input = System.Console.ReadLine();
inputBytes = Encoding.Unicode.GetBytes(input);
inputKey = System.Console.ReadLine();
key = Encoding.Unicode.GetBytes(inputKey);
//byte[] key = { 0, 0 }; if key is 0, encryption will not happen
byte[] encryptedBytes = EncryptOrDecrypt(inputBytes, key);
string encryptedStr = Encoding.Unicode.GetString(encryptedBytes);
byte[] decryptedBytes = EncryptOrDecrypt(encryptedBytes, key);
string decryptedStr = Encoding.Unicode.GetString(decryptedBytes);
System.Console.WriteLine("Encrypted string:");
System.Console.WriteLine(encryptedStr);
System.Console.WriteLine("Decrypted string:");
System.Console.WriteLine(decryptedStr);
} while (input != "-1" && inputKey != "-1");
//test:
//pavle
//23
//Encrypted string:
//BRD_W
//Decrypted string:
//pavle
}
Related
I have a json web key(https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key-41) and I want to use it to sign some data with the private key and then later verify it with the public key. I am using c# with .net framework 4.5.1 and I can't seem to instantiate the classes properly using the keys I have. I generated the keys using this tool: https://github.com/mitreid-connect/json-web-key-generator. The following json is available and from this I should be able to sign and verify:
{
"kty": "RSA",
"d": "rZ_cdME7usL5EavJW1q0cjz8dhfdO9P-E4dacHYFf4I-TN7o-Q0ksfWCb4fpQPghUoz6v2b6-m3IZk4CocmdEAoFH2JqI0PbH5HIBqgva-bE8-elNJIKwza0Hbrw13bRU6KgpOrc9hrX-NcRCTkeKHYtDWGUa2NDB_lNQvkyg-V0NVXf5oSa_cZ9_H4kHPXrzcBeQapn2M_CFb3qfYgVgQb5xU5n67eAcSlztWHIaSaLyu_YAR0SxnEAvWiik1rtSYrEOWsVrPHfHBFwVHluP0g--bedH6kI3mZRI6H_UbmTMnRtxBkCA5mVdzOmsyX2e98MUqIlOeDQ4zB21xSDQQ",
"e": "AQAB",
"use": "sig",
"alg": "RS512",
"n": "xwHPJaSvKvLqrqb6oeXDL3A4iNgRo5PEQOQCE5zGa6ZWeoC88IuJZxXFJ93wzJk0J22QZJWofC8vV8GAeB3d9mD25koh0dbtb0yoWK-ttWamMIAN4WPiZu30JWzxY1k8LRzOz5lIT9Ze87gV_lgXbpkzQzKFNhxOmV_BhEu1PCLcOTHhic93WQk_E97nYCOwOifmkEFOCBzHEuTG1XHJ1nGEfBCAsdUXrMg_lU3w86TfVDYS6xLVtfVAq4ihDjBsmtPthrdMG4H5Qls8EM-_cbIRe7UEAQK9MgXDLHaQZbx_lQ46_P852SpCprbvqWaoM8zKyEiDf1q6O89D6YIaDw"
}
Then in C# I have a model with those fields and I made a function to test if I can verify data:
public class RSAKeyPair
{
public string kty { get; set; }
public string e { get; set; }
public string use { get; set; }
public string alg { get; set; }
public string n { get; set; }
public string d { get; set; }
}
And the test code:
public static bool TestSigning(RSAKeyPair keySet)
{
if (keySet.alg != "RS512")
{
throw new ArgumentException("Only RS512 is supported.");
}
var oid = CryptoConfig.MapNameToOID("SHA512");
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
rsaProvider.ImportParameters(
new RSAParameters()
{
Modulus = FromBase64Url(keySet.n),
Exponent = FromBase64Url(keySet.e),
D = FromBase64Url(keySet.d)
}
);
var hasher = SHA512.Create();
var testmsg = System.Text.Encoding.UTF8.GetBytes("TestMsg");
var hash = hasher.ComputeHash(new MemoryStream(testmsg));
var signedData = rsaProvider.SignHash(hash, oid);
var isSigned = rsaProvider.VerifyHash(hash, oid, signedData);
return isSigned;
}
private static byte[] FromBase64Url(string base64Url)
{
string padded = base64Url.Length % 4 == 0
? base64Url : base64Url + "====".Substring(base64Url.Length % 4);
string base64 = padded.Replace("_", "/")
.Replace("-", "+");
var s = Convert.FromBase64String(base64);
return s;
}
However when I run it. I get the System.Security.Cryptography.CryptographicException with the message Object contains only the public half of a key pair. A private key must also be provided. when trying to get the signedData
I have no idea which parameters to set because this seems correct according to what I understand from RSA and reading the docs.
I have also tried to create two instances of the RSACryptoServiceProvider One signer with Exponent = keySet.d and one verifier with Exponent = keySet.e. But when I call RSACryptoServiceProvider.ImportParameters for the signer it throws a Bad data exception.
Any help is appreciated.
The main reason is RSACryptoServiceProvider is not able to generate a private key using modulus, public and private exponent i.e n, e and d only, it requires p,q,dp and dq as well. To generate RsaParameters with private key you will require following code to calculate p,q,dp and dq and finally generate RsaParameters:
private static RSAParameters RecoverRSAParameters(BigInteger n, BigInteger e, BigInteger d)
{
using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
{
BigInteger k = d * e - 1;
if (!k.IsEven)
{
throw new InvalidOperationException("d*e - 1 is odd");
}
BigInteger two = 2;
BigInteger t = BigInteger.One;
BigInteger r = k / two;
while (r.IsEven)
{
t++;
r /= two;
}
byte[] rndBuf = n.ToByteArray();
if (rndBuf[rndBuf.Length - 1] == 0)
{
rndBuf = new byte[rndBuf.Length - 1];
}
BigInteger nMinusOne = n - BigInteger.One;
bool cracked = false;
BigInteger y = BigInteger.Zero;
for (int i = 0; i < 100 && !cracked; i++)
{
BigInteger g;
do
{
rng.GetBytes(rndBuf);
g = GetBigInteger(rndBuf);
}
while (g >= n);
y = BigInteger.ModPow(g, r, n);
if (y.IsOne || y == nMinusOne)
{
i--;
continue;
}
for (BigInteger j = BigInteger.One; j < t; j++)
{
BigInteger x = BigInteger.ModPow(y, two, n);
if (x.IsOne)
{
cracked = true;
break;
}
if (x == nMinusOne)
{
break;
}
y = x;
}
}
if (!cracked)
{
throw new InvalidOperationException("Prime factors not found");
}
BigInteger p = BigInteger.GreatestCommonDivisor(y - BigInteger.One, n);
BigInteger q = n / p;
BigInteger dp = d % (p - BigInteger.One);
BigInteger dq = d % (q - BigInteger.One);
BigInteger inverseQ = ModInverse(q, p);
int modLen = rndBuf.Length;
int halfModLen = (modLen + 1) / 2;
return new RSAParameters
{
Modulus = GetBytes(n, modLen),
Exponent = GetBytes(e, -1),
D = GetBytes(d, modLen),
P = GetBytes(p, halfModLen),
Q = GetBytes(q, halfModLen),
DP = GetBytes(dp, halfModLen),
DQ = GetBytes(dq, halfModLen),
InverseQ = GetBytes(inverseQ, halfModLen),
};
}
}
private static BigInteger GetBigInteger(byte[] bytes)
{
byte[] signPadded = new byte[bytes.Length + 1];
Buffer.BlockCopy(bytes, 0, signPadded, 1, bytes.Length);
Array.Reverse(signPadded);
return new BigInteger(signPadded);
}
private static byte[] GetBytes(BigInteger value, int size)
{
byte[] bytes = value.ToByteArray();
if (size == -1)
{
size = bytes.Length;
}
if (bytes.Length > size + 1)
{
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
}
if (bytes.Length == size + 1 && bytes[bytes.Length - 1] != 0)
{
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
}
Array.Resize(ref bytes, size);
Array.Reverse(bytes);
return bytes;
}
private static BigInteger ModInverse(BigInteger e, BigInteger n)
{
BigInteger r = n;
BigInteger newR = e;
BigInteger t = 0;
BigInteger newT = 1;
while (newR != 0)
{
BigInteger quotient = r / newR;
BigInteger temp;
temp = t;
t = newT;
newT = temp - quotient * newT;
temp = r;
r = newR;
newR = temp - quotient * newR;
}
if (t < 0)
{
t = t + n;
}
return t;
}
Now to continue with JWK use it like following:
public static bool TestSigning(RSAKeyPair keySet)
{
if (keySet.alg != "RS512")
{
throw new ArgumentException("Only SHA512 is supported.");
}
var n = GetBigInteger(FromBase64Url(keySet.n));
var d = GetBigInteger(FromBase64Url(keySet.d));
var e = GetBigInteger(FromBase64Url(keySet.e));
var rsaParams= RecoverRSAParameters(n, e, d);
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(512);
rsaProvider.ImportParameters(rsaParams);
var hasher = SHA512.Create();
var testmsg = Encoding.UTF8.GetBytes("TestMsg");
var hash = hasher.ComputeHash(new MemoryStream(testmsg));
var oid = CryptoConfig.MapNameToOID("SHA512");
var signedData = rsaProvider.SignHash(hash, oid);
var isSigned = rsaProvider.VerifyHash(hash, oid, signedData);
return isSigned;
}
Output:
Using vsprintf, the c code below converts a char array to an int. How would I do this in c#? I have tried casting the c# string to an int, and then adding the values, but the return result is not the same. My c# code needs to return the same value as the c code does(3224115)
C# Code
var astring = "123";
int output = 0;
foreach(char c in astring){
var currentChar = (int)c;
output += c;
}
//output = 150
C Code
void vout(char *string, char *fmt, ...);
char fmt1 [] = "%d";
int main(void)
{
char string[32];
vout(string, fmt1, '123'); //output is 3224115
printf("The string is: %s\n", string);
}
void vout(char *string, char *fmt, ...)
{
va_list arg_ptr;
va_start(arg_ptr, fmt);
vsprintf(string, fmt, arg_ptr);
va_end(arg_ptr);
}
Finally figured out. Could be a bit cleaner, but it works, and gets the same output as the c code.
public static ulong getAsciiLiteral(string x)
{
int len = x.Length;
string[] strArray = new string[32];
byte[] finalByte = new byte[32];
int i = 0;
int i2 = 0;
int i3 = 0;
int offset = 0;
var hexFinalString = "0x";
var bytes = Encoding.ASCII.GetBytes(x);
if(len >= 5)
{
while (true)
{
if (4 + i3 == len)
{
offset = i3;
break;
}
else
{
i3++;
}
}
}
foreach (byte b in bytes)
{
strArray[i] = b.ToString("X2");
i++;
}
i = 0;
i3 = 0;
while (i3 < len - 1)
{
hexFinalString += strArray[offset];
offset++;
i3++;
}
var ret = Convert.ToUInt64(hexFinalString, 16);
return ret;
}
G'Day. I am attempting to convert a function that was initially made for Bohemia Interactives language SQF to C#. The script is designed to encrypt a string with the encryption method RC4, however, it works a little bit different to the way this is traditionally done thanks to limitations of the arma3 engine. The whole idea of this is so I can encrypt a string with the C# program, and decrypt it through Arma 3 in-game.
Here is the code I am trying to convert from.
/*
Function: ALiVE_fnc_crypt
Author(s): Naught
Version: 1.0
Description:
Encrypts or decrypts a string with a specified encryption key.
Parameters:
0 - Decrypt (0) or encrypt (1) [number]
1 - Encryption method name [string]
2 - Encrypted or plain data [string]
3 - Encryption key [string]
Returns:
Encrypted or decrypted data or nothing on failure [string:nil]
Note(s):
1. Current encryption method names:
- "rc4" // Rivest Cipher 4 Stream Encryption Algorithm
*/
// Constants
MAX_CHAR_SIZE = 8;
CHAR_ZERO_REP = 256;
private ["_method", "_key"];
_encText = _this select 0;
_key = _this select 1;
private ["_fnc_intToBin"];
_fnc_intToBin = {
private ["_int", "_bin", "_pwr", "_bool"];
_int = _this select 0;
_bin = if ((count _this) > 1) then {_this select 1} else {[]};
for "_i" from (MAX_CHAR_SIZE - 1) to 0 step (-1) do
{
_pwr = 2^(_i);
_bool = _pwr <= _int;
_bin set [(count _bin), _bool];
if (_bool) then {_int = _int - _pwr};
};
_bin
};
private ["_bin"];
_bin = [];
// Convert string to UTF-8 binary
{ // count (faster than forEach)
[(if (_x == CHAR_ZERO_REP) then {0} else {_x}), _bin] call _fnc_intToBin;
false;
} count toArray(_encText);
systemChat str _bin;
// Encrypt & decrypt methods
_key = toArray(_key);
private ["_keyLen", "_state", "_temp", "_j"];
_keyLen = count _key;
_state = [];
_temp = 0;
_j = 0;
// Key-Scheduling Algorithm
for "_i" from 0 to 255 do {_state set [_i,_i]};
for "_i" from 0 to 255 do
{
_temp = _state select _i;
_j = (_j + _temp + (_key select (_i mod _keyLen))) mod 256;
_state set [_i, (_state select _j)];
_state set [_j, _temp];
};
private ["_temp1", "_temp2", "_rand", "_i", "_mod", "_rbit"];
_temp1 = 0;
_temp2 = 0;
_rand = [];
_i = 0;
_j = 0;
hint str _bin;
// Pseudo-Random Generation Algorithm
{
_mod = _forEachIndex % MAX_CHAR_SIZE;
if (_mod == 0) then
{
_i = (_i + 1) mod 256;
_j = (_j + (_state select _i)) mod 256;
_temp1 = _state select _i;
_temp2 = _state select _j;
_state set [_i, _temp2];
_state set [_j, _temp1];
_rand = [(_state select ((_temp1 + _temp2) mod 256))] call _fnc_intToBin;
};
_rbit = _rand select _mod;
_bin set [_forEachIndex, (_x && !_rbit) || {!_x && _rbit}]; // XOR
} forEach _bin;
private ["_dec", "_buf", "_mod"];
_dec = 0;
_buf = [];
// Convert binary array to UTF-8 string
{
_mod = _forEachIndex % MAX_CHAR_SIZE;
if (_x) then {_dec = _dec + 2^((MAX_CHAR_SIZE - 1) - _mod)};
if (_mod == 7) then
{
if (_dec == 0) then {_dec = CHAR_ZERO_REP};
_buf set [(count _buf), _dec];
_dec = 0;
};
} forEach _bin;
toString(_buf)
I have made slight adjustments to this code, and it all still works fine in Arma 3.
Now, the converted function. I have changed about everything in this code from what my initial code was to try and get it working, so at this point, it may be completely incorrect, however, I will include it anyway.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace encrypt
{
class Program
{
static public int MAX_CHAR_SIZE = 8;
static public int CHAR_ZERO_REP = 256;
static public int _keyLen;
static void Main()
{
string[] args = new string[2];
args[0] = "Some Random Code";
args[1] = "4tuIc9tai";
string text = args[0];
// Convert the text to an array of decimal unicode || Same as toArray in arma 3
string[] txtArray = new string[text.Length];
txtArray = text.ToCharArray().Select(c => c.ToString()).ToArray();
int[] utf = getUni(txtArray);
// Convert the key to an array of decimal unicode || Same as toArray in arma 3
string[] keyArray = new string[args[1].Length];
keyArray = args[1].ToCharArray().Select(c => c.ToString()).ToArray();
int[] key = getUni(keyArray);
// Debug the output
//foreach (int i in utf){Console.Write(i); Console.Write(",");} Console.WriteLine();foreach (int i in key){Console.Write(i);Console.Write(","); }
// Convert string to UTF-8 binary
Dictionary<int, bool> _bin = new Dictionary<int, bool>();
foreach (int i in utf)
{
int _num;
if (i == CHAR_ZERO_REP)
{
_num = 0;
}
else
{
_num = i;
}
_bin = intToBin(_num, _bin);
}
foreach (KeyValuePair<int, bool> i in _bin)
{
Console.Write(Convert.ToString(i.Value));
Console.Write(", ");
}
// Encrypt & decrypt methods
_keyLen = key.Length;
int[] _state = new int[1024];
int _temp = 0;
int _j = 0;
// Key-Scheduling Algorithm
for (int _i = 0; _i < 255; _i++)
{
_state.SetValue(_i, _i);
}
for (int _i = 0; _i < 255; _i++)
{
_temp = _state[_i];
_j = (_j + _temp + key[_i % _keyLen]) % 256;
_state.SetValue(_i, _state[_j]);
_state.SetValue(_j, _temp);
}
// Pseudo-Random Generation Algorithm
int _temp1 = 0;
int _temp2 = 0;
Dictionary<int, bool> _rand = new Dictionary<int, bool>();
int __i = 0;
int __j = 0;
int indx = 0;
for (int i = 0; i < _bin.Count-1; i++)
{
int _mod = indx % MAX_CHAR_SIZE;
if (_mod == 0)
{
__i = (__i + 1) % 256;
__j = (__j + _state[__i]) % 256;
_temp1 = _state[__i];
_temp2 = _state[__j];
_state.SetValue(__i, _temp2);
_state.SetValue(__j, _temp1);
_rand = intToBin(_state[_temp1 + _temp2] % 256, _rand);
}
bool _rbit = _rand[_mod];
bool _bit = _bin[i];
if (_bin.ContainsKey(indx))
{
_bin.Remove(indx);
}
_bin.Add(indx, (_bit && !_rbit) || (!_bit && _rbit));
indx++;
}
// Convert binary array to UTF-8 string
int _dec = 0;
int[] _buf = new int[_bin.Count];
for (int i = 0; i < _bin.Count-1; i++)
{
int _mod = i % MAX_CHAR_SIZE;
Console.WriteLine(i);
if (_bin[i])
{
_dec = _dec + 2 ^ ((MAX_CHAR_SIZE - 1) - _mod);
}
if (_mod == 7)
{
if (_dec == 0)
{
_dec = CHAR_ZERO_REP;
}
_buf.SetValue(_dec, _buf.Length-1);
_dec = 0;
}
_buf.SetValue(_dec, _buf.Length - 1);
}
Console.ReadLine();
}
static int[] getUni(string[] txtArray)
{
int[] ret = new int[txtArray.Length];
int idx = 0;
foreach (string i in txtArray)
{
ret.SetValue(Encoding.UTF8.GetBytes(i)[0], idx);
idx++;
}
return ret;
}
static Dictionary<int, bool> intToBin(int val, Dictionary<int, bool> bin)
{
for (int i = MAX_CHAR_SIZE-1; i > 0; i--)
{
int _pwr = 2 ^ i;
bool _bool = _pwr <= val;
int cc = bin.Count;
if (bin.ContainsKey(cc))
{
bin.Remove(cc);
}
bin.Add(cc, _bool);
if (_bool)
{
val = val - _pwr;
}
}
return bin;
}
}
}
Any help what so ever would be great :)
My goal is to be able to convert a string into binary code that is still a string. I am able to turn the string into byte[] but not back to a string without decoding it.
You can use the Convert method for that:
byte [] bytesToEncode = Encoding.UTF8.GetBytes (inputText);
string encodedText = Convert.ToBase64String (bytesToEncode);
If you can encode/decode a byte, e.g.
private static String ToBinary(Byte value) {
StringBuilder Sb = new StringBuilder(8);
Sb.Length = 8;
for (int i = 0; i < 8; ++i) {
Sb[7 - i] = (Char) ('0' + value % 2);
value /= 2;
}
return Sb.ToString();
}
private static Byte FromBinary(String value) {
int result = 0;
for (int i = 0; i < value.Length; ++i)
result = result * 2 + value[i] - '0';
return (Byte) result;
}
You can easily encode/decode a whole string:
// Encoding...
String source = "abc";
// 011000010110001001100011
String result = String.Join("", UTF8Encoding.UTF8.GetBytes(source).Select(x => ToBinary(x)));
...
// Decoding...
List<Byte> codes = new List<Byte>();
for (int i = 0; i < result.Length; i += 8)
codes.Add(FromBinary(result.Substring(i, 8)));
// abc
String sourceBack = UTF8Encoding.UTF8.GetString(codes.ToArray());
use
string str = "Welcome";
byte []arr = System.Text.Encoding.ASCII.GetBytes(str);
I wrote this code in C# to encrypt a string with a key:
private static int Bin2Dec(string num)
{
int _num = 0;
for (int i = 0; i < num.Length; i++)
_num += (int)Math.Pow(2, num.Length - i - 1) * int.Parse(num[i].ToString());
return _num;
}
private static string Dec2Bin(int num)
{
if (num < 2) return num.ToString();
return Dec2Bin(num / 2) + (num % 2).ToString();
}
public static string StrXor(string str, string key)
{
string _str = "";
string _key = "";
string _xorStr = "";
string _temp = "";
for (int i = 0; i < str.Length; i++)
{
_temp = Dec2Bin(str[i]);
for (int j = 0; j < 8 - _temp.Length + 1; j++)
_temp = '0' + _temp;
_str += _temp;
}
for (int i = 0; i < key.Length; i++)
{
_temp = Dec2Bin(key[i]);
for (int j = 0; j < 8 - _temp.Length + 1; j++)
_temp = '0' + _temp;
_key += _temp;
}
while (_key.Length < _str.Length) _key += _key;
if (_key.Length > _str.Length) _key = _key.Substring(0, _str.Length);
for (int i = 0; i < _str.Length; i++)
if (_str[i] == _key[i]) { _xorStr += '0'; } else { _xorStr += '1'; }
_str = "";
for (int i = 0; i < _xorStr.Length; i += 8)
{
char _chr = (char)0;
_chr = (char)Bin2Dec(_xorStr.Substring(i, 8)); //ERROR : (Index and length must refer to a location within the string. Parameter name: length)
_str += _chr;
}
return _str;
}
The problem is that I always get error when I want to decrypt an encryted text with this code:
string enc_text = ENCRYPT.XORENC("abc","a"); // enc_text = " ♥☻"
string dec_text = ENCRYPT.XORENC(enc_text,"a"); // ArgumentOutOfRangeException
Any clues?
If you have a character, a char, you can convert it to an integer, an int.
And then you can use the ^ operator to perform XOR on it. You don't appear to be using that operator at the moment, which might be the source of your problem.
string EncryptOrDecrypt(string text, string key)
{
var result = new StringBuilder();
for (int c = 0; c < text.Length; c++)
result.Append((char)((uint)text[c] ^ (uint)key[c % key.Length]));
return result.ToString();
}
That kind of thing. Here's a longer version with comments that does the same thing in steps, to make it easier to learn from:
string EncryptOrDecrypt(string text, string key)
{
var result = new StringBuilder();
for (int c = 0; c < text.Length; c++)
{
// take next character from string
char character = text[c];
// cast to a uint
uint charCode = (uint)character;
// figure out which character to take from the key
int keyPosition = c % key.Length; // use modulo to "wrap round"
// take the key character
char keyChar = key[keyPosition];
// cast it to a uint also
uint keyCode = (uint)keyChar;
// perform XOR on the two character codes
uint combinedCode = charCode ^ keyCode;
// cast back to a char
char combinedChar = (char)combinedCode;
// add to the result
result.Append(combineChar);
}
return result.ToString();
}
The short version is the same but with the intermediate variables removed, substituting expressions directly into where they're used.
// Code
public static byte[] EncryptOrDecrypt(byte[] text, byte[] key)
{
byte[] xor = new byte[text.Length];
for (int i = 0; i < text.Length; i++)
{
xor[i] = (byte)(text[i] ^ key[i % key.Length]);
}
return xor;
}
// Test
static void Main(string[] args){
string input;
byte[] inputBytes;
string inputKey;
byte[] key;
do
{
input = System.Console.ReadLine();
inputBytes = Encoding.Unicode.GetBytes(input);
inputKey = System.Console.ReadLine();
key = Encoding.Unicode.GetBytes(inputKey);
//byte[] key = { 0, 0 }; if key is 0, encryption will not happen
byte[] encryptedBytes = EncryptOrDecrypt(inputBytes, key);
string encryptedStr = Encoding.Unicode.GetString(encryptedBytes);
byte[] decryptedBytes = EncryptOrDecrypt(encryptedBytes, key);
string decryptedStr = Encoding.Unicode.GetString(decryptedBytes);
System.Console.WriteLine("Encrypted string:");
System.Console.WriteLine(encryptedStr);
System.Console.WriteLine("Decrypted string:");
System.Console.WriteLine(decryptedStr);
} while (input != "-1" && inputKey != "-1");
//test:
//pavle
//23
//Encrypted string:
//BRD_W
//Decrypted string:
//pavle
}
Here is some simple code to encrypt and decrypt
class CEncryption
{
public static string Encrypt(string strIn, string strKey)
{
string sbOut = String.Empty;
for (int i = 0; i < strIn.Length; i++)
{
sbOut += String.Format("{0:00}", strIn[i] ^ strKey[i % strKey.Length]);
}
return sbOut;
}
public static string Decrypt(string strIn, string strKey)
{
string sbOut = String.Empty;
for (int i = 0; i < strIn.Length; i += 2)
{
byte code = Convert.ToByte(strIn.Substring(i, 2));
sbOut += (char)(code ^ strKey[(i/2) % strKey.Length]);
}
return sbOut;
}
}