Convert a string to a byte array in PowerShell version 2 - powershell

What I'm trying to do is use SHA1 UTF-8 encryption and then base64 encoding and on a password string value. However, I needed to do the encryption first, then the encoding, but I did it the other way around.
Here is the code:
# Create Input Data
$enc = [system.Text.Encoding]::UTF8
$string1 = "This is a string to hash"
$data1 = $enc.GetBytes($string1)
# Create a New SHA1 Crypto Provider
$sha = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$# Now hash and display results
$result1 = $sha.ComputeHash($data1)
So, when I went to do the hashing I realized I had to have a byte[] from the string and I'm not sure how to do that. I'm thinking there is a simple way from the .Net libraries, but couldn't find an example.
So if I have a string, like:
$string = "password"
How do I convert that into a byte array that I can use on :: ComputeHash($string)?
So what I have to end up with is an encrypted SHA-1 and base 64 encoded UTF-8 password, which the code above does, but it's coming back different than when I coded this same thing in java, where I encrypted it first, then converted that result to base 64 encoding.
I'm making the assumption that while encrypting a string directly isn't supported in the api, there may be a work-around that will allow you to do this. That is what I'm attempting to do.
So I'm assuming my issue with the code is that I had to encrypt it first and then encode it to get the correct value. Correct or am I missing something here?
Here is the pertinent java code that does work:
//First method call uses a swing component to get the user entered password.
String password = getPassword();
//This line is where the work starts with the second and third methods below.
String hashed = byteToBase64(getHash(password));
//The second method call here gets the encryption.
public static byte[] getHash(String password) {
MessageDigest digest = null;
byte[] input = null;
try {
digest = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
digest.reset();
try {
input = digest.digest(password.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return input;
}
//Then the third method call here gets the encoding, FROM THE ENCRYPTED STRING.
public static String byteToBase64(byte[] data){
return new String(Base64.encodeBase64(data));
When I run the java code with the password string of "password" I get
[91, -86, 97, -28, -55, -71, 63, 63, 6, -126, 37, 11, 108, -8, 51, 27, 126, -26, -113, -40]
which is the encryption.
Then I when the encoding in java I get this:
W6ph5Mm5Pz8GgiULbPgzG37mj9g=
but when I run it in PowerShell I get this because it's encoded first for UTF8:
91 170 97 228 201 185 63 63 6 130 37 11 108 248 51 27 126 230 143 216
Then when I run this line of code to convert it I get an error:
$base64 = [System.Convert]::FromBase64String($result)
Exception calling "FromBase64String" with "1" argument(s): "Invalid length for a Base-64 char array."
At line:1 char:45
However, if I run the new line of code to make it hex from below I get:
$hexResult = [String]::Join("", ($result | % { "{0:X2}" -f $_}))
PS C:\Program Files (x86)\PowerGUI> Write-Host $hexResult
5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8
but I need to end up with this value:
W6ph5Mm5Pz8GgiULbPgzG37mj9g=
Again, this may not even be possible to do, but I'm trying to find a work-around to see.

You most likely just need to convert your hash to base64 after the last line.
$enc = [system.Text.Encoding]::UTF8
$string1 = "This is a string to hash"
$data1 = $enc.GetBytes($string1)
# Create a New SHA1 Crypto Provider
$sha = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
# Now hash and display results
$result1 = $sha.ComputeHash($data1)
[System.Convert]::ToBase64String($result1)
Text->Bytes->Encrypt/Hash->Base64
That's a very common pattern for sending cryptographic data in a text format.

It looks like you're on the right track. You have to pick a character encoding to convert between a string and a byte array. You picked UTF-8 above, but there are other options (e.g. ASCII, UTF-16, etc.).
Encrypting a string directly is not supported.

The problem seems to be that in first bytearray, you are have signed bytes (-86 = 10101010) and in the second one unsigned bytes (170 = 10101010).

Related

Dart is not printing hex string

I got the string \x01\x01 from a tcp/ip socket, when I try to print it to console, no output is coming
void main() {
var out = "\x01\x01";
print("printing out as --> $out <--");
final runes = out.runes.toList();
print(runes);
}
It gives the output as
printing out as --> <--
[1, 1]
dart pad link: https://dartpad.dev/?id=854e4479bfec03d7e8fd40621c845567
I tried to use hex package and it gives Non-hex character detected error.
Questions.
How do I print these types of strings to the console?
If some conversion is needed, how do I know data belongs to these type ?
my socket client is like the following
socket.listen(
// handle data from the server
(Uint8List data) async {
var serverResponse = String.fromCharCodes(data);
print('Server: $serverResponse');
final runes = serverResponse.runes.toList();
print(runes);
},
EDIT
The socket server is the x0vnc server, on reading the input with wire shark I can see the server sent 01 01
To display a hexa, you have to escape the characters like this:
var out = '\\x01\\x01';
this will work.
I suspect you have misunderstood what the server is sending.
Given you've not stated the server language I'm going to guess that ` ab = b'\x01\x01' generates a array with two bytes both with the value 1.
If you treat this as an ASCII value then 1 is a non printable character.
As such you need to iterate over the array and convert each byte into a suitable visual format.
This might mean that when you see a 1 you print x01.
Edit:
actually dart will convert an int to a string for you:
void main() {
final bytes = <int>[1, 2, 3];
for (final byte in bytes) {
print(byte.toString());
}
}

Connecting to Coinex API issue

I try to connect to Coinex API through a Java program
I follow exact patter that mentioned in below link for authorisation
https://github.com/coinexcom/coinex_exchange_api/wiki/012security_authorization
I MD5 has whole query string that is like below , and put result in authorization in request header parameter
tonce=1635504041595&access_id=XXXX&secret_key=YYYY
My intentions is to get account balance so my Get request URL is
https://api.coinex.com/v1//balance/info?tonce=1635504041595&access_id=XXXX
but server return below error
{"code": 25, "data": {}, "message": "Signature Incorrect"}
Anybody can advice what is the issue , thanks AndyJ
well this is my encode method:
public static String encode(String str) {
try {
// Generate a summary of MD5 encryption calculations
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes("UTF-8"));
// digest() finally determines to return the md5 hash value, returning a value of 8 as a string. Because the md5 hash value is a 16-bit hex value, it is actually an 8-bit character.
// The BigInteger function converts an 8-bit string into a 16-bit hex value, represented by a string; gets a hash value in the form of a string
String md5 = new BigInteger(1, md.digest()).toString(16);
//BigInteger will omit 0 and need to be completed to 32 bits
return fillMD5(md5).toUpperCase();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
and one more thing,
your timestmap should have 10 digits, remove the last 3 "000" like this:
Integer.parseInt(String.valueOf(timestamp).substring(0, 10));

RSA2048 signature output Base64length

I am trying to sign a text using a certificate in my personal store. I am supposed to sign it with RSA2048 and then convert the output to the BASE64 string. The output I am getting is just 172 characters. Can you help understand is better where am I making mistake? As per my understanding, the output base64 length should be more.
RSAParameters privateKey = new RSAParameters();
foreach (X509Certificate2 cert in my.Certificates)
{
if (cert.Subject.Contains(certSubject))
{
using (var rsa = cert.GetRSAPrivateKey())
{
UnicodeEncoding encoding = new UnicodeEncoding();
byte[] data = encoding.GetBytes(text);
return rsa.SignData(data, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
}
}

Why Encoding giving different results?

This is my string
<Auth uid="" tid="" ver="" txn="" lk=""><Meta udc="" fdc="" idc="" pip="" lot="P" lov=""/><Skey ci="">03ec063e6a932b12130090c7112a15ba30bb5c0db05b9a0fd22dbd8d33fd61ea1fd1dca544905d5c77c31783376a0b94bf6136ecf9e10dbc5cb3cd09d335c4b4c114b49c5124306a3ea9c0ce124d8da4135de27a99d60085d77a11c2769207bd700fd61d80867e043557713d9dc030fec6949e1049811285e55a561644e12ead734dc61d3caa89b313879da8339efe8163bbcc750cc7901a9fb7353920e544bc851a76e07206a357d34123fb7703440d793063f8bfc54293522266f8e12a059dadfd8822d3585f230265094501d8014ab45b896928ef03062e4745a31d5e2be9b0c1dd61c95fa89dc8e1d66ab34b438a49aaa055055a2ce680719d3e62e3cefa</Skey><Data type="">55c8623b6b26ce63b0cc4fd7333d7ef47cc02e4bb27e4fef879092f487698bcc575b571c5ca834d3b6dd23ab8c73877ecfc243427d34239c9276a0187ab4e1a13559172c57de0a9aa66f8497ecc757449889d9e00cc958963838eedbccf5f6c5d4d426cba12869b2ee530e5b32d08e1123839b348efc51999a384fc46629d2beb75638650ec6a041698ac1411a306362174c8d38687832095b27f36c3f59586fbf73370e79488b03157bd5e12305140c29f1fc4d8500157e93ec71c5b829f7d23f7fcb5079fa9d21c90bc8ac2c043b7c221e45eb2ea1ba14091cdc614a5a1591153072bcbdcfaab8b517f9bfdcf66bfdef1ba1b7455edd37c2b5a08ce299f16219a6398368c1b08aa236c93f1a6949f0e8aada425c7fe3a318ae507e3ec1e6108b66c5dff1872071c15fca0e0ffd3986b2fecd0105b1667526b1760c742a2812b46f0a6775447bddf4387574d16ff85418bce76328496042d6b4d8fde3fac902580a3eb0f4ebd12b0dc653fc29eee45fcb183a1a352a58b464385e5596203c9e1273ab5b1e48a98059614e8924f25aa506aaf3328fba4cf218ecd242fa68976b73ff75c92f1bc96e434463804ad34772184f7e1e1d6d8a7a61f33e354b60c35735488a3ca6dd57ac544d5ed77338bb73178d62bbcde6e6e1997c87b1801823fa904e318f2e33cafa99b9b7d8bbe25d039296d4a22228196a00a89ce27e690ed29c81db23dc683ef6bcd8a1bb77dc8b95725b1a874fc9059aa91d55787357ffea77c2bb71863370e7cdf96efc4f3f975168c1a74861d6f776632e1cc2e0c40a247f734db07847d2eb4d6bcbbe57bb8b7c61f44c1ff1571cb70c9acf650412205325a4a005ad286b705943b4f9cc160e268cf3174cc5031f9e4b47f6df8f52bc6fc42ba1bcef4fb56a12591e7d3eedec0124c2ed300215c263010925a1c56161376019d8de44a062f81f667818f90b269b61482453ff469529c91c0bb5771ffae848a6dbbe57816a6bde84cdaf576f1279a65b1dc3dc92ed3bdf80ccbde1373f6b098f28c33e905a39138b83713bdccc45b1bf05a76be308e3f16bef17655df0ef45dbf4b661e8ecae5cb819e751d1f9bd80adcda398dd7044c7e283aa88f7c174</Data><Hmac>4c4a58555a484c6a4651486d344a6b586f586131536555573373594a30757768593046345435644c336677576a2b65682b686e416e6d52634878383751767632</Hmac></Auth>
And I am using This Code
public String encode(String orig)
{
byte[] encoded = Base64.encodeBase64(orig.getBytes());
System.out.println("Original String: " + orig );
String s=new String(encoded);
System.out.println("Base64 Encoded String : " + new String(encoded));
return s;
}
and output is
PEF1dGggdWlkPSIiIHRpZD0iIiB2ZXI9IiIgdHhuPSIiIGxrPSIiPjxNZXRhIHVkYz0iIiBmZGM9IiIgaWRjPSIiIHBpcD0iIiBsb3Q9IlAiIGxvdj0iIi8+PFNrZXkgY2k9IiI+MDNlYzA2M2U2YTkzMmIxMjEzMDA5MGM3MTEyYTE1YmEzMGJiNWMwZGIwNWI5YTBmZDIyZGJkOGQzM2ZkNjFlYTFmZDFkY2E1NDQ5MDVkNWM3N2MzMTc4MzM3NmEwYjk0YmY2MTM2ZWNmOWUxMGRiYzVjYjNjZDA5ZDMzNWM0YjRjMTE0YjQ5YzUxMjQzMDZhM2VhOWMwY2UxMjRkOGRhNDEzNWRlMjdhOTlkNjAwODVkNzdhMTFjMjc2OTIwN2JkNzAwZmQ2MWQ4MDg2N2UwNDM1NTc3MTNkOWRjMDMwZmVjNjk0OWUxMDQ5ODExMjg1ZTU1YTU2MTY0NGUxMmVhZDczNGRjNjFkM2NhYTg5YjMxMzg3OWRhODMzOWVmZTgxNjNiYmNjNzUwY2M3OTAxYTlmYjczNTM5MjBlNTQ0YmM4NTFhNzZlMDcyMDZhMzU3ZDM0MTIzZmI3NzAzNDQwZDc5MzA2M2Y4YmZjNTQyOTM1MjIyNjZmOGUxMmEwNTlkYWRmZDg4MjJkMzU4NWYyMzAyNjUwOTQ1MDFkODAxNGFiNDViODk2OTI4ZWYwMzA2MmU0NzQ1YTMxZDVlMmJlOWIwYzFkZDYxYzk1ZmE4OWRjOGUxZDY2YWIzNGI0MzhhNDlhYWEwNTUwNTVhMmNlNjgwNzE5ZDNlNjJlM2NlZmE8L1NrZXk+PERhdGEgdHlwZT0iIj41NWM4NjIzYjZiMjZjZTYzYjBjYzRmZDczMzNkN2VmNDdjYzAyZTRiYjI3ZTRmZWY4NzkwOTJmNDg3Njk4YmNjNTc1YjU3MWM1Y2E4MzRkM2I2ZGQyM2FiOGM3Mzg3N2VjZmMyNDM0MjdkMzQyMzljOTI3NmEwMTg3YWI0ZTFhMTM1NTkxNzJjNTdkZTBhOWFhNjZmODQ5N2VjYzc1NzQ0OTg4OWQ5ZTAwY2M5NTg5NjM4MzhlZWRiY2NmNWY2YzVkNGQ0MjZjYmExMjg2OWIyZWU1MzBlNWIzMmQwOGUxMTIzODM5YjM0OGVmYzUxOTk5YTM4NGZjNDY2MjlkMmJlYjc1NjM4NjUwZWM2YTA0MTY5OGFjMTQxMWEzMDYzNjIxNzRjOGQzODY4NzgzMjA5NWIyN2YzNmMzZjU5NTg2ZmJmNzMzNzBlNzk0ODhiMDMxNTdiZDVlMTIzMDUxNDBjMjlmMWZjNGQ4NTAwMTU3ZTkzZWM3MWM1YjgyOWY3ZDIzZjdmY2I1MDc5ZmE5ZDIxYzkwYmM4YWMyYzA0M2I3YzIyMWU0NWViMmVhMWJhMTQwOTFjZGM2MTRhNWExNTkxMTUzMDcyYmNiZGNmYWFiOGI1MTdmOWJmZGNmNjZiZmRlZjFiYTFiNzQ1NWVkZDM3YzJiNWEwOGNlMjk5ZjE2MjE5YTYzOTgzNjhjMWIwOGFhMjM2YzkzZjFhNjk0OWYwZThhYWRhNDI1YzdmZTNhMzE4YWU1MDdlM2VjMWU2MTA4YjY2YzVkZmYxODcyMDcxYzE1ZmNhMGUwZmZkMzk4NmIyZmVjZDAxMDViMTY2NzUyNmIxNzYwYzc0MmEyODEyYjQ2ZjBhNjc3NTQ0N2JkZGY0Mzg3NTc0ZDE2ZmY4NTQxOGJjZTc2MzI4NDk2MDQyZDZiNGQ4ZmRlM2ZhYzkwMjU4MGEzZWIwZjRlYmQxMmIwZGM2NTNmYzI5ZWVlNDVmY2IxODNhMWEzNTJhNThiNDY0Mzg1ZTU1OTYyMDNjOWUxMjczYWI1YjFlNDhhOTgwNTk2MTRlODkyNGYyNWFhNTA2YWFmMzMyOGZiYTRjZjIxOGVjZDI0MmZhNjg5NzZiNzNmZjc1YzkyZjFiYzk2ZTQzNDQ2MzgwNGFkMzQ3NzIxODRmN2UxZTFkNmQ4YTdhNjFmMzNlMzU0YjYwYzM1NzM1NDg4YTNjYTZkZDU3YWM1NDRkNWVkNzczMzhiYjczMTc4ZDYyYmJjZGU2ZTZlMTk5N2M4N2IxODAxODIzZmE5MDRlMzE4ZjJlMzNjYWZhOTliOWI3ZDhiYmUyNWQwMzkyOTZkNGEyMjIyODE5NmEwMGE4OWNlMjdlNjkwZWQyOWM4MWRiMjNkYzY4M2VmNmJjZDhhMWJiNzdkYzhiOTU3MjViMWE4NzRmYzkwNTlhYTkxZDU1Nzg3MzU3ZmZlYTc3YzJiYjcxODYzMzcwZTdjZGY5NmVmYzRmM2Y5NzUxNjhjMWE3NDg2MWQ2Zjc3NjYzMmUxY2MyZTBjNDBhMjQ3ZjczNGRiMDc4NDdkMmViNGQ2YmNiYmU1N2JiOGI3YzYxZjQ0YzFmZjE1NzFjYjcwYzlhY2Y2NTA0MTIyMDUzMjVhNGEwMDVhZDI4NmI3MDU5NDNiNGY5Y2MxNjBlMjY4Y2YzMTc0Y2M1MDMxZjllNGI0N2Y2ZGY4ZjUyYmM2ZmM0MmJhMWJjZWY0ZmI1NmExMjU5MWU3ZDNlZWRlYzAxMjRjMmVkMzAwMjE1YzI2MzAxMDkyNWExYzU2MTYxMzc2MDE5ZDhkZTQ0YTA2MmY4MWY2Njc4MThmOTBiMjY5YjYxNDgyNDUzZmY0Njk1MjljOTFjMGJiNTc3MWZmYWU4NDhhNmRiYmU1NzgxNmE2YmRlODRjZGFmNTc2ZjEyNzlhNjViMWRjM2RjOTJlZDNiZGY4MGNjYmRlMTM3M2Y2YjA5OGYyOGMzM2U5MDVhMzkxMzhiODM3MTNiZGNjYzQ1YjFiZjA1YTc2YmUzMDhlM2YxNmJlZjE3NjU1ZGYwZWY0NWRiZjRiNjYxZThlY2FlNWNiODE5ZTc1MWQxZjliZDgwYWRjZGEzOThkZDcwNDRjN2UyODNhYTg4ZjdjMTc0PC9EYXRhPjxIbWFjPjRjNGE1ODU1NWE0ODRjNmE0NjUxNDg2ZDM0NGE2YjU4NmY1ODYxMzE1MzY1NTU1NzMzNzM1OTRhMzA3NTc3Njg1OTMwNDYzNDU0MzU2NDRjMzM2Njc3NTc2YTJiNjU2ODJiNjg2ZTQxNmU2ZDUyNjM0ODc4MzgzNzUxNzY3NjMyPC9IbWFjPjwvQXV0aD4=
but when I use online BAse 64 encoder it gives output
PEF1dGggdWlkPSIiIHRpZD0iIiB2ZXI9IiIgdHhuPSIiIGxrPSIiPjxNZXRhIHVkYz0iIiBmZGM9IiIgaWRjPSIiIHBpcD0iIiBsb3Q9IlAiIGxvdj0iIi8+PFNrZXkgY2k9IiI+MDNlYzA2M2U2YTkzMmIxMjEzMDA5MGM3MTEyYTE1YmEzMGJiNWMwZGIwNWI5YTBmZDIyZGJkOGQzM2ZkNjFlYTFmZDFkY2E1NDQ5MDVkNWM3N2MzMTc4MzM3NmEwYjk0YmY2MTM2ZWNmOWUxMGRiYzVjYjNjZDA5ZDMzNWM0YjRjMTE0YjQ5YzUxMjQzMDZhM2VhOWMwY2UxMjRkOGRhNDEzNWRlMjdhOTlkNjAwODVkNzdhMTFjMjc2OTIwN2JkNzAwZmQ2MWQ4MDg2N2UwNDM1NTc3MTNkOWRjMDMwZmVjNjk0OWUxMDQ5ODExMjg1ZTU1YTU2MTY0NGUxMmVhZDczNGRjNjFkM2NhYTg5YjMxMzg3OWRhODMzOWVmZTgxNjNiYmNjNzUwY2M3OTAxYTlmYjczNTM5MjBlNTQ0YmM4NTFhNzZlMDcyMDZhMzU3ZDM0MTIzZmI3NzAzNDQwZDc5MzA2M2Y4YmZjNTQyOTM1MjIyNjZmOGUxMmEwNTlkYWRmZDg4MjJkMzU4NWYyMzAyNjUwOTQ1MDFkODAxNGFiNDViODk2OTI4ZWYwMzA2MmU0NzQ1YTMxZDVlMmJlOWIwYzFkZDYxYzk1ZmE4OWRjOGUxZDY2YWIzNGI0MzhhNDlhYWEwNTUwNTVhMmNlNjgwNzE5ZDNlNjJlM2NlZmE8L1NrZXk+PERhdGEgdHlwZT0iIj41NWM4NjIzYjZiMjZjZTYzYjBjYzRmZDczMzNkN2VmNDdjYzAyZTRiYjI3ZTRmZWY4NzkwOTJmNDg3Njk4YmNjNTc1YjU3MWM1Y2E4MzRkM2I2ZGQyM2FiOGM3Mzg3N2VjZmMyNDM0MjdkMzQyMzljOTI3NmEwMTg3YWI0ZTFhMTM1NTkxNzJjNTdkZTBhOWFhNjZmODQ5N2VjYzc1NzQ0OTg4OWQ5ZTAwY2M5NTg5NjM4MzhlZWRiY2NmNWY2YzVkNGQ0MjZjYmExMjg2OWIyZWU1MzBlNWIzMmQwOGUxMTIzODM5YjM0OGVmYzUxOTk5YTM4NGZjNDY2MjlkMmJlYjc1NjM4NjUwZWM2YTA0MTY5OGFjMTQxMWEzMDYzNjIxNzRjOGQzODY4NzgzMjA5NWIyN2YzNmMzZjU5NTg2ZmJmNzMzNzBlNzk0ODhiMDMxNTdiZDVlMTIzMDUxNDBjMjlmMWZjNGQ4NTAwMTU3ZTkzZWM3MWM1YjgyOWY3ZDIzZjdmY2I1MDc5ZmE5ZDIxYzkwYmM4YWMyYzA0M2I3YzIyMWU0NWViMmVhMWJhMTQwOTFjZGM2MTRhNWExNTkxMTUzMDcyYmNiZGNmYWFiOGI1MTdmOWJmZGNmNjZiZmRlZjFiYTFiNzQ1NWVkZDM3YzJiNWEwOGNlMjk5ZjE2MjE5YTYzOTgzNjhjMWIwOGFhMjM2YzkzZjFhNjk0OWYwZThhYWRhNDI1YzdmZTNhMzE4YWU1MDdlM2VjMWU2MTA4YjY2YzVkZmYxODcyMDcxYzE1ZmNhMGUwZmZkMzk4NmIyZmVjZDAxMDViMTY2NzUyNmIxNzYwYzc0MmEyODEyYjQ2ZjBhNjc3NTQ0N2JkZGY0Mzg3NTc0ZDE2ZmY4NTQxOGJjZTc2MzI4NDk2MDQyZDZiNGQ4ZmRlM2ZhYzkwMjU4MGEzZWIwZjRlYmQxMmIwZGM2NTNmYzI5ZWVlNDVmY2IxODNhMWEzNTJhNThiNDY0Mzg1ZTU1OTYyMDNjOWUxMjczYWI1YjFlNDhhOTgwNTk2MTRlODkyNGYyNWFhNTA2YWFmMzMyOGZiYTRjZjIxOGVjZDI0MmZhNjg5NzZiNzNmZjc1YzkyZjFiYzk2ZTQzNDQ2MzgwNGFkMzQ3NzIxODRmN2UxZTFkNmQ4YTdhNjFmMzNlMzU0YjYwYzM1NzM1NDg4YTNjYTZkZDU3YWM1NDRkNWVkNzczMzhiYjczMTc4ZDYyYmJjZGU2ZTZlMTk5N2M4N2IxODAxODIzZmE5MDRlMzE4ZjJlMzNjYWZhOTliOWI3ZDhiYmUyNWQwMzkyOTZkNGEyMjIyODE5NmEwMGE4OWNlMjdlNjkwZWQyOWM4MWRiMjNkYzY4M2VmNmJjZDhhMWJiNzdkYzhiOTU3MjViMWE4NzRmYzkwNTlhYTkxZDU1Nzg3MzU3ZmZlYTc3YzJiYjcxODYzMzcwZTdjZGY5NmVmYzRmM2Y5NzUxNjhjMWE3NDg2MWQ2Zjc3NjYzMmUxY2MyZTBjNDBhMjQ3ZjczNGRiMDc4NDdkMmViNGQ2YmNiYmU1N2JiOGI3YzYxZjQ0YzFmZjE1NzFjYjcwYzlhY2Y2NTA0MTIyMDUzMjVhNGEwMDVhZDI4NmI3MDU5NDNiNGY5Y2MxNjBlMjY4Y2YzMTc0Y2M1MDMxZjllNGI0N2Y2ZGY4ZjUyYmM2ZmM0MmJhMWJjZWY0ZmI1NmExMjU5MWU3ZDNlZWRlYzAxMjRjMmVkMzAwMjE1YzI2MzAxMDkyNWExYzU2MTYxMzc2MDE5ZDhkZTQ0YTA2MmY4MWY2Njc4MThmOTBiMjY5YjYxNDgyNDUzZmY0Njk1MjljOTFjMGJiNTc3MWZmYWU4NDhhNmRiYmU1NzgxNmE2YmRlODRjZGFmNTc2ZjEyNzlhNjViMWRjM2RjOTJlZDNiZGY4MGNjYmRlMTM3M2Y2YjA5OGYyOGMzM2U5MDVhMzkxMzhiODM3MTNiZGNjYzQ1YjFiZjA1YTc2YmUzMDhlM2YxNmJlZjE3NjU1ZGYwZWY0NWRiZjRiNjYxZThlY2FlNWNiODE5ZTc1MWQxZjliZDgwYWRjZGEzOThkZDcwNDRjN2UyODNhYTg4ZjdjMTc0PC9EYXRhPjxIbWFjPjRjNGE1ODU1NWE0ODRjNmE0NjUxNDg2ZDM0NGE2YjU4NmY1ODYxMzE1MzY1NTU1NzMzNzM1OTRhMzA3NTc3Njg1OTMwNDYzNDU0MzU2NDRjMzM2Njc3NTc2YTJiNjU2ODJiNjg2ZTQxNmU2ZDUyNjM0ODc4MzgzNzUxNzY3NjMyPC9IbWFjPjwvQXV0aD4NCg==
Last digits are changed
Why is that?
It's because you have extra "\n" at the end of second string. It can be seen easy if you run this command:
echo "your base 64 encoded string"|base64 -d|hexdump -C
in the linux shell

Generating Content-MD5 for AWS S3 REST in Haxe

I'm trying to add a Content-MD5 header to my REST calls to AWS S3 in Haxe (compiling to PHP). It's generated by
var contentMD5 = haxe.crypto.Base64.encode(haxe.io.Bytes.ofString(haxe.crypto.Md5.encode(_data)));
with _data in my example being
<Delete><Object><Key>nathan/storage/72ENgrtnpA5VAoy7zEpzPRNEChN0TRGc</Key></Object><Object><Key>nathan/storage/7rlZZSJFvZ7AxUhQZsh4ufn9M2x8m1ae</Key></Object><Object><Key>nathan/storage/HN8NFlUnJiiGo7qlddvRrlGE6hPmWMnZ</Key></Object><Object><Key>nathan/storage/SFsZ8z63DswEVFJQJqmUwbenaWyfZ8zb</Key></Object><Object><Key>nathan/storage/YSYXXgYbSZixOKo27PL65ii6nCeiFesl</Key></Object></Delete>
My full request sent to AWS (for a multiple delete call as described here http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html), using AWS signature version 4 (bucket, signature, and credential shortened):
POST /?delete= HTTP/1.1
Host: mybucket.s3-eu-central-1.amazonaws.com
Content-Length: 392
x-amz-content-sha256: 53da469cb6fc9d0701a1c6ff98d48edd361cd8a90d8a290a2dd224b2681bf7fb
x-amz-date: 20150923T195117Z
Authorization: AWS4-HMAC-SHA256 Credential=zzzzz/20150923/eu-central-1/s3/aws4_request, SignedHeaders=content-md5;host;x-amz-date, Signature=xxxxx
Content-MD5: MDAzNDZmZjJiMGJkMDFkNzVjYzFiOGE4MzI5NTc0NGY=
<Delete><Object><Key>nathan/storage/72ENgrtnpA5VAoy7zEpzPRNEChN0TRGc</Key></Object><Object><Key>nathan/storage/7rlZZSJFvZ7AxUhQZsh4ufn9M2x8m1ae</Key></Object><Object><Key>nathan/storage/HN8NFlUnJiiGo7qlddvRrlGE6hPmWMnZ</Key></Object><Object><Key>nathan/storage/SFsZ8z63DswEVFJQJqmUwbenaWyfZ8zb</Key></Object><Object><Key>nathan/storage/YSYXXgYbSZixOKo27PL65ii6nCeiFesl</Key></Object></Delete>
The response is as follows (RequestId and HostId shortened)
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidDigest</Code><Message>The Content-MD5 you specified was invalid.</Message><Content-MD5>MDAzNDZmZjJiMGJkMDFkNzVjYzFiOGE4MzI5NTc0NGY=</Content-MD5><RequestId>rrrrrr</RequestId><HostId>ccccccc</HostId></Error>
In my opinion, the generated MD5 is correct. I verified the value with other tools. Also, note that x-amz-content-sha256 is based on the same _data and AWS accepted that header in my previous (non delete) calls.
What am I missing here? Why does my MD5 value differ from the one AWS generates?
You're very close.
Here's the problem:
An md5 hash is 16 bytes in binary representation, 32 characters in hexadecimal representation, and 24 characters (Including padding) in base64.
Yours is approximately twice as long. You appear to be taking the 32 character hex md5, and base64-encoding that, resulting in a base64 string of about 44 characters, instead of just encoding the binary form.
Note that the length of the output, 44 vs 24 is not a factor of two in spite of my assertion that you are encoding 32 initial bytes instead of 16. That's expected, because base64 output_bytes = ceil(input_bytes/3) * 4.
My expertise is with the S3 API -- not haxe, which I've never used -- so the above is almost certainly correct, but the following is wild speculation.
var contentMD5 = haxe.crypto.Base64.encode(haxe.crypto.Md5.make(_data));
Any one out there looking to do this in java can use this code
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Base64;
public class GenerateMD5 {
public static void main(String args[]) throws Exception{
String s = "<CORSConfiguration> <CORSRule> <AllowedOrigin>http://www.example.com</AllowedOrigin> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration>";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(s.getBytes());
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
/*for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}*/
System.out.println(sb.toString());
StringBuffer sbi = new StringBuffer();
byte [] bytes = Base64.encodeBase64(digest);
String finalString = new String(bytes);
System.out.println(finalString);
}
}
The commented code is where most people get it wrong changing it to hex