如何使用SecretKeySpec加密ruby中的数据?

我正在尝试使用Cipher和AES算法加密ruby中的字符串。 我有用Java编写的示例。 我从这个例子中获得了帮助,并用Java编写了代码,但是无法获得与JAVA相同的输出。

以下是用java编写的代码

import java.util.Base64; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.Key; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import java.util.Arrays; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class HelloWorld { public static final String PHONENUMBER_PARAM = "phoneNumber"; public static final String PIN_PARAM ="pin"; public static final String MERCHANTID_PARAM = "merchantId"; public static void main(String args[]) throws Exception { String phoneNumber ="+917738995286"; String pin ="5577"; String merchantId ="527425858"; String encodedKey ="vPDkdTDrcygLPROzd1829A=="; String payLoad = PHONENUMBER_PARAM + "=" + URLEncoder.encode(phoneNumber, "UTF-8")+ "&" + PIN_PARAM + "=" + URLEncoder.encode(pin, "UTF-8") ; byte[] decodedKey = Base64.getDecoder().decode(encodedKey.getBytes()); Key encryptionKey = new SecretKeySpec(decodedKey, "AES"); byte[] utf8Bytes = payLoad.getBytes("utf-8"); byte[] encryptedBody = encrypt(encryptionKey, utf8Bytes); String encryptedData = new String(Base64.getEncoder().encode(encryptedBody)); System.out.println("encryptedData:" + encryptedData); } private static byte[] encrypt(Key encryptionKey, byte[] data) throws Exception { Cipher c = Cipher.getInstance("AES"); c.init(1, encryptionKey); return c.doFinal(data); } } 

此代码的输出是

的EncryptedData:lE40HlECbxU / mWRivF / + + Szm3PprMoLW + Y7x911GczunakbG8l A2JVEEP8gTw6xy

我试着在ruby中编写相同的代码。 Ruby代码是:

 payLoad = "phoneNumber=%2B917738995286&pin=5577" encodedKey = "vPDkdTDrcygLPROzd1829A==" decodedKey = Base64.decode64(encodedKey) dKey = decodedKey.each_byte.map { |b| b.to_s(16) }.join cipher = OpenSSL::Cipher.new('aes128').encrypt encryptionKey = cipher.update(dKey) encryptionKey<< cipher.final utf8Bytes = payLoad.bytes uKey = utf8Bytes.map { |b| b.to_s(16) }.join scipher = OpenSSL::Cipher.new('aes128').encrypt scipher.key = encryptionKey encryptedBody = scipher.update(uKey) encryptedBody<< scipher.final encryptedData = Base64.encode64(encryptedBody) 

此代码的输出是

CqFmCKJ004PsoXi2tDCTBmx7 / iTHVyDsFH9y8NWNrEP3k3bOQp7h8uyl / A7Z \ nYi9ZmcXSspo6FCyCo6fJIwPohg == \ n

不知道错误在哪里。 我已经工作了2天但没有得到任何答案。 任何帮助都会很棒。 提前致谢。

以下版本输出与Java代码相同的结果:

 # crypt.rb require 'base64' require 'openssl' payLoad = "phoneNumber=%2B917738995286&pin=5577" encodedKey = "vPDkdTDrcygLPROzd1829A==" decodedKey = Base64.decode64(encodedKey) scipher = OpenSSL::Cipher.new('aes-128-ecb').encrypt scipher.key = decodedKey encryptedBody = scipher.update(payLoad) encryptedBody << scipher.final encryptedData = Base64.encode64(encryptedBody) puts encryptedData $ ruby crypt.rb # => lE40HlECbxU/mWRivF/+Szm3PprMoLW+Y7x911GczunakbG8l+A2JVEEP8gT # w6xy 

与ruby脚本版本的显着差异:

  • 必须指定密码模式 。 问题是Java 默认为ECB模式,而ruby默认为CBC模式。 顺便说一句,ECB模式今天被认为不太安全, 你实际上不应该使用它

  • 在ruby中,您尝试重新加密Base64解码版本的加密密钥,这是您在Java版本中没有做到的。

  • 在ruby中,不需要进行字符串到字节的转换,您可以立即加密字符串。

因此,虽然现在两个脚本输出相同的加密数据,但我会强烈考虑更改AES操作模式,以实际保持安全。