OpenSSL 字符串解密问题

Posted

技术标签:

【中文标题】OpenSSL 字符串解密问题【英文标题】:OpenSSL string decryption issue 【发布时间】:2013-06-11 15:30:12 【问题描述】:

我会尽量做到简洁。

我希望能够使用我以前做过的 OpenSSL 加密和解密简单字符串。

但是,必须满足以下条件:

简单的密码短语使用(无密钥) 没有输入/输出文件 不提示输入密码(通过命令行选项指定任一方向)

我占了 50%。我可以通过以下方式成功执行加密:

echo 'someTextIWantToEncrypt' | openssl enc -e -aes-256-cbc -nosalt -pass pass:mySecretPass

输出结果为:

(??bn??v???>??G??.?B??~?

好的,太好了。现在我想解密那个字符串。所以我这样做:

echo -n '(??bn??v???>??G??.?B??~?' | openssl enc -d -aes-256-cbc -pass pass:mySecretPass

甚至作为替代方案:

openssl enc -d -aes-256-cbc -pass pass:mySecretPass <<< '(??bn??v???>??G??.?B??~?'

但我得到了这样的回应:

bad magic number

虽然我不想使用输入/输出文件,但该方法确实 100% 有效:

# encrypt to file
echo -n 'someTextIWantToEncrypt' | openssl enc -e -nosalt -out test.txt -aes-256-cbc -pass pass:mySecretPass 

# decrypt from file
openssl enc -d -nosalt -in test.txt -aes-256-cbc -pass pass:mySecretPass

# result of decryption (is successful):
someTextIWantToEncrypt

那么...我如何不使用输入/输出文件来实现上述解密过程?我觉得我很接近,但缺少一些小细节。

提前致谢。

【问题讨论】:

【参考方案1】:

问题在于加密使用了整个 ASCII 字符集,包括不可打印的字符。如果您希望能够剪切和粘贴加密数据,则需要将其转换为仅可打印的字符。您可以使用-base64(或-a)选项来做到这一点:

echo 'someTextIWantToEncrypt' | \
  openssl enc -base64 -e -aes-256-cbc -nosalt -pass pass:mySecretPass

KPkBkGJ9bs4YHvh24xz7m9jTlYWm1LcIFcWR0DwY4PU=

然后用同样的方法解密:

echo "KPkBkGJ9bs4YHvh24xz7m9jTlYWm1LcIFcWR0DwY4PU=" | \
  openssl enc -base64 -d -aes-256-cbc -nosalt -pass pass:mySecretPass

警告:如果您使用的是 openssl,我只能假设数据的机密性,因此密码对您很重要。如果是这种情况,您应该永远不要在命令行上提供密码,因为它可能会暴露给任何有权运行ps 的人。

更好的解决方案是将密码存储在环境变量中,并让 openssl 从那里读取:

export passwd="mySecretPass"
echo "KPkBkGJ9bs4YHvh24xz7m9jTlYWm1LcIFcWR0DwY4PU=" | \
  openssl enc -base64 -d -aes-256-cbc -nosalt -pass env:passwd

【讨论】:

你是对的,我已经明白了——你和帮助我的人都是对的。道具给你们两个。由于我对这个网站很陌生,所以再过几个小时我都不会回答我自己的问题。无论如何,谢谢! 顺便说一句,您对“更好”的解决方案也是正确的。我只能说这是一个有效的概念证明,为了补充您的评论,最终目标是对此类信息进行更安全的“存储”,而不是将其暴露给命令行。向你致敬 Adam Liss。 在这种情况下,我会恭敬地建议您征求安全专家的意见。在 15 年以上的业务中,您会看到很多看似合理但非常脆弱的实施。 完全同意 - 此外,如果此 POC 成熟到可行状态,最终将由社区驱动。 在这样的短字符串上,您应该使用盐。否则,使用相同密钥的相同输入的加密输出将始终相同。因此允许攻击者替换字符串,或仅识别已知字符串何时出现。【参考方案2】:

解密

#!/bin/bash
clear 
# encrypt to file
echo "enter choice "
echo "1-dakr"
echo "2-gakr"
read choice 
case $choice in
1 )
echo "text?"
read text
echo "pass?"
read pass

echo -n '$text' | openssl enc -e -nosalt -out test.txt -aes-256-cbc -pass pass:$pass 
;;
2 ) 
# decrypt from file
echo "pass?"
read pass
echo "path?"
read path
openssl enc -d -nosalt -in $path -aes-256-cbc -pass pass:$pass
;;
* )
echo "shcd"
;;
esac

Decrypt 的输出是 $text 如何解决?

【讨论】:

你能解释一下具体是什么问题吗?如何解决什么?您希望该程序做什么? 我想加密字符串并保存在文本文件中编程做得很好但是当我选择解密时我选择文件路径(保存加密文本的位置)但输出是 $text 而不是解密字符串跨度> 您可以将此添加到您的问题中吗?这样其他人就可以准确地了解问题所在。 使用双引号代替单引号:echo -n "$text" | openssl ... 或完全不使用引号:echo $text | openssl ...

以上是关于OpenSSL 字符串解密问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用之前使用 mcrypt 加密的 OpenSSL 解密字符串?

c语言中的openssl aes解密

php7实现基于openssl的加密解密方法

解密用 PHP openssl_encrypt 加密的 C# 中的字符串

使用rust的openssl库加密/解密大文本

如何利用OpenSSL库进行RSA加密和解密