本文介绍了如何将AESCrypt中的IV与JAVA和RUBY相匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将加密ID和昵称放入数据库。
但是当我需要在ruby
中获取ID和昵称时会出现问题,因为ruby中的AESCrypt不起作用。

I put the Encrypted ID and Nickname to Database.but there is a problem when I need to get the ID and nickname in rubybecause AESCrypt in ruby doesn't work.

我认为问题是IV与ruby和java不一样

I think the problem is IV that isn't same with ruby and java

这里是我在java代码中使用的(实际上在android中)

here is I used in java code (actually in android)

public class AESCrypt {

private final Cipher cipher;
private final SecretKeySpec key;
private AlgorithmParameterSpec spec;




public AESCrypt(String password) throws Exception
{
    // hash password with SHA-256 and crop the output to 128-bit for key
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.update(password.getBytes("UTF-8"));
    byte[] keyBytes = new byte[16];
    System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);

    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    key = new SecretKeySpec(keyBytes, "AES");
    spec = getIV();
}

public AlgorithmParameterSpec getIV()
{
    byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
    IvParameterSpec ivParameterSpec;
    ivParameterSpec = new IvParameterSpec(iv);

    return ivParameterSpec;
}

public String encrypt(String plainText) throws Exception
{
    cipher.init(Cipher.ENCRYPT_MODE, key, spec);
    byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
    String encryptedText = new String(Base64.encode(encrypted, Base64.DEFAULT), "UTF-8");

    return encryptedText;
}

public String decrypt(String cryptedText) throws Exception
{
    cipher.init(Cipher.DECRYPT_MODE, key, spec);
    byte[] bytes = Base64.decode(cryptedText, Base64.DEFAULT);
    byte[] decrypted = cipher.doFinal(bytes);
    String decryptedText = new String(decrypted, "UTF-8");

    return decryptedText;
}

}

我需要解密ruby
中的数据所以我使用下面的代码

and I need to decrypt the data in rubyso i used the code below

require 'openssl'
require 'base64'

module AESCrypt

  def self.encrypt(message, password)
    Base64.encode64(self.encrypt_data(message.to_s.strip,
    self.key_digest(password), nil, "AES-256-CBC"))
  end

  def self.decrypt(message, password)
    base64_decoded = Base64.decode64(message.to_s.strip)
    self.decrypt_data(base64_decoded, self.key_digest(password), nil, "AES-256-CBC")
  end

  def self.key_digest(password)
    OpenSSL::Digest::SHA256.new(password).digest
  end


  def self.decrypt_data(encrypted_data, key, iv, cipher_type)
    aes = OpenSSL::Cipher::Cipher.new(cipher_type)
    aes.decrypt
    aes.key = key
    aes.iv = "0000000000000000"
    aes.update(encrypted_data) + aes.final
  end

  def self.encrypt_data(data, key, iv, cipher_type)
    aes = OpenSSL::Cipher::Cipher.new(cipher_type)
    aes.encrypt
    aes.key = key
    aes.iv = "0000000000000000"
    aes.update(data) + aes.final
  end
end

如何将红宝石中的IV与Java相匹配?
这是一个IV问题?

how to match IV in ruby to Java?and is this a IV problem?

推荐答案

此代码存在许多问题:


  1. 将初始化向量初始化为16字节 0 。不幸的是,这被推荐在互联网上的许多地方,但是它违背了IV 的目的 - 一个随机且不可预测的值来播种密码块链 。此值不需要保密(即您可以将其添加到密文并通过明确的渠道传输)但它必须随机唯一对于使用相同密钥加密的每个值。


    • 您不仅生成静态IV,而且在课程构建期间执行此操作,因此即使您要修改中的代码getIV()返回一个随机的IV,它对于这个类加密的所有值都是常量;再一次,打败了目的。

  1. You initialize the initialization vector to 16 bytes of 0. Unfortunately this is recommended many places on the internet but it defeats the purpose of an IV -- a random and unpredictable value to seed the Cipher Block Chain Mode of Operation. This value does not need to be kept secret (i.e. you can prepend it to the cipher text and transmit over clear channels) but it must be random and unique for every value encrypted with the same key.
    • Not only do you generate a static IV, you do it during class construction, so even if you were to modify the code in getIV() to return a random IV, it would be constant for all values encrypted by this class; again, defeating the purpose.

以下是示例代码(取自并针对此示例进行了修改)它使用您正在使用的相同KDF并加密和解密简单消息。注意注释行将生成随机IV并将其用于更安全的操作。有关Ruby中字节操作的更多信息(即(\0* 16).unpack('c *')。pack('s *'))请参阅。

Here is sample code (taken from an Apache NiFi test resource and modified for this example) which uses the same KDF you are using and encrypts and decrypts a simple message. Note the commented line which would generate a random IV and use it for a more secure operation. For more information on byte manipulation in Ruby (i.e. ("\0" * 16).unpack('c*').pack('s*')) see Byte manipulation in Ruby.

#!/usr/bin/env ruby

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require 'openssl'

def bin_to_hex(s)
  s.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join
end

plaintext = "This is a plaintext message."
puts "Plaintext: #{plaintext}"

cipher = OpenSSL::Cipher.new 'AES-128-CBC'
cipher.encrypt
# iv = cipher.random_iv
# This creates a string of 16 0x00 bytes
iv = ("\0" * 16)

key_len = cipher.key_len
digest = OpenSSL::Digest::SHA256.new
key = digest.digest(plaintext)[0..15]

puts ""

puts "  IV: #{bin_to_hex(iv)} #{iv.length}"
puts " Key: #{bin_to_hex(key)} #{key.length}"
cipher.key = key
cipher.iv = iv

# Now encrypt the data:

encrypted = cipher.update plaintext
encrypted << cipher.final
puts "Cipher text length: #{encrypted.length}"
puts "Cipher text: #{bin_to_hex(encrypted)}"

cipher.decrypt
cipher.iv = iv
cipher.key = key
decrypted = cipher.update encrypted
decrypted << cipher.final
puts "Plaintext length: #{decrypted.length}"
puts "Plaintext: #{decrypted}"

结果输出:

$ ./openssl_aes.rb
Plaintext: This is a plaintext message.

  IV: 00000000000000000000000000000000 16
 Key: c72943d27c3e5a276169c5998a779117 16
Cipher text length: 32
Cipher text: 4f6ab6c5a6c628693f77aa9e2c63b3c5366f433fcad9fbd623510c2ba517381f
Plaintext length: 28
Plaintext: This is a plaintext message.

现在可以将这些数据反馈到Java类中(注意Ruby输出是十六进制编码的,不是Base64)来验证。

You can now feed this data back into your Java class (note the Ruby output is hex-encoded, not Base64) to verify.

这篇关于如何将AESCrypt中的IV与JAVA和RUBY相匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 09:08
查看更多