Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a string to a byte array in PowerShell version 2

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.

like image 925
James Drinkard Avatar asked Nov 08 '11 14:11

James Drinkard


People also ask

How do I convert a string to an array in PowerShell?

Split() function. The . Split() function splits the input string into the multiple substrings based on the delimiters, and it returns the array, and the array contains each element of the input string. By default, the function splits the string based on the whitespace characters like space, tabs, and line-breaks.

What is byte in PowerShell?

All variables in PowerShell are .NET objects, including 8-bit unsigned integer bytes. A byte object is an object of type System.Byte in the .NET class library, hence, it has properties and methods accessible to PowerShell (you can pipe them into get-member).


Video Answer


2 Answers

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.

like image 53
Eric Nicholson Avatar answered Oct 16 '22 14:10

Eric Nicholson


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.

like image 44
Matthew Flaschen Avatar answered Oct 16 '22 14:10

Matthew Flaschen