Скрипт Powershell для хеширования

У меня есть файл CSV (значения, разделенные запятыми) Файл выглядит так:

20171108,120909470,SO1244,12,101 
20171109,122715740,AG415757,11,101

Мне нужно скрыть данные в (например) столбцах 3 и, не затрагивая другие записи в файле.

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

Мне нужно отправить данные третьей стороне, а некоторые столбцы содержат конфиденциальную информацию (например, имена клиентов). Мне нужно, чтобы файл был завершен, и когда строка заменяется, мне нужно, чтобы это выполнялось одинаково каждый раз, когда она встречается (чтобы оставалось любое сопоставление или группировка). Он не требует военного шифрования, просто чтобы его было трудно отменить. Поскольку мне нужно делать это с перерывами, идеальным решением было бы скриптовое решение.

Как проще всего добиться этого с помощью инструмента или сценария командной строки?

Я предпочитаю сценарий PowerShell, поскольку для этого не требуется никакого дополнительного программного обеспечения ...

Этот вопрос кажется дубликатом Мне нужно хешировать (скрыть) столбец данных в файле CSV. Предпочтительный сценарий, но предложенное решение не решило мою проблему и выдает следующую ошибку

You cannot call a method on a null-valued expression.
At C:\Users\mey\Hashr.ps1:4 char:5
+     $_.column3 = $_.column3.gethashcode()

Сценарий следующий

(Import-Csv .\results.csv -delimiter ',' ) | ForEach-Object{ 
 $_.column3 = $_.column3.gethashcode()
 $_
} | Export-Csv .\myobfuscated.csv -NoTypeInformation -delimiter ','

Обновлять:

Вот программа, которую я запускаю, и она была предложена @BaconBits:

    param (
    [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
    [String[]]
    $String,
    [Parameter(Position = 1)]
    [ValidateSet('SHA1', 'MD5', 'SHA256', 'SHA384', 'SHA512')]
    [String]
    $HashName = 'SHA256'
)

process {
    $StringBuilder = [System.Text.StringBuilder]::new(128)
    [System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String)) | ForEach-Object { 
        [Void]$StringBuilder.Append($_.ToString("x2")) 
    } 
    $StringBuilder.ToString() 
}
}
$csv = Import-Csv .\results.csv -delimiter ',' 
foreach ($line in $csv) {
$line.column1 = Get-StringHash $line.column1
}
$csv | Export-Csv .\myobfuscated.csv -NoTypeInformation -delimiter ','

Файл csv, который я импортирую, является результатом другой созданной мной Java-программы, и он не создает заголовка, он просто заполняет файл csv значениями

Я получаю эту ошибку Get-StringHash: невозможно привязать аргумент к параметру String, поскольку он имеет значение NULL.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
1 316
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Основываясь на документ, вы не захотите использовать GetHashCode() таким образом:

A hash code is intended for efficient insertion and lookup in collections that are based on a hash table. A hash code is not a permanent value. For this reason:

  • Do not serialize hash code values or store them in databases.

  • Do not use the hash code as the key to retrieve an object from a keyed collection.

  • Do not send hash codes across application domains or processes. In some cases, hash codes may be computed on a per-process or per-application domain basis.

  • Do not use the hash code instead of a value returned by a cryptographic hashing function if you need a cryptographically strong hash. For cryptographic hashes, use a class derived from the System.Security.Cryptography.HashAlgorithm or System.Security.Cryptography.KeyedHashAlgorithm class.

  • Do not test for equality of hash codes to determine whether two objects are equal. (Unequal objects can have identical hash codes.) To test for equality, call the ReferenceEquals or Equals method.

Пункт 4 - основная проблема. Нет гарантии, что хеширование необратимо. Используемая функция хеширования является деталью реализации, а не безопасной криптографической функцией, такой как SHA.

Я бы использовал такую ​​функцию:

function Get-StringHash { 
    [CmdletBinding()]

    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [String[]]
        $String,
        [Parameter(Position = 1)]
        [ValidateSet('SHA1', 'MD5', 'SHA256', 'SHA384', 'SHA512')]
        [String]
        $HashName = 'SHA256'
    )

    process {
        $StringBuilder = [System.Text.StringBuilder]::new(128)
        [System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String)) | ForEach-Object { 
            [Void]$StringBuilder.Append($_.ToString("x2")) 
        } 
        $StringBuilder.ToString() 
    }
}

$csv = Import-Csv .\results.csv -delimiter ',' -Header column1,column2,column3,column4,column5
foreach ($line in $csv) {
    $line.column3 = Get-StringHash $line.column3
}
$csv | Export-Csv .\myobfuscated.csv -NoTypeInformation -delimiter ','

Я полагаю, что основал эту функцию на Вот этот, но прошло некоторое время с тех пор, как я ее написал.

Отредактируйте LotPings, чтобы показать результаты хеширования

