为了账号安全,请及时绑定邮箱和手机立即绑定

在执行 getKey() 时,在令牌 USB 上存储密钥会提供不同的密钥

在执行 getKey() 时,在令牌 USB 上存储密钥会提供不同的密钥

蝴蝶刀刀 2021-08-19 18:57:10
我正在尝试SecretKey在加密 USB 令牌上存储对称密钥(即三重 DES 密钥,ECB 模式)。我使用以下代码来做到这一点:private void storeSecretKey( SecretKey secretKey, String alias ) throws StoreException {    try {        log.info("Format: " + secretKey.getFormat());        log.info("Alg: " + secretKey.getAlgorithm());        log.info("STORE KEY (bytes): " + Arrays.toString( secretKey.getEncoded()));        log.info("STORE KEY: " + ArrayUtils.convertToHexString( secretKey.getEncoded(), false, false));        myKeyStore.setKeyEntry(alias, secretKey, tokenPIN.toCharArray(), null);        myKeyStore.store(null);        Key key = myKeyStore.getKey(alias, tokenPIN.toCharArray());        log.info("Format: " + key.getFormat());        log.info("Alg: " + key.getAlgorithm());        log.info("FINAL KEY (bytes): " + Arrays.toString( key.getEncoded()));        log.info("FINAL KEY: " + ArrayUtils.convertToHexString( key.getEncoded(), false, false));    }    catch ( KeyStoreException e ) {        throw new StoreException( "Unable to store encryption key", e );    } catch (NoSuchAlgorithmException e) {        e.printStackTrace();    } catch (UnrecoverableEntryException e) {        e.printStackTrace();    }}我得到以下日志:INFO: Format: RAWINFO: Alg: DESedeINFO: STORE KEY (bytes): [87, -81, -89, -62, 5, -116, -46, 111, -85, -52, -28, -85, -26, -57, -26, -58, -66, -52, -16, 30, 89, -45, 61, -86]INFO: STORE KEY: 57afa7c2058cd26fabcce4abe6c7e6c6beccf01e59d33daaINFO: Format: RAWINFO: Alg: DESedeINFO: FINAL KEY (bytes): [87, -82, -89, -62, 4, -116, -45, 110, -85, -51, -27, -85, -26, -57, -26, -57, -65, -51, -15, 31, 88, -45, 61, -85]INFO: FINAL KEY: 57aea7c2048cd36eabcde5abe6c7e6c7bfcdf11f58d33dab存储在令牌上的密钥 (STORE KEY) 和我使用的密钥getKey()(FINAL KEY) 不同。怎么会这样?如果您需要任何其他可能丢失的信息,请通知我。
查看完整描述

1 回答

?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

您的 USB 令牌只是调整 3DES 密钥的奇偶校验。每个字节的每个低端位是(三重)DES 的奇偶校验位。


如果最高 7 位相加是偶数则需要设置,如果是奇数则不需要设置。如果将所有位加在一起,最后每个字节都应该具有奇校验。所以第一个带有值0x57or0b0101011_1和的字节在最高位置有 4 位,所以最后一位必须是1- 但它已经被设置,所以不需要调整。第二个字节,0xAF或者0b1010111_1最高位有 5 位,所以最后一位需要是0. 情况并非如此,因此将其调整为0b1010111_0或0xAE。


如果您想拥有相同的值,那么您可以使用 aSecretKeyFactory而不是直接使用随机数生成器来构造您的(三重)DES 密钥。该SecretKeyFactory也将为你调整奇偶-无需自己动手编程。我建议这样做,因为其他实现可能会拒绝位数为偶数的字节(尽管通常调整或忽略位)。正如 James 所指出的,在加密/解密期间(三重)DES 不使用最低位。


这将创建正确编码的三重 DES 密钥(168 位有效,192 位编码)。这些也称为 DES ABC 密钥,因为所有三个 DES 密钥都不同(概率非常高)。


public static SecretKey generate192Bit3DESKey() {

    KeyGenerator keyGen;

    try {

        keyGen = KeyGenerator.getInstance("DESede");

    } catch (NoSuchAlgorithmException e) {

        throw new IllegalStateException("DESede functionality is required for Java, but it is missing");

    }


    // NOTE: this is the effective key size excluding parity bits

    // use 112 for two key (ABA) triple DES keys (not recommended)

    keyGen.init(168);


    // this does adjust parity

    SecretKey desABCKey = keyGen.generateKey();

    return desABCKey;

}

如果您的数据之后需要调整,您可以使用它(只有一个 for 循环,没有额外的分支):


public static byte[] adjustDESParity(final byte[] keyData) {

    for (int i = 0; i < keyData.length; i++) {

        // count the bits, and XOR with 1 if even or 0 if already odd 

        keyData[i] ^= (Integer.bitCount(keyData[i]) % 2) ^ 1;

    }

    return keyData;

}


查看完整回答
反对 回复 2021-08-19
  • 1 回答
  • 0 关注
  • 171 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信