Преобразование строки в массив байтов в PowerShell версии 2

#powershell #encoding #utf-8 #bytearray #sha1

#powershell #кодирование #utf-8 #массивы #sha1

Вопрос:

То, что я пытаюсь сделать, это использовать шифрование SHA1 UTF-8, а затем кодировку base64 и значение строки пароля. Однако мне нужно было сначала выполнить шифрование, а затем кодировку, но я сделал это наоборот.

Вот код:

 # 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) 
  

Итак, когда я приступил к выполнению хэширования, я понял, что мне нужен байт [] из строки, и я не уверен, как это сделать. Я думаю, что есть простой способ из .Сетевые библиотеки, но не смог найти пример.

Итак, если у меня есть строка, например:

 $string = "password"
  

Как мне преобразовать это в массив байтов, который я могу использовать в :: ComputeHash($ string)?

Итак, в итоге я должен получить зашифрованный пароль SHA-1 и base 64 в кодировке UTF-8, что и делает приведенный выше код, но он возвращается иначе, чем когда я кодировал то же самое в java, где я сначала зашифровал его, а затем преобразовал этот результат в кодировку base 64.

Я делаю предположение, что, хотя прямое шифрование строки не поддерживается в api, может существовать обходной путь, который позволит вам это сделать. Это то, что я пытаюсь сделать.

Итак, я предполагаю, что моя проблема с кодом заключается в том, что мне пришлось сначала зашифровать его, а затем закодировать, чтобы получить правильное значение. Исправьте, или я что-то здесь упускаю?

Вот соответствующий Java-код, который действительно работает:

 //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));
  

Когда я запускаю Java-код со строкой пароля типа «password», я получаю

[91, -86, 97, -28, -55, -71, 63, 63, 6, -126, 37, 11, 108, -8, 51, 27, 126, -26, -113, -40] что является шифрованием.

Затем я при кодировании в java получаю это: W6ph5Mm5Pz8GgiULbPgzG37mj9g=

но когда я запускаю это в PowerShell, я получаю это, потому что сначала оно кодируется для UTF8:

91 170 97 228 201 185 63 63 6 130 37 11 108 248 51 27 126 230 143 216

Затем, когда я запускаю эту строку кода для ее преобразования, я получаю сообщение об ошибке:

 $base64 = [System.Convert]::FromBase64String($result)
  

Исключение, вызывающее «FromBase64String» с аргументами «1»: «Недопустимая длина для массива символов Base-64».
В строке: 1 символ:45

Однако, если я запускаю новую строку кода, чтобы сделать ее шестнадцатеричной снизу, я получаю:

 $hexResult = [String]::Join("", ($result | % { "{0:X2}" -f $_}))
PS C:Program Files (x86)PowerGUI> Write-Host $hexResult
  

5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8

но мне нужно в конечном итоге получить это значение:

W6ph5Mm5Pz8GgiULbPgzG37mj9g=

Опять же, возможно, это даже невозможно сделать, но я пытаюсь найти обходной путь, чтобы увидеть.

Комментарии:

1. $data1 уже есть массив байтов — вот что Encoding.GetBytes($string1) возвращает.

2. Надеюсь, вы на самом деле не используете UTF-9: en.wikipedia.org/wiki/UTF-9_and_UTF-18

3. Нет, это UTF-8, у меня была опечатка.

4. Вы не хотите использовать FromBase64String, вы хотите использовать ToBase64String. Байты != Base64. Код в моем примере выдает именно тот результат, который вы хотите.

5. Вы правы, это сработало!

Ответ №1:

Скорее всего, вам просто нужно преобразовать ваш хэш в base64 после последней строки.

 $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)
  

Текст-> Байты-> Шифрование / хэш-> Base64

Это очень распространенный шаблон для отправки криптографических данных в текстовом формате.

Комментарии:

1. За исключением этого случая, похоже, что api требует закодированный массив байтов, а не просто массив байтов.

2. Я не уверен, что вы подразумеваете под «api», но массив байтов не знает никакой кодировки. Приведенный выше код совместим с генераторами SHA-1 (хотя некоторые выводят шестнадцатеричный код вместо Base64). Если ваш Java-код хэширует строку, уже закодированную в Base64, то вы, безусловно, можете сделать это и в PowerShell (но это было бы необычно). Может быть, вы могли бы предоставить нам выходные данные, которые выдает программа Java…

3. Библиотека .Net Framework. Код Java сначала выполняет шифрование с помощью дайджеста сообщения, затем использует кодировку UTF-8. По-видимому, .Net Framework не может сделать это таким образом, вот что я имел в виду. Я неоднократно пытался получить массив байтов из строки, но единственный способ добиться успеха — использовать $encoding.getBytes(encodedString), а не $ somevariable.getBytes(regularString)

4. Класс Java MessageDigest также хэширует массив байтов и возвращает массив байтов (который будет соответствовать . ЧИСТЫЙ эквивалент), поэтому я не уверен, к чему вы клоните. Я не уверен, что мы сможем помочь без кода или примера вывода.

5. Понятно, сейчас я добавлю java-код. Под «api» я подразумевал всего лишь библиотеку .Net Framework. Не уверен, было ли это понятно в предыдущих комментариях.

Ответ №2:

Похоже, вы на правильном пути. Вы должны выбрать кодировку символов для преобразования между строкой и массивом байтов. Вы выбрали UTF-8 выше, но есть и другие варианты (например, ASCII, UTF-16 и т.д.).

Прямое шифрование строки не поддерживается.

Комментарии:

1. Я новичок в .Net Framework, поэтому, хотя напрямую не поддерживается, есть ли у вас решение с кодом, которое могло бы работать? Нравится использовать поток вместо массива байтов?

2. @Джеймс, это не имеет значения. В любом случае вам необходимо сопоставить символьные данные<=> байтовые данные (потоки — это байтовые данные). System.Encoding это инструмент для этого. Для этого вам нужно использовать некоторую кодировку, но это не обязательно должен быть UTF-8, который вы используете в данный момент.

Ответ №3:

Проблема, по-видимому, заключается в том, что в первом bytearray у вас есть байты со знаком (-86 = 10101010), а во втором — байты без знака (170 = 10101010).