"column1","column2","column3","column4","column5"
"20171108","120909470","0cdd3c3acdb7cfa107286565c044c5a0f1e58268f6f10e7e3415ff84942e577d","12","101 "
"20171109","122715740","0a7fb9f6bb7a180f2fd9429b0fbd1e7b0a83597b6a64aa6a123cef3e84700fe3","11","101"

Большое спасибо за отзыв, но это вызывает еще одну ошибку. Get-StringHash: Невозможно привязать аргумент к параметру String, потому что он имеет значение null.

Yacine Walid 30.04.2018 16:11

@YacineWalid Похоже, вы ссылаетесь на несуществующий столбец. Вы уверены, что название вашей колонки - column3? Что $csv[0] показывает названия столбцов?

Bacon Bits 30.04.2018 16:17

@YacineWalid Тогда я бы попробовал $line.'Column #2', если вам нужен третий столбец. Имя столбца, которое вы используете, должно совпадать с именами столбцов в заголовке CSV.

Bacon Bits 30.04.2018 17:06

ДА, это работает, и сценарий работает правильно, но в файле csv результатов не происходит хеширования :(

Yacine Walid 30.04.2018 17:14

Скрипт экспортирует в .\myobfuscated.csv, а не в results.csv, и здесь он работает.

user6811411 30.04.2018 18:44

да, конечно, он экспортируется в. \ myobfuscated.csv, но в моем случае хеширования не происходит

Yacine Walid 01.05.2018 07:58

@LotPings, вы можете показать нам результат хеширования в вашем случае?

Yacine Walid 01.05.2018 11:34

Я добавил содержимое файла myobfuscated.csv в конце ответа @BaconBits.

user6811411 01.05.2018 11:47

Вот результат, который он показывает для меня '20171108, "120909470", "SO19086", "12", "101"' 20171108, "120918640", "SO455", "12", "101"

Yacine Walid 01.05.2018 14:11

Он просто добавляет "" в каждый столбец, кроме первого.

Yacine Walid 01.05.2018 14:12

@YacineWalid Похоже, мой код работает для меня и других. Вам нужно будет обновить вопрос, указав точный код, который вы используете, и хотя бы одну строку из вашего фактического файла данных включая заголовок. Вы не делаете того, чем занимаемся мы, и невозможно сказать, что именно.

Bacon Bits 01.05.2018 14:39

@BaconBits Я обновил сообщение скриптом, который я запускаю, и csv, который я импортирую

Yacine Walid 01.05.2018 15:11

@YacineWalid Вам нужно либо отредактировать csv, чтобы он содержал заголовки, либо добавить этот -Header column1,column2,column3,column4,column5 к команде Import-Csv

user6811411 02.05.2018 10:26

Большое спасибо за вашу помощь, я настоящий новичок в Powershell, и я вроде как борюсь с командами в данный момент, вы можете показать мне шаги для добавления '-header' к команде Import-Csv?

Yacine Walid 02.05.2018 10:32

@YacineWalid см. Выше измененный сценарий. Кстати, вы должны отметить это как правильный ответ.

user6811411 02.05.2018 10:37

Bacon Bits, похоже, имеет правильную методологию за вычетом одной части. Цикл ForEach в исходном примере не изменяет исходную переменную. Кроме того, похоже, что столбец, который вы хотите изменить, - это не «Столбец 3», а «Столбец № 2», поскольку заголовки начинаются с нуля. Я повторю функцию, предоставленную в предложении Bacon Bits.

function Get-StringHash { 
    [CmdletBinding()]

    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [String[]]
        $String,
        [Parameter(Position = 1)]
        [ValidateSet('SHA1', 'MD5', 'SHA256', 'SHA384', 'SHA512')]
        [String]
        $HashName = 'SHA256'
    )

    process {
        $StringBuilder = [System.Text.StringBuilder]::new(128)
        [System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String)) | ForEach-Object { 
            [Void]$StringBuilder.Append($_.ToString("x2")) 
        } 
        $StringBuilder.ToString() 
    }
}

Я бы предложил для замены:

$csv = Import-Csv .\results.csv | Select-Object *,@{n='Column #2';e = {Get-StringHash $_.'Column #2'}} -ExcludeProperty 'Column #2'
$CSV | Export-Csv .\myobfuscated.csv -NoTypeInformation

Это поместит "Столбец №2" последним в CSV. Вы можете просто перечислить их явно, если вам нужно, чтобы они отображались в том же порядке, например:

Select-Object 'Column #0','Column #1',@{n='Column #2';e = {Get-StringHash $_.'Column #2'}},'Column #3'

Это решение кажется точным, но и у меня оно не работает: // Select-Object: не найден параметр, который соответствует имени параметра ExcluedeProperty.

Yacine Walid 01.05.2018 08:19

В своем сообщении вы неправильно написали "исключить". Если вы написали правильно, то, может быть, проблема в версии? Это определенно в версиях 3 и выше.

markg 16.05.2018 02:07

Другие вопросы по теме