在Java中解密在3DES中加密的Python数据 [英] Decrypting data in Python that was encrypted in 3DES by Java

查看:248
本文介绍了在Java中解密在3DES中加密的Python数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用PyCrypto解密数据。数据使用javax.crypto包编码为Java。加密是Triple DES(简称 DESede )。据我所知,默认设置用于所有内容。但是,当我在Python中解密数据时,数据总是存在问题。



这是加密/解密的Java代码:

  import sun.misc.BASE64Decoder; 
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.security.spec.KeySpec;

public final class Encrypter
{
public static final String DESEDE_ENCRYPTION =DESede;

私钥KeySpec keySpec;
private SecretKeyFactory keyFactory;
私密密码;

private static final String UNICODE_FORMAT =UTF8;

public Encrypter(String encryptionKey)
throws异常
{
byte [] keyAsBytes = encryptionKey.getBytes(UNICODE_FORMAT);
keySpec = new DESedeKeySpec(keyAsBytes);
keyFactory = SecretKeyFactory.getInstance(DESEDE_ENCRYPTION);
cipher = Cipher.getInstance(DESEDE_ENCRYPTION);
}

public String encryptString(String unencryptedString)
{
SecretKey key = keyFactory.generateSecret(keySpec);
cipher.init(Cipher.ENCRYPT_MODE,key);
byte [] cleartext = unencryptedString.getBytes(UNICODE_FORMAT);
byte [] ciphertext = cipher.doFinal(cleartext);

BASE64Encoder base64encoder = new BASE64Encoder();
return base64encoder.encode(ciphertext);
}

public String decryptString(String encryptedString)
{
SecretKey key = keyFactory.generateSecret(keySpec);
cipher.init(Cipher.DECRYPT_MODE,key);
BASE64Decoder base64decoder = new BASE64Decoder();
byte [] ciphertext = base64decoder.decodeBuffer(encryptedString);
byte [] cleartext = cipher.doFinal(ciphertext);

return bytesToString(cleartext);
}

private static String bytesToString(byte [] bytes)
{
StringBuilder sb = new StringBuilder();
(byte aByte:bytes)
{
sb.append((char)aByte);
}
return sb.toString();
}
}

但是当我使用base64编码字符串之一这是由这段代码产生的,我无法解码。以下是我尝试过的一些python代码的示例:

 从Crypto.Cipher import DES3 
import array

key =<键的值,作为十六进制字符串>
encryptedvalue =<加密的值,字符串>
keyarray = array.array('B',key.decode(hex))
des = DES3.new(keyarray)
value = des.decrypt(encryptedvalue.decode base64'))

value.decode('utf-8')#​​给我一个错误

我收到的错误已经沿着

  UnicodeDecodeError:'utf8'codec可以' t解码字节0xa7在位置6:无效的起始字节

这意味着,在某个地方,我避风港没有得到正确的设置。我已经在这个工作了几个小时,甚至去试图查看 SunJCE源代码,其中实现DESede ,以查看它们使用的默认值,但无效。我将使用它作为自动运行的脚本的一部分,所以我真的不用使用Java来进行我的解密。有没有人知道我需要做什么来正确解密我的数据?

解决方案

所有我必须做的,更改此行

  keyarray = array.array('B',key.decode(hex))

到:

  keyarray = array.array('B',key.encode(utf-8))

这符合java编码密钥的方式,允许我拥有正确的加密密钥。






如果你我来这里希望从这个问题中学到一些东西,这里有一些一般的建议:


  1. 仔细检查你的假设:关键字符串是十六进制字符串,所以我假设它被这样使用。

  2. 确保你知道你的假设是什么:我没有意识地考虑我如何假设关键被使用。这通常在编程和生活中都是一个非常频繁的问题。

  3. 检查所有的方式(特别是当您有 Oracle 时):查看字节数组中的值是什么导致我意识到我的问题。


I'm trying to decrypt data using PyCrypto. The data was encoded in Java with the javax.crypto package. The encryption is Triple DES (referred to as "DESede" in Java). As far as I can tell, default settings are used for everything. However, when I go to decrypt the data in Python there is always a problem with the data.

Here's the Java code that does encrypting/decrypting:

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import java.security.spec.KeySpec;

public final class Encrypter
{
    public static final String DESEDE_ENCRYPTION = "DESede";

    private KeySpec keySpec;
    private SecretKeyFactory keyFactory;
    private Cipher cipher;

    private static final String UNICODE_FORMAT = "UTF8";

    public Encrypter(String encryptionKey)
        throws Exception
    {
        byte[] keyAsBytes = encryptionKey.getBytes(UNICODE_FORMAT);
        keySpec = new DESedeKeySpec(keyAsBytes);
        keyFactory = SecretKeyFactory.getInstance(DESEDE_ENCRYPTION);
        cipher = Cipher.getInstance(DESEDE_ENCRYPTION);
    }

    public String encryptString(String unencryptedString)
    {
        SecretKey key = keyFactory.generateSecret(keySpec);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] cleartext = unencryptedString.getBytes(UNICODE_FORMAT);
        byte[] ciphertext = cipher.doFinal(cleartext);

        BASE64Encoder base64encoder = new BASE64Encoder();
        return base64encoder.encode(ciphertext);
    }

    public String decryptString(String encryptedString)
    {
        SecretKey key = keyFactory.generateSecret(keySpec);
        cipher.init(Cipher.DECRYPT_MODE, key);
        BASE64Decoder base64decoder = new BASE64Decoder();
        byte[] ciphertext = base64decoder.decodeBuffer(encryptedString);
        byte[] cleartext = cipher.doFinal(ciphertext);

        return bytesToString(cleartext);
    }

    private static String bytesToString(byte[] bytes)
    {
        StringBuilder sb = new StringBuilder();
        for (byte aByte : bytes)
        {
            sb.append((char) aByte);
        }
        return sb.toString();
    }
}

But when I take one of the base64-encoded strings that was produced by this code, I can't decode it. Here's an example of some of the python code I've tried:

from Crypto.Cipher import DES3
import array

key = <value of the key, as a hex string>
encryptedvalue = <the value that's encrypted, as a string>
keyarray = array.array('B', key.decode("hex"))
des = DES3.new(keyarray)
value = des.decrypt(encryptedvalue.decode('base64'))

value.decode('utf-8') # Gives me an error

The errors I've gotten have looked along the lines of

UnicodeDecodeError: 'utf8' codec can't decode byte 0xa7 in position 6: invalid start byte

Which means that somewhere along the way, I haven't gotten something set up correctly. I've been working on this for a few hours, even going so far as trying to look into the SunJCE source code, which implements DESede, to see what defaults they use, but to no avail. I'm going to be using this as part of a script that runs automatically, so I'd really rather not have to use Java to do my decryption. Does anyone know what I need to do to decrypt my data correctly?

解决方案

All I had to do to make it work was to change this line

keyarray = array.array('B', key.decode("hex"))

to this:

keyarray = array.array('B', key.encode("utf-8"))

This matches the way that java was encoding the key, allowing me to have the correct encryption key.


If you've come here hoping to learn something from this question, here's some general advice:

  1. Double-check your assumptions: The key string was a hex string, so I assumed it was being used as such.
  2. Make sure you know what your assumptions are: I didn't consciously think about how I was making an assumption about how the key was used. This tends to be a very frequent problem in both programming and life in general.
  3. Check all the values along the way (especially when you have an Oracle): Looking at the values in the byte arrays was what led me to realizing my problem.

这篇关于在Java中解密在3DES中加密的Python数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