【问题标题】:PKCS7 Padding in JavaCardJavaCard 中的 PKCS7 填充
【发布时间】:2016-02-05 11:57:01
【问题描述】:

我正在尝试在 JavaCard 环境中实现我自己的 PKCS7 填充方案,以防智能卡不支持 PKCS5 或 7 填充方案。

如果使用对称密码的不同块大小,我希望 PKCS 填充方案的块大小灵活。 length 表示消息输入长度,blocksize 表示密码块的大小。

我的算法将检查 PKCS7 填充中的两种情况,即所有字节是否都是相同的字节(例如 0A, 0A, 0A .. 0A, 0A, 0A),这意味着不涉及填充,并将返回值 0

第二种情况是检查是否有填充(例如0A, 0B, 0C, 05, 05, 05, 05, 05)。

我能够成功检查所有场景,但是在复制数据以输出结果时,它似乎无法正确复制。

似乎在调用arrayCopyRepackNonAtomic() 之前填充的arrayFillGenericNonAtomic() 数据仍停留在输出字节数组中,并且执行arrayCopyRepackNonAtomic() 并未正确复制数据。

我使用的输出字节数组格式是数组中的第一个元素携带已处理输出数据量的指示符(以字节表示)(例如,output[outputOffset] = (byte) 0x10 表示之后的 16 个数据元素已处理)。输出字节数组中第一个元素之后的后续数据元素包含处理后的数据。

问题的一个例子是我正在尝试 PKCS7 解码 A0, B0, C0, D0, E0, 04, 04, 04, 04,结果应该是 05, A0, B0, C0, D0, E0(其中 05 表示处理了以下 5 个字节)但我得到的是 05, 04, 04, 04, 04 ..

如何解决arrayCopyRepackNonAtomic() 无法按预期工作的问题?

我正在实际的 JavaCard 2.2.2 和 JavaCard 3.0.4 兼容智能卡上测试代码,该智能卡处于 OP_READY 模式。

public static void process(byte[] input, short offset, short length,
        short blockSize, byte[] output, short outputOffset, short mode) {
    if (mode == MODE_DECODE) {
        // Data length must be >= blocksize and have to have be a modulus of 0 size.
        if ((length >= blockSize) && ((length % blockSize) == 0)) {
            output[outputOffset] = (byte) length;
            ArrayLogic.arrayFillGenericNonAtomic(output, (short) (outputOffset + 1), (short) (length - 1), output, outputOffset);
            if (ArrayLogic.arrayCompareGeneric(input, offset, output, outputOffset, length) == 0x00) {
                // If all bytes are the same, return 0.
                output[outputOffset] = (byte) 0x00;
            } else {
                // Bytes are not all the same, check if the last segment of bytes are padded.
                if (ArrayLogic.arrayCompareGeneric(input, offset, output, outputOffset, (short) (input[(short) (offset + length - 1)] & 0xFF)) == 0x00) {
                    // Padded bytes are found.
                    output[outputOffset] = (byte) (length - input[(short) (offset + length - 1)]);
                    // Unable to copy correctly to output
                    ArrayLogic.arrayCopyRepackNonAtomic(input, offset, (short) (output[outputOffset] & 0xFF), output, (short) (outputOffset + 1)); 
                } else {
                    output[outputOffset] = (byte) length;
                    // Unable to copy correctly to output
                    ArrayLogic.arrayCopyRepackNonAtomic(input, offset, length, output, (short) (outputOffset + 1));
                }
            }
        }
    }
}

问题已经解决,问题是错误的变量偏移量以及导致问题的字节到短转换的处理。

下面是一个工作版本,经过一些测试,似乎可以为将来有兴趣使用它的人进行填充。

public static void process(byte[] input, short offset, short length,
        short blockSize, byte[] workBuff, short buffOffset, byte[] output,
        short outputOffset, short mode) {
    if (mode == MODE_DECODE) {
        // Data length must be >= blocksize and have to have be a modulus of 0 size.
        if ((length >= blockSize) && ((length % blockSize) == 0)) {
            workBuff[buffOffset] = (byte) input[(short) (length + offset - 1)];
            ArrayLogic.arrayFillGenericNonAtomic(workBuff, buffOffset, length, workBuff, buffOffset);
            if (ArrayLogic.arrayCompareGeneric(input, offset, workBuff, buffOffset, length) == 0x00) {
                // If all bytes are the same, return 0.
                output[outputOffset] = (byte) 0x00;
            } else {
                output[outputOffset] = (byte) (offset + length - (workBuff[buffOffset] & 0xFF));
                output[(short) (outputOffset + 1)] = workBuff[buffOffset];
                // Bytes are not all the same, check if the last segment of bytes are padded.
                if (ArrayLogic.arrayCompareGeneric(input, (short) (offset + length - (workBuff[buffOffset] & 0xFF)), workBuff, buffOffset, (short) (workBuff[buffOffset] & 0xFF)) == 0x00) {
                    // Padded bytes are found.
                    output[outputOffset] = (byte) (length - input[(short) (offset + length - 1)]);
                    ArrayLogic.arrayCopyRepackNonAtomic(input, offset, (short) output[outputOffset], output, (short) (outputOffset + 1));
                } else {
                    // Padded bytes are not found.
                    output[outputOffset] = (byte) length;
                    ArrayLogic.arrayCopyRepackNonAtomic(input, offset, length, output, (short) (outputOffset + 1));
                }
            }
        }
    }
}

【问题讨论】:

  • 输出05, 04, 04, 04, 04 ..的确切输入值(lengthblockSize)是什么?
  • 一般建议:不要将ArrayLogic“重新打包”方法用于您可以通过javacard.framework.Util 轻松处理的任务。 ArrayLogic 方法比 Util 方法强大得多,但没有理由将它们用于这些非常简单的目的 - Util 方法更具可读性并且具有更好的性能。
  • 我刚刚注意到,当我调用这些方法时,输入和输出字节数组是相同的,所以它会被混淆和覆盖,所以现在我添加了一个额外的字节数组作为中间缓冲区,这似乎解决了一部分的问题。原始邮政编码尚未更新,因为@Paul Bastian 的回答似乎很有趣,我现在正在查看。

标签: padding smartcard javacard pkcs#7


【解决方案1】:

嗯,我不认为这是唯一的错误,但你的分支肯定是错误的:

// Bytes are not all the same, check if the last segment of bytes are padded.
if (ArrayLogic.arrayCompareGeneric(input, offset, output, outputOffset, (short) (input[(short) (offset + length - 1)] & 0xFF)) == 0x00) {

您正在比较正确的长度,但错误的偏移量。

我不明白 else-case 在你的方法中应该做什么。如果填充错误应该抛出错误吗?

【讨论】:

  • else case 处理您有 0A, 0B, 0C, 0D, 08, 08, 08, 07, 08, 08, 08, 08 的情况。最后 8 个字节看起来几乎像 08 填充但由于 07 它不被视为填充,因此 else 子句捕获了它并声明它不是正确的填充,并简单地将输入结果作为输出返回而不进行修改。
  • 是的,问题的一部分是用于偏移的错误变量和许多其他小问题导致函数的错误。我将更新问题以包含实际的工作答案。
  • 我写的旧代码的另一个主要问题是假设输入和输出是两个不同的字节数组,这些数组可以重新用作工作缓冲区来操作数据,但情况并非总是如此,所以我添加了一个特定的工作缓冲区字节数组,用于将缓冲区计算与输入/输出分开,这是旧函数存在的许多问题的一部分。
猜你喜欢
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 2020-12-28
  • 2011-05-29
  • 2017-08-29
相关资源
最近更新 更多