- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试解密在我的rails项目中已加密的字符串。这就是我加密数据的方式:
def encrypt_text(text_To_encrypt)
# 0. generate the key using command openssl rand -hex 16 on linux machines
# 1. Read the secret from config
# 2. Read the salt from config
# 3. Encrypt the data
# 4. return the encypted data
# Ref: http://www.monkeyandcrow.com/blog/reading_rails_how_does_message_encryptor_work/
secret = Rails.configuration.miscconfig['encryption_key']
salt = Rails.configuration.miscconfig['encryption_salt']
key = ActiveSupport::KeyGenerator.new(secret).generate_key(salt, 32)
crypt = ActiveSupport::MessageEncryptor.new(key)
encrypted_data = crypt.encrypt_and_sign(text_To_encrypt)
encrypted_data
end
openssl enc -d -aes-256-cbc -salt -in encrypted.txt -out decrypted.txt -d -pass pass:<the key given in rails> -a
最佳答案
除非您了解并处理了两个系统如何进行加密的许多复杂细节,否则尝试对在不同系统中加密的数据进行解密将无法进行。尽管Rails和openssl
命令行工具都在底层使用OpenSSL库进行加密操作,但是它们都以自己独特的方式使用了OpenSSL库,这些方法不能直接进行互操作。
如果您靠近两个系统,将会看到例如:
Rails消息加密器不仅对消息进行加密,还对其进行签名
Rails加密器使用Marshal
序列化输入数据openssl enc
工具期望加密的数据以具有Salted__<salt>
标头的独特文件格式显示(这就是为什么您从openssl
收到错误的幻数消息的原因)openssl
工具必须正确配置为使用与Rails加密器和密钥生成器相同的密码,因为openssl
的默认设置与Rails的默认设置不同
自Rails 5.2起,默认密码配置发生了重大变化。
有了这个一般信息,我们可以看一个实际的例子。它已在Rails 4.2中进行了测试,但在Rails 5.1之前也应该能够正常工作。
Rails加密消息的剖析
让我从您介绍的代码稍作修改开始。唯一的更改是将password
和salt
预设为静态值并打印很多调试信息:
def encrypt_text(text_to_encrypt)
password = "password" # the password to derive the key
salt = "saltsalt" # salt must be 8 bytes
key = ActiveSupport::KeyGenerator.new(password).generate_key(salt, 32)
puts "salt (hexa) = #{salt.unpack('H*').first}" # print the saltin HEX
puts "key (hexa) = #{key.unpack('H*').first}" # print the generated key in HEX
crypt = ActiveSupport::MessageEncryptor.new(key)
output = crypt.encrypt_and_sign(text_to_encrypt)
puts "output (base64) = #{output}"
output
end
encrypt_text("secret text")
salt (hexa) = 73616c7473616c74
key (hexa) = 196827b250431e911310f5dbc82d395782837b7ae56230dce24e497cf07b6518
output (base64) = SGRTUXYxRys1N1haVWNpVWxxWTdCMHlyMk15SnQ0dWFBOCt3Z0djWVdBZz0tLTkrd1hBNWJMVm9HcnptZ3loOG1mNHc9PQ==--80d091e8799776113b2c0efd1bf75b344bf39994
encrypt_and_sign
方法的输出)是由
--
分隔的两部分的组合(请参见
source):
> Base64.strict_decode64("SGRTUXYxRys1N1haVWNpVWxxWTdCMHlyMk15SnQ0dWFBOCt3Z0djWVdBZz0tLTkrd1hBNWJMVm9HcnptZ3loOG1mNHc9PQ==")
=> "HdSQv1G+57XZUciUlqY7B0yr2MyJt4uaA8+wgGcYWAg=--9+wXA5bLVoGrzmgyh8mf4w=="
--
分隔的Base64编码部分组成(请参见
source):
aes-256-cbc
密码(请注意,自Rails 5.2起,此密码已更改)。该密码需要一个初始化向量,该初始化向量由Rails随机生成,并且必须存在于加密输出中,以便我们可以将其与密钥一起使用来解密消息。
Marshal
序列化器(
source)加密数据的序列化版本。如果我们使用openssl解密这种序列化的值,我们仍然会得到原始纯文本数据的乱码(序列化)版本。这就是为什么在Rails中加密数据时更禁用禁用序列化的原因。这可以通过将参数传递给加密方法来完成:
# crypt = ActiveSupport::MessageEncryptor.new(key)
crypt = ActiveSupport::MessageEncryptor.new(key, serializer: ActiveSupport::MessageEncryptor::NullSerializer)
salt (hexa) = 73616c7473616c74
key (hexa) = 196827b250431e911310f5dbc82d395782837b7ae56230dce24e497cf07b6518
output (base64) = SUlIWFBjSXRUc0JodEMzLzhXckJzUT09LS1oZGtPV1ZRc2I5Wi8zOG01dFNOdVdBPT0=--58bbaf983fd20459062df8b6c59eb470311cbca9
pbkdf2_hmac_sha1
算法与
2**16 = 65536
迭代一起使用,以从密码/机密中获取密钥。
openssl
加密邮件的剖析
openssl
侧进行类似的调查,以了解其解密过程的详细信息。首先,如果使用
openssl enc
工具加密任何内容,您将发现输出具有不同的格式:
Salted__<salt><encrypted_message>
Salted__
魔术字符串开头,然后是盐(十六进制形式),最后是加密数据。为了能够使用此工具解密任何数据,我们必须将加密的数据转换为相同的格式。
openssl
工具默认情况下使用
EVP_BytesToKey
(请参见
source)派生密钥,但可以使用
pbkdf2_hmac_sha1
和
-pbkdf2
选项将其配置为使用
-md sha1
算法。可以使用
-iter
选项设置迭代次数。
openssl
中解密Rails加密的消息
openssl
中的Rails加密消息进行解密。
> Base64.strict_decode64("SUlIWFBjSXRUc0JodEMzLzhXckJzUT09LS1oZGtPV1ZRc2I5Wi8zOG01dFNOdVdBPT0=")
=> "IIHXPcItTsBhtC3/8WrBsQ==--hdkOWVQsb9Z/38m5tSNuWA=="
openssl
所需的形式:
> Base64.strict_decode64("hdkOWVQsb9Z/38m5tSNuWA==").unpack("H*").first
=> "85d90e59542c6fd67fdfc9b9b5236e58" # the initialization vector in hex form
openssl
可以识别的格式,即在其前面加上魔术字符串和salt并再次对其进行Base64编码:
> Base64.strict_encode64("Salted__" + "saltsalt" + Base64.strict_decode64("IIHXPcItTsBhtC3/8WrBsQ=="))
=> "U2FsdGVkX19zYWx0c2FsdCCB1z3CLU7AYbQt//FqwbE=" # encrypted data suitable for openssl
openssl
命令来解密数据:
$ echo "U2FsdGVkX19zYWx0c2FsdCCB1z3CLU7AYbQt//FqwbE=" |
> openssl enc -aes-256-cbc -d -iv 85d90e59542c6fd67fdfc9b9b5236e58 \
> -pass pass:password -pbkdf2 -iter 65536 -md sha1 -a
secret text
openssl
参数如下:
-aes-256-cbc
设置与Rails用于加密的相同密码
-d
代表解密
-iv
以十六进制字符串形式传递初始化向量
-pass pass:password
将用于导出加密密钥的密码设置为“ password”
-pbkdf2
和
-md sha1
设置与Rails(
pbkdf2_hmac_sha1
)相同的密钥派生算法
-iter 65536
设置与Rails中相同的密钥派生迭代次数
-a
允许使用Base64编码的加密数据-无需处理文件中的原始字节
openssl
从STDIN读取数据,因此我们仅使用echo将加密数据(以正确格式)传递给
openssl
。
openssl
解密时遇到任何问题,将
-P
参数添加到命令行会很有用,该命令行会输出有关密码/密钥参数的调试信息:
$ echo ... | openssl ... -P
salt=73616C7473616C74
key=196827B250431E911310F5DBC82D395782837B7AE56230DCE24E497CF07B6518
iv =85D90E59542C6FD67FDFC9B9B5236E58
salt
,
key
和
iv
值必须与上面打印的
encrypt_text
方法中原始代码打印的调试值相对应。如果它们不同,则说明您做错了什么...
关于ruby-on-rails - 尝试使用已在rails中加密的openssl/golang解密字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55352313/
说真的,你怎么能在不发疯的情况下处理所有这些异常呢?我是不是读了太多关于异常处理的文章或什么?我尝试重构了几次,但每次似乎都以更糟糕的结果告终。也许我应该承认确实会发生异常(exception)情况,
背景 两者 try/rescue和 try/catch是 Elixir 中的错误处理技术。根据 corresponding chapter在介绍指南中。 Errors can be rescued u
每当我尝试在 Raspberry PI 上运行此 python 脚本时,我都会遇到问题: import socket import sys # Create a TCP/IP socket sock
我想知道一些关于 PHP 的 try , catch声明。 让我们考虑以下示例。 abstract class ExceptionA extends Exception {} class Except
我的 laravel v5.4 项目中有两个模型,user 和 admin。 在 config/auth.php 中,我向守卫和提供者添加了管理员,如下所示: 'guards' => [ 'w
try: r = requests.get(url, params={'s': thing}) except requests.ConnectionError, e: print e
我有以下代码。 但是,它并不能捕获所有错误,而我仍然会收到“throw er;//未处理的'错误'事件”。 为什么是这样? app.post('/api/properties/zip/:zip/bed
问题与细节 我正在使用自定义错误处理,遇到的错误之一是“路径中的非法字符”。我有一个自定义函数,旨在通过路径字符串查找此类非法字符,并在找到它们时引发自定义错误。但是我发现,取决于非法字符,Test-
This question already has answers here: How do I catch a numpy warning like it's an exception (not j
我正在使用其他人的代码,但我不熟悉try/catch,因此我举了一个类似的小例子。在第11行上,如果我写了error(''),似乎没有发现错误并增加了索引j。但是,编写error(' ')或error
我在我的一个程序中遇到了这个问题,在这种情况下,尝试/异常(exception)的错误使程序变得更好,以防用户意外输入了他们不应该输入的内容。它仍然给我错误,我为为什么感到困惑。如果对我的问题确实很重
我在尝试TRY ... CATCH块时遇到问题。有人可以解释为什么以下代码无法执行我的sp吗? DECLARE @Result int SET @Result = 0 BEGIN TRY SE
我有一个相当大的 powershell 脚本,其中包含许多(20 多个)执行各种操作的函数。 现在所有代码实际上都没有任何错误处理或重试功能。如果某个特定的任务/功能失败,它就会失败并继续。 我想改进
为什么我尝试时需要导入 inputmismatchException catch(InputMismatchException e){ System.out.println("
我对此感到困惑 - 我为辅助方法编写了一个 try/catch 。它的目的是捕获任何无效输入(任何不是“男性”或“女性”的内容(没有特定情况)。如果输入无效,它将通知用户,然后让他们重试。如果有效,则
我有时会发现自己处于如下场景。尽可能简单地陈述问题 “有时我会创建一段代码,Java 让我将其包含在 try/catch 语句中。我没有使用 catch,所以我将其留空。为什么这是错误的?” boo
我有点困惑为什么当我不使用 Try block 时会出现 Try block 错误。 我在代码块底部附近收到错误通知。如果我不使用 try/catch,有人可以向我解释为什么会发生这种情况吗? 它是否
我已经盯着我的电脑两个小时了,我不知道我做错了什么。谁能帮助我看到光明? package blackjack; import java.util.Random; import java.util.Sc
我想将方法保存在 Enum 中,但 Class.getDeclaredMethod 抛出 NoSuchMethodException,那么我该如何处理呢?我的代码: public enum Car
这个问题已经有答案了: Executing multi-line statements in the one-line command-line (18 个回答) 已关闭 3 年前。 如何使用try.
我是一名优秀的程序员,十分优秀!