【问题标题】:Decrypting Rijndael in Android在 Android 中解密 Rijndael
【发布时间】:2023-04-05 15:54:01
【问题描述】:

我基本上需要解密从使用 Rijndael 加密的服务器中检索到的密码,我以前从未使用过加密/解密,我完全迷路了。我在这个网络上的某个地方发现 Java 有一些不需要外部库来实现的方法,但我没有得到它。我唯一需要的是解密,因为无论如何我都不会写回服务器。

关于如何做或在哪里可以找到有关它的文档的任何想法?

我不知道这段代码是否来自答案here 是我正在寻找的,我不太了解它,正如我所说,我以前从未使用过这种东西:

byte[] sessionKey = null; //Where you get this from is beyond the scope of this post
byte[] iv = null ; //Ditto
byte[] plaintext = null; //Whatever you want to encrypt/decrypt
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//You can use ENCRYPT_MODE or DECRYPT_MODE
cipher.calling init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext);

提前致谢。

【问题讨论】:

  • 看起来它是正确的代码。你试过用它吗?我想它应该是cipher.init(Cipher.DECRYPT_MODE, ...,我不知道你从哪里获得会话密钥和初始化向量(iv),或者"AES/CBC/PKCS5Padding" 是否是正确的模式。但是如果你发现你所要做的就是把加密后的密码填入plaintext,最后在cyphertext中解密。
  • 我没有尝试主要是因为我不知道将找回的密码放在哪里,现在就像你说的那样尝试。谢谢。
  • @zapl 显然它无法解析 .calling 并且找不到 init() 方法。有什么想法吗?
  • 我猜.calling 部分是一个错误,它是cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv));
  • @zapl 你说得对,实际上我几分钟前自己就想出来了,遗憾的是我无法尝试解密是否有效,因为服务器目前表现得很愚蠢,需要先解决那个。还是谢谢。

标签: java android encryption rijndael


【解决方案1】:

这是一个简单的加密实用程序类,可能对您有所帮助。它基于 ferenc.hechler 在以下 url 上发布的代码: http://www.androidsnippets.com/encryptdecrypt-strings 我已经对其进行了一些更改以满足我的需要。

import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class SimpleCrypto {

    private static final int KEY_SIZE = 128;

    public static String encrypt(String seed, String cleartext) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
        final byte[] rawKey = getRawKey(seed.getBytes());
        final byte[] result = encrypt(rawKey, cleartext.getBytes());
        return bin2hex(result);
    }

    public static String decrypt(String seed, String encrypted) throws NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException {
        final byte[] rawKey = getRawKey(seed.getBytes());
        final byte[] enc = toByte(encrypted);
        final byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    public static String decrypt(String seed, byte[] encrypted) throws NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException {
        final byte[] rawKey = getRawKey(seed.getBytes());
        final byte[] result = decrypt(rawKey, encrypted);
        return new String(result);
    }

    private static byte[] getRawKey(byte[] seed) throws NoSuchAlgorithmException {
        final KeyGenerator kgen = KeyGenerator.getInstance("AES");
        final SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed(seed);
        kgen.init(KEY_SIZE, sr); // 192 and 256 bits may not be available
        final SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }

    public static byte[] encrypt(byte[] raw, byte[] clear) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        final SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        final Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        final byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    public static byte[] decrypt(byte[] raw, byte[] encrypted) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        final SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        final Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        final byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    public static String toHex(String txt) {
        return bin2hex(txt.getBytes());
    }

    public static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    public static byte[] toByte(String hexString) {
        final int len = hexString.length() / 2;
        final byte[] result = new byte[len];
        for (int i = 0; i < len; i++) {
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
        }
        return result;
    }

    public static byte[] getHash(String str) {
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        digest.reset();
        return digest.digest(str.getBytes());
    }

    static String bin2hex(byte[] data) {
        return String.format("%0" + (data.length * 2) + "X", new BigInteger(1, data));
    }
}

以下是您将如何使用它来解密某些内容:

    final String ssid = "MY_WIFI_SSID";
    final String encWifiKey = "myEncryptedWifiKeyString";

    String wifiKey = "";
    try {
        wifiKey = new String(SimpleCrypto.decrypt(SimpleCrypto.getHash(ssid), Base64.decode(encWifiKey, Base64.DEFAULT)));
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    }

【讨论】:

  • 没有尝试过,但我不明白的一件事是,在我看到的每一种方法中,结果似乎都是字节类型。解密后我不应该有一个字符串吗?我的意思是,用户输入的内容被捕获为字符串,所以...
  • 加密(或至少是分组密码)通常只对字节有效。所以 String 需要在加密前转换为字节,解密后要反转回来。通常这是通过使用特定的字符编码来执行的,例如 UTF-8。对于最常用的 UTF-8 编码,使用 new String(byte[], Charset.forName("UTF-8")) 完成此操作。
  • 不要使用这个例子!我已经多次遇到过这个例子,它确实做了所有可以做错的事情。 Akos Cz,不要发布你不懂的代码。
  • 就像我说的,它符合我的需要,它可能对原始海报有所帮助。您可以考虑提供一个您认为一切正确的示例:P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-06
相关资源
最近更新 更多