I'm trying to upload a Base64 image string from iOS (using NSData+Base64) to MVC .Net. The upload is ok, but when I try to convert string back to Image, an exception is thrown at line:
byte[] imageBytes = Convert.FromBase64String(imageString);
Exception: "Invalid length for a Base-64 char array"
The imageString length converted in iOS is 944062.
To verify the length, I converted the same image in .Net using
string fota = ImageToBase64(Image.FromFile(#"C:\PR\Source\Servicea\bin\Imag043.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
and the size was 203956. And the original image file size is 156,967.
Both methods shouldn't convert the image returning the same string? Anybody had this problem before? Tks
Update: After many tests, I decided to use ASIHTTPRequest lib. Tks all.
Try using this:
#import <CommonCrypto/CommonDigest.h>
#include <stdlib.h>
static char base64EncodingTable[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {
unsigned long ixtext, lentext;
long ctremaining;
unsigned char input[3], output[4];
short i, charsonline = 0, ctcopy;
const unsigned char *raw;
NSMutableString *result;
lentext = [data length];
if (lentext < 1)
return #"";
result = [NSMutableString stringWithCapacity: lentext];
raw = [data bytes];
ixtext = 0;
while (true) {
ctremaining = lentext - ixtext;
if (ctremaining <= 0)
break;
for (i = 0; i < 3; i++) {
unsigned long ix = ixtext + i;
if (ix < lentext)
input[i] = raw[ix];
else
input[i] = 0;
}
output[0] = (input[0] & 0xFC) >> 2;
output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
output[3] = input[2] & 0x3F;
ctcopy = 4;
switch (ctremaining) {
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for (i = 0; i < ctcopy; i++)
[result appendString: [NSString stringWithFormat: #"%c", base64EncodingTable[output[i]]]];
for (i = ctcopy; i < 4; i++)
[result appendString: #"="];
ixtext += 3;
charsonline += 4;
if ((length > 0) && (charsonline >= length))
charsonline = 0;
}
return result;
}
Related
I was wondering those differences, since I have a program that asks me for a byte[].
public static string DecryptTextFromFile(String FileName, byte[] Key, byte[]
IV){}
enter image description here
and I have already tried:
char[] key= { '9', 'D', '2', 'A', 'E'}; doesn't give an error but I need byte[]
and this:
byte[] key= { '9', 'D', '2', 'A', 'E'}; // but this one says that I am using char characters, how do I put them in byte[] format?.
You can initialize a byte array like :
byte[] key1 = new byte[] { 57, 68, 50, 65, 69 };
Or convert from Char Array :
char[] keyChars = { '9', 'D', '2', 'A', 'E' };
var key2 = Encoding.ASCII.GetBytes(keyChars);
The char and byte are two different types, char size is 16 bit and byte size is 8 bit;
To represent a char you need to convert to bytes.
To do that you can use BitConverter
char charValue = 'c';
bytep[] bytes = BitConverter.GetBytes(charValue);
To convert your string from the picture you can use this method
static class HexStringConverter
{
public static byte[] ToByteArray(String HexString)
{
int NumberChars = HexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(HexString.Substring(i, 2), 16);
}
return bytes;
}
}
Hope this answer will help you
I'm rewriting this stopwatch code from C# to C++.
I have rewritten some of the code (I can attach it if you think it's helpful) but confused about the lines after var watch = Stopwatch.StartNew(). Does C++ have similar things like this? What kind of variable type should I put for watch in C++?
namespace BruteForcePasswordGeneration
{
class Program
{
static void Main(string[] args)
{
char[] chars = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
int passwordLength=0;
Console.WriteLine("Enter the password length");
passwordLength = Convert.ToInt32(Console.ReadLine());
BigInteger iPossibilities = (BigInteger)Math.Pow((double)chars.Length, (double)passwordLength);
Console.WriteLine("{0} words total. Press enter to continue;", iPossibilities);
Console.ReadLine();
var watch = Stopwatch.StartNew();
for (BigInteger i = 0; i < iPossibilities; i++)
{
string theword = "";
BigInteger val = i;
for (int j = 0; j < passwordLength; j++)
{
BigInteger ch = val % chars.Length;
theword = chars[(int)ch] + theword;
val = val / chars.Length;
}
Console.WriteLine(theword);
}
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine("It took {0} seconds to generate {1} possible combinations", elapsedMs / 1000, iPossibilities);
Console.ReadLine();
}
}
}
Although you can write a "stopwatch" class in C++ if you want, the usual is to just use high_resolution_clock::now() to get the start and stop times. You then use duration_cast to get the difference in the form you want.
If you'll forgive me, I don't see any real point in requiring the user to enter the password length after starting the program. At least to me, it seems easier to use something like "gen_passwords 4" to generate all the passwords of length 4.
That gives code something on this general order:
#include <iostream>
#include <chrono>
#include <string>
int main(int argc, char **argv) {
static const std::string chars{ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" };
if (argc != 2) {
std::cerr << "Usage: generate <password length>\n";
return EXIT_FAILURE;
}
int passwordLength = std::stoi(argv[1]);
unsigned long long iPossibilities = std::pow(chars.size(), passwordLength);
using namespace std::chrono;
auto start = high_resolution_clock::now();
for (unsigned long long i = 0; i < iPossibilities; i++) {
std::string theword;
unsigned long long val = i;
for (int j = 0; j < passwordLength; j++) {
size_t ch = val % chars.size();
theword = chars[ch] + theword;
val /= chars.size();
}
std::cout << theword << '\n';
}
auto stop = high_resolution_clock::now();
double elapsed = duration_cast<milliseconds>(stop - start).count() / 1000.0;
std::cerr << "It took " << elapsed << " seconds to generate " << iPossibilities << " combinations\n";
}
The program needs to check if the array is palindrome using recursion, but I get stack overflow exception in unmanaged. Been stuck on it for over a day, please help
public static void Main(string[] args)
{
char[] arr = { 'd', 'a', 'd' };
int ind = 0;
Rowpalindrome(arr, ind);
}
static bool Rowpalindrome(char[] arr, int index)
{
if (index == arr.Length % 2)
return true;
int i = index;
if (arr[i] != arr[(arr.Length - index - 1)])
return false;
else
return Rowpalindrome(arr, index++);
}
You have error in the increment; it should be ++indexinstead of index++:
return Rowpalindrome(arr, ++index);
you should increment and pass modified value of index (++index), not increment and pass initial value (index++). Even better implementation is to put it simple:
return Rowpalindrome(arr, index + 1);
Edit: You have some logical errors as well (thanks to Fildor who's pointed it out): the condition should be
if (arr.Length <= 1 || index > arr.Length % 2 + 1)
return true;
The final recoursive code can be
static bool Rowpalindrome(char[] arr, int index) {
if (arr.Length <= 1 || index > arr.Length % 2 + 1)
return true;
// Let's get rid of "i" (which is index) and exploit short circuit of &&:
// .Net tests arr[index] != arr[(arr.Length - index - 1)]
// and only if it's true call for Rowpalindrome(arr, index + 1)
return arr[index] != arr[(arr.Length - index - 1)] && Rowpalindrome(arr, index + 1);
}
Test cases: (Let's use Linq to query for each test)
using System.Linq;
...
var tests = new char[][] {
new char[] { },
new char[] { 'a' },
new char[] { 'a', 'a' },
new char[] { 'a', 'b' },
new char[] { 'a', 'b', 'a' },
new char[] { 'a', 'b', 'c' },
new char[] { 'a', 'b', 'b', 'a' },
new char[] { 'a', 'b', 'c', 'a' },
new char[] { 'a', 'b', 'b', 'c' },
};
var result = tests
.Select(test => $"{"[" +string.Join(", ", test) + "]", -15} : {(Rowpalindrome(test, 0) ? "Palindrome" : "Not")}");
Console.Write(string.Join(Environment.NewLine, result));
Outcome:
[] : Palindrome
[a] : Palindrome
[a, a] : Palindrome
[a, b] : Not
[a, b, a] : Palindrome
[a, b, c] : Not
[a, b, b, a] : Palindrome
[a, b, c, a] : Not
[a, b, b, c] : Not
Edit 2: In case of multidimensional array (see comments below) you can extract column of interest into an array and run the routine, e.g. for 2D array:
char[,] c = new char[,] {
{ 'a', 'b', 'c'},
{ 'x', 'y', 'z'},
{ 'x', 'p', 'q'},
{ 'a', 'm', 'n'},
};
int colIndex = 0; // should be {'a', 'x', 'x', 'a'} column
// c.GetLength(0) - number of lines (length of the 1st dimension) - 4
char[] a = new char[c.GetLength(0)];
for (int i = 0; i < a.Length; ++i)
a[i] = c[i, colIndex];
bool result = Rowpalindrome(a, 0);
I've a big problem.
I using this C# function to encode my message:
byte[] buffer = Encoding.ASCII.GetBytes(file_or_text);
SHA1CryptoServiceProvider cryptoTransformSHA1 = new SHA1CryptoServiceProvider();
String hashText = BitConverter.ToString(cryptoTransformSHA1.ComputeHash(buffer)).Replace("-", "");
On java side, I use this snippet:
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] sha1hash = new byte[40];
md.update(text.getBytes("iso-8859-1"), 0, text.length());
sha1hash = md.digest();
My message is: Block|Notes|Text !£$%&/()=?^€><{}ç°§;:_-.,##ùàòè+
I have this result:
(C#) 8EDC7F756BCECDB99B045FA3DEA2E36AA0BF0875
(Java) 2a566428826539365bb2fe2197da91395c2b1b72
Can you help me please??
Thanks...
My guess is you seem to be comparing ASCII bytes to Latin1 bytes. Try switching
md.update(text.getBytes("iso-8859-1"), 0, text.length());
to this
md.update(text.getBytes("ISO646-US"), 0, text.length());
That might solve your problem.
(Or switch C# to use Latin1)
What is happening in your program your GetBytes method is returning different values for the same characters depending on encoding, so our nifty SHA1 hash algorithm is getting passed different parameters resulting in different return values.
The change to use ISO-8859-1 on the C# side is easy:
byte[] buffer = Encoding.GetEncoding(28591).GetBytes(file_or_text);
However, both this and ASCII will lose data if your text contains Unicode characters above U+00FF.
Ideally if your source data is genuinely text, you should use an encoding which will cope with anything (e.g. UTF-8) and if your source data is actually binary, you shouldn't be going through text encoding at all.
Try the following code:
public static string Sha1encode(string toEncrypt) {
// Produce an array of bytes which is the SHA1 hash
byte[] sha1Signature = new byte[40];
byte[] sha = System.Text.Encoding.Default.GetBytes(toEncrypt);
SHA1 sha1 = SHA1Managed.Create();
sha1Signature = sha1.ComputeHash(sha);
// The BASE64 encoding standard's 6-bit alphabet, from RFC 1521,
// plus the padding character at the end.
char[] Base64Chars = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
'5', '6', '7', '8', '9', '+', '/', '=' };
// Algorithm to encode the SHA1 hash using Base64
StringBuilder sb = new StringBuilder();
int len = sha1Signature.Length;
int i = 0;
int ival;
while (len >= 3) {
ival = ((int) sha1Signature[i++] + 256) & 0xff;
ival <<= 8;
ival += ((int) sha1Signature[i++] + 256) & 0xff;
ival <<= 8;
ival += ((int) sha1Signature[i++] + 256) & 0xff;
len -= 3;
sb.Append(Base64Chars[(ival >> 18) & 63]);
sb.Append(Base64Chars[(ival >> 12) & 63]);
sb.Append(Base64Chars[(ival >> 6) & 63]);
sb.Append(Base64Chars[ival & 63]);
}
switch (len) {
case 0: // No pads needed.
break;
case 1: // Two more output bytes and two pads.
ival = ((int) sha1Signature[i++] + 256) & 0xff;
ival <<= 16;
sb.Append(Base64Chars[(ival >> 18) & 63]);
sb.Append(Base64Chars[(ival >> 12) & 63]);
sb.Append(Base64Chars[64]);
sb.Append(Base64Chars[64]);
break;
case 2: // Three more output bytes and one pad.
ival = ((int) sha1Signature[i++] + 256) & 0xff;
ival <<= 8;
ival += ((int) sha1Signature[i] + 256) & 0xff;
ival <<= 8;
sb.Append(Base64Chars[(ival >> 18) & 63]);
sb.Append(Base64Chars[(ival >> 12) & 63]);
sb.Append(Base64Chars[(ival >> 6) & 63]);
sb.Append(Base64Chars[64]);
break;
}
string base64Sha1Signature = sb.ToString();
return base64Sha1Signature;
}
I am trying to calculate a SHA-1 Hash from a string, but when I calculate the string using php's sha1 function I get something different than when I try it in C#. I need C# to calculate the same string as PHP (since the string from php is calculated by a 3rd party that I cannot modify). How can I get C# to generate the same hash as PHP? Thanks!!!
String = s934kladfklada#a.com
C# Code (Generates d32954053ee93985f5c3ca2583145668bb7ade86)
string encode = secretkey + email;
UnicodeEncoding UE = new UnicodeEncoding();
byte[] HashValue, MessageBytes = UE.GetBytes(encode);
SHA1Managed SHhash = new SHA1Managed();
string strHex = "";
HashValue = SHhash.ComputeHash(MessageBytes);
foreach(byte b in HashValue) {
strHex += String.Format("{0:x2}", b);
}
PHP Code (Generates a9410edeaf75222d7b576c1b23ca0a9af0dffa98)
sha1();
Use ASCIIEncoding instead of UnicodeEncoding. PHP uses ASCII charset for hash calculations.
This method in .NET is equivalent to sha1 in php:
string sha1Hash(string password)
{
return string.Join("", SHA1CryptoServiceProvider.Create().ComputeHash(Encoding.UTF8.GetBytes(password)).Select(x => x.ToString("x2")));
}
I had this problem also. The following code will work.
string dataString = "string to hash";
SHA1 hash = SHA1CryptoServiceProvider.Create();
byte[] plainTextBytes = Encoding.ASCII.GetBytes(dataString);
byte[] hashBytes = hash.ComputeHash(plainTextBytes);
string localChecksum = BitConverter.ToString(hashBytes)
.Replace("-", "").ToLowerInvariant();
Had the same problem. This code worked for me:
string encode = secretkey + email;
SHA1 sha1 = SHA1CryptoServiceProvider.Create();
byte[] encodeBytes = Encoding.ASCII.GetBytes(encode);
byte[] encodeHashedBytes = sha1.ComputeHash(passwordBytes);
string pencodeHashed = BitConverter.
ToString(encode HashedBytes).Replace("-", "").ToLowerInvariant();
FWIW, I had a similar issue in Java. It turned out that I had to use "UTF-8" encoding to produce the same SHA1 hashes in Java as the sha1 function produces in PHP 5.3.1 (running on XAMPP Vista).
private static String SHA1(final String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
final MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(text.getBytes("UTF-8"));
return new String(org.apache.commons.codec.binary.Hex.encodeHex(md.digest()));
}
Try The following! I think it will work great:
public static string SHA1Encodeb64(string toEncrypt)
{
//Produce an array of bytes which is the SHA1 hash
byte[] sha1Signature = new byte[40];
byte[] sha = System.Text.Encoding.Default.GetBytes(toEncrypt);
SHA1 sha1 = SHA1Managed.Create();
sha1Signature = sha1.ComputeHash(sha);
/**
* The BASE64 encoding standard's 6-bit alphabet, from RFC 1521,
* plus the padding character at the end.
*/
char[] Base64Chars = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
'='
};
//Algorithm to encode the SHA1 hash using Base64
StringBuilder sb = new StringBuilder();
int len = sha1Signature.Length;
int i = 0;
int ival;
while (len >= 3)
{
ival = ((int)sha1Signature[i++] + 256) & 0xff;
ival <<= 8;
ival += ((int)sha1Signature[i++] + 256) & 0xff;
ival <<= 8;
ival += ((int)sha1Signature[i++] + 256) & 0xff;
len -= 3;
sb.Append(Base64Chars[(ival >> 18) & 63]);
sb.Append(Base64Chars[(ival >> 12) & 63]);
sb.Append(Base64Chars[(ival >> 6) & 63]);
sb.Append(Base64Chars[ival & 63]);
}
switch (len)
{
case 0: // No pads needed.
break;
case 1: // Two more output bytes and two pads.
ival = ((int)sha1Signature[i++] + 256) & 0xff;
ival <<= 16;
sb.Append(Base64Chars[(ival >> 18) & 63]);
sb.Append(Base64Chars[(ival >> 12) & 63]);
sb.Append(Base64Chars[64]);
sb.Append(Base64Chars[64]);
break;
case 2: // Three more output bytes and one pad.
ival = ((int)sha1Signature[i++] + 256) & 0xff;
ival <<= 8;
ival += ((int)sha1Signature[i] + 256) & 0xff;
ival <<= 8;
sb.Append(Base64Chars[(ival >> 18) & 63]);
sb.Append(Base64Chars[(ival >> 12) & 63]);
sb.Append(Base64Chars[(ival >> 6) & 63]);
sb.Append(Base64Chars[64]);
break;
}
//Encode the signature using Base64
string base64Sha1Signature = sb.ToString();
return base64Sha1Signature;
}