当前位置: 首页 > 知识库问答 >
问题:

用于AES/ECB/PKCS7Padding的自定义字符串填充,键大小为0到256位

农星华
2023-03-14

我最近遇到了一种情况,在这种情况下,我需要在iOS和Android之间使用预定义的字符串密钥进行256-AES跨平台加密/解密,比如预定义密钥

AES的实现是用这段代码在iOS上完成的,我需要做的就是在Android上更改代码,这样我就可以进行“跨平台”加密/解密。

注意:我知道iOS上的AES代码存在严重的安全/内存问题,但目前我并不担心:-)

我可以单独在Android和iOS上进行加密/解密。然而,这里的两个AES实现似乎有一个微不足道的区别,这阻止了我进行“跨平台”加密/解密。例如,我把Android加密的字符串iOS,它不能返回预期的结果(在这种情况下,它返回null)。

问题:

在iOS和Android平台上,我确信算法是AES/ECB/PKCS7Padd,具有128-Rijndael算法用于AES实现。

两个平台都应该使用256位大小的密钥。通过对iOS AES代码的深入研究,我发现它实际上使用了来将键填充到256位。

以下是iOS上与零填充相关的代码片段:

// 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

下面是代码中的AES参数(它使用Rijndael-128算法,256位密钥大小,初始向量为NULL):

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES256,
                                     NULL /* initialization vector (optional) */,
                                     [self bytes], dataLength, /* input */
                                     buffer, bufferSize, /* output */
                                     &numBytesEncrypted);

但是在Android系统上,我不知道如何做类似的事情,所以有人能为我指出正确的方法吗?

在Android平台上,我使用下面的代码来执行AES:

private static final String AES_SECRET = "PreDefinedKey";

/**
 * Method for AES encryption
 * @param raw
 * @param plain
 * @return
 * @throws Exception
 */
private static byte[] encrypt(byte[] raw, byte[] plain) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES/ECB/PKCS7Padding");
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(plain);
    return encrypted;
}



/**
 * AES decryption
 * @param encryptMsg
 * @return
 * @throws Exception
 */
public static String AESDecrypt(String encryptMsg)
        throws Exception {          
    byte[] rawKey = getRawKey(AES_SECRET.getBytes());
    //byte[] enc = toByte(encryptMsg);
    byte[] enc = Base64.decode(encryptMsg, 0);
    byte[] result = decrypt(rawKey, enc);
    return new String(result);

}

/**
 * Method for AES decryption
 * @param raw
 * @param encrypted
 * @return
 * @throws Exception
 */
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
    SecretKeySpec keySpec = new SecretKeySpec(raw, "AES/ECB/PKCS7Padding");
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
    cipher.init(Cipher.DECRYPT_MODE, keySpec);
    byte[] decrypted = cipher.doFinal(encrypted);
    return decrypted;

}

public static byte[] getRawKey(byte[] seed) throws Exception {

    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed(seed);
    //Init for 256bit AES key
    kgen.init(256);
    SecretKey secret = kgen.generateKey();
    //Get secret raw key
    byte[] raw = secret.getEncoded();

    return seed;

}

在getRawKey()方法中,它使用SHA1PRNG生成随机填充,使AES密钥成为256位大小,这与iOS实现不同(它使用零将密钥填充为256位)。

那么,我该如何更改这个方法,以便使用预定义的字符串键,该键由0填充到256位?

如果你需要更多信息,请告诉我。谢谢!

共有1个答案

慎建本
2023-03-14

找到想出这个零填充方案的人,让他们被解雇。然后对应用程序进行审查。

至于你的问题,简单地创建一个长度为32的字节数组,并将密钥字节复制到开头,用它初始化秘密密钥规范KeyGenerator将生成一个随机密钥,整个“固定种子”的想法是有缺陷的,在最新的Android版本上不起作用。这里有一些代码:

// zeros by default
byte[] rawKey = new byte[32];
// if you don't specify the encoding you might get weird results
byte[] keyBytes = AES_SECRET.getBytes("ASCII");
System.arraycopy(keyBytes, 0, rawKey, 0, keyBytes.length);
SecretKey key = new SecretKeySpec(rawKey, "AES");
Cipher cipher = ...
// rest of your decryption code
 类似资料:
  • 问题内容: 我目前正在使用 256个字节的* 密钥大小来用Java加密文件,但是在搜索时我在stackexchange PKCS#5-PKCS#7填充上发现了它,并提到: * PKCS#5填充是8个字节块大小的PKCS#7填充的子集 所以我想知道 相对于上述配置,性能会更好吗? 正如我们所提到的,我们如何在Java中配置块大小 PKCS#7填充适用于从1到255字节的任何块大小。 我的示例代码是

  • rank ▲ ✰ vote url 77 340 83 533 url 给字符串填充0 有什么方法可以给字符串左边填充0,这样就可以有一个特定长度. 字符串: >>> n = '4' >>> print n.zfill(3) >>> '004' 对于数字: >>> n = 4 >>> print '%03d' % n >>> 004 >>> print format(4, '03') # pyt

  • 字符串像这里一样用php加密。可以用这个用参数解密:Rijndael-256,ECB,Base64。但是我的ActionScript代码无法解密它: 更新: “它无法解密”意味着我弄错了纯文本。 在php中,明文首先由aes-256-ecb加密。然后由Base64编码。在ActionScript中,这些步骤以相反的顺序进行。 UPD2: 编码-解码测试: 在 停止后的输出是: 更新3: 它适用于P

  • 如果公司营业额大于50亿卢比,GST理事会已批准将企业对企业(B2B)发票的“电子发票”或“电子发票”实施到GST系统。参考商品及服务税门户 API :einv-apisandbox.nic.in/index.html 我必须使用APP密钥对加密的SEK进行解密,并使用解密的SEK对json数据进行编码,以便发布Einvoice Generation,我找到了java和C#的示例代码,我已经用PH

  • 我目前使用< code > AES/CBC/PKCS 5 Padding 对Java文件进行加密,密钥大小为256字节,但在搜索时,我在stack exchange PKCS # 5-PKCS # 7 Padding上发现了它, PKCS#5填充是8字节块大小的PKCS#7填充的子集 所以我想知道 > < li >对于上述配置,< code > AES/CBC/pkcs 7 padding 的性能

  • 我对我当前尝试访问的API的加密有以下要求: < li>PKCS7填充方法 < li>CBC加密模式 < li>AES密钥大小256,块大小128 每次我提交带有加密的API时,API似乎都有问题(不幸的是没有产生错误)。 问题: PKCS7填充方法到底是什么,可以用php实现? AES 256很好,但是块大小到底是什么意思? IV到底是做什么的?