我有一个每天在 Linux 上收到的 csv 文件。文件本身并未整体加密,但其中一个字段已加密,因此它看起来像这样:
数据,数据,数据,加密数据、数据等
我有一个用于解密的 RSA 密钥,现在我正在逐行解析文件,剪切加密字段,使用 openssl 解密,然后将其放回行中,如下所示:
###cut out the encrypted field into a variable
INFIELD=`echo $DATALINE | cut -d"," -f10`
###decrypt the field into another variable
OUTFIELD=`echo $INFIELD | base64 --decode | openssl rsautl -inkey $SCRIPTFILES/MyKey.rsa -decrypt`
###swap the decrypted value into the original line and append to a temp file
echo $DATALINE | awk -v outfield=$OUTFIELD '{$10 = outfield;print}' FS=, OFS=, >> $DATAPATH/$TEMPFILE
这是可行的,但是令人惊奇的是很慢……处理 600,000 行数据需要 4-5 个小时。有没有更快的方法?
答案1
可能可以猜想,为每一行生成 6-7 个全新的进程是最慢的部分,甚至比实际的 RSA 计算还要慢。请注意,每个实例` `
也是一个子进程(即使它仍然在 shell 内部,并且不像执行完全外部的工具那样繁重),并且每个echo | ...
都是另一个子进程。(据我所知,最近的 Melt/Spectre 缓解措施使这种情况比本来的情况更糟糕。)
因此,更快的方法是使用其他可以执行解密、解码和其他所有操作的语言编写脚本进程中. (即几乎任何不是“shell”并且不依赖于从 /usr/bin 调用工具的语言。)
例如,Python 有“Cryptodome”和“cryptography”模块,Perl 有“CryptX”,而 Ruby 则有“OpenSSL”模块。(其他语言也可用。)当然,几乎所有语言都可以拆分逗号分隔的行并解码 Base64,而无需任何外部帮助。
我目前不知道 OpenSSL 的 rsautl 使用什么具体格式以及如何将其输入到 Cryptodome 库中,但总体思路是:
require 'base64'
require 'openssl'
pkey = OpenSSL::PKey::RSA.new(File.read("MyKey.rsa"))
while line = STDIN.gets()
fields = line.chomp.split(",")
fields[9] = Base64.decode64(fields[9])
fields[9] = pkey.private_decrypt(fields[9])
puts fields.join(",")
end