我有一个CSV文件(逗号分隔值) 该文件如下所示:
20171108,120909470,SO1244,12,101
20171109,122715740,AG415757,11,101
我需要隐藏(例如)第3列中的数据,而不会影响文件中的任何其他条目。
我想使用像SHA1或MD5这样的散列算法来做到这一点,这样相同的字符串将在遇到它们的任何地方恢复到相同的散列值。
我需要将数据发送给第三方,而某些列包含敏感信息(例如客户名称)。我需要文件完整,并且在替换字符串的地方,我需要在每次遇到它时以相同的方式完成(以便保留任何映射或分组)。它不需要军事加密,只是难以扭转。我需要间歇性地使用脚本化解决方案。
使用命令行工具或脚本实现此目的的最简单方法是什么?
首选,我想要一个PowerShell脚本,因为这不需要任何额外的软件来实现......
此问题似乎与I need to hash (obfuscate) a column of data in a CSV file. Script preferred重复,但建议的解决方案无法解决我的问题并引发以下错误
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。
答案 0 :(得分:2)
根据the doc,您不希望以这种方式使用GetHashCode()
:
哈希码用于高效插入和查找 基于哈希表的集合。哈希码不是 永久价值。出于这个原因:
不要序列化哈希码值或将它们存储在数据库中。
请勿使用哈希码作为密钥从密钥集合中检索对象。
不要跨应用程序域或进程发送哈希码。在某些情况下,可以在每个进程上计算哈希码 每个应用程序域的基础。
如果您需要加密强大,请不要使用哈希码而不是加密哈希函数返回的值 哈希值。对于加密哈希,请使用从中派生的类 System.Security.Cryptography.HashAlgorithm或 System.Security.Cryptography.KeyedHashAlgorithm类。
不测试哈希码的相等性以确定两个对象是否相等。 (不等的对象可以具有相同的哈希码。)To 测试相等性,调用ReferenceEquals或Equals方法。
第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 ','
我相信我的功能是基于this one,但是自从我写完以来已经有一段时间了。
通过LotPings编辑以显示哈希
的结果"column1","column2","column3","column4","column5"
"20171108","120909470","0cdd3c3acdb7cfa107286565c044c5a0f1e58268f6f10e7e3415ff84942e577d","12","101 "
"20171109","122715740","0a7fb9f6bb7a180f2fd9429b0fbd1e7b0a83597b6a64aa6a123cef3e84700fe3","11","101"
答案 1 :(得分:0)
Bacon Bits似乎有正确的方法减去一部分。原始示例中的ForEach循环不会修改原始变量。此外,您要修改的列似乎不是“列3”,而是“#2”列#2'因为标题从零开始。我将重复培根比特提出的功能。
A
我建议替换:
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()
}
}
这将把#2;列#2'最后在CSV中。如果您需要它们以相同的顺序出现,您可以简单地列出它们,例如:
$csv = Import-Csv .\results.csv | Select-Object *,@{n='Column #2';e={Get-StringHash $_.'Column #2'}} -ExcludeProperty 'Column #2'
$CSV | Export-Csv .\myobfuscated.csv -NoTypeInformation