使用java对PSKC文件进行解密

使用java对PSKC文件进行解密,java,Java,我不熟悉加密和解密。我得到了一个PSKC文件并要求解密。我得到了解密的密码。PSKC文件没有初始化向量值。 我写的代码试图解密它。但我没有取得成功。 下面是PSKC文件示例 <?xml version="1.0"?> <pskc:KeyContainer xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:pkcs5="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkc

我不熟悉加密和解密。我得到了一个PSKC文件并要求解密。我得到了解密的密码。PSKC文件没有初始化向量值。 我写的代码试图解密它。但我没有取得成功。 下面是PSKC文件示例

<?xml version="1.0"?>
<pskc:KeyContainer xmlns:ds="http://www.w3.org/2000/09/xmldsig#"    xmlns:pkcs5="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#"   xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:xenc11="http://www.w3.org/2009/xmlenc11#" xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc">
 <pskc:EncryptionKey>
<xenc11:DerivedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:pkcs5="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#" xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc11="http://www.w3.org/2009/xmlenc11#">
  <xenc11:KeyDerivationMethod Algorithm="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2">
    <pkcs5:PBKDF2-params xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc" xmlns:xenc11="http://www.w3.org/2009/xmlenc11#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:pkcs5="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#">
      <Salt>
        <Specified>EW0h0yUcDX72WU9UiKiCwDpXsJg=</Specified>
      </Salt>
      <IterationCount>128</IterationCount>
      <KeyLength>16</KeyLength>
      <PRF />
      </pkcs5:PBKDF2-params>
     </xenc11:KeyDerivationMethod>
     <xenc:ReferenceList>
       <xenc:DataReference URI="#ED" />
       </xenc:ReferenceList>
       <xenc11:MasterKeyName>Passphrase1</xenc11:MasterKeyName>
       </xenc11:DerivedKey>
    </pskc:EncryptionKey>
   <pskc:MACMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
     <pskc:MACKey>
     <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" />
      <xenc:CipherData>
           <xenc:CipherValue>jq/NdikC7AZf0Z+HEL5NrCICV8XW+ttzl/8687hVGHceoyJAaFws+111plQH6Mlg</xenc:CipherValue>
  </xenc:CipherData>
   </pskc:MACKey>
  </pskc:MACMethod>
 <pskc:KeyPackage>
<pskc:DeviceInfo>
  <pskc:Manufacturer>Gemalto</pskc:Manufacturer>
  <pskc:SerialNo>GAKT000047A5</pskc:SerialNo>
</pskc:DeviceInfo>
<pskc:CryptoModuleInfo>
  <pskc:Id>CM_ID_007</pskc:Id>
</pskc:CryptoModuleInfo>
<pskc:Key Id="GAKT000047A5" Algorithm="urn:ietf:params:xml:ns:keyprov:pskc:totp">
  <pskc:Issuer>Issuer0</pskc:Issuer>
  <pskc:AlgorithmParameters>
    <pskc:ResponseFormat Encoding="DECIMAL" Length="6" />
  </pskc:AlgorithmParameters>
  <pskc:Data>
    <pskc:Secret>
      <pskc:EncryptedValue>
        <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"   />
        <xenc:CipherData>
              <xenc:CipherValue>pM7VB/KomPjq2cKaxPr5cKT1tUZN5tGMI+u1XKJTG1la+ThraPpLKlL2plKk6vQE</xenc:CipherValue>
        </xenc:CipherData>
      </pskc:EncryptedValue>
      <pskc:ValueMAC>lbu+9OcLArnj6mS7KYOKDa4zRU0=</pskc:ValueMAC>
    </pskc:Secret>
    <pskc:Time>
      <pskc:PlainValue>0</pskc:PlainValue>
    </pskc:Time>
    <pskc:TimeInterval>
      <pskc:PlainValue>30</pskc:PlainValue>
    </pskc:TimeInterval>
  </pskc:Data>
</pskc:Key>
 </pskc:KeyPackage>
 </pskc:KeyContainer>
它不会抛出任何异常,但会打印“哈希验证失败”,这是在解密失败时在我的代码中定义的。
有人能帮我一下吗。

根据pskc标准,IV是在密码值前加上的。这是aes128,因此它将是base64解码后的前16个字节。

根据pskc标准,IV在密码值之前。这是aes128,所以它将是base64解码后的前16个字节。

添加到bcharlton描述的内容上;您没有做的是使用xml文档中描述的MACKey检查hmac_sha1中的加密数据(它以加密形式预先添加了iv)

AES-128 CBC明确定义了初始化向量,由于没有内置验证,因此使用HMAC进行验证

因此,以您的示例为例,以下内容将起作用:

public static HashMap decryptSeedValue() throws Exception
{

String password = "G?20R+I+3-/UcWIN";


String pbesalt = "EW0h0yUcDX72WU9UiKiCwDpXsJg=";
String iv = "aaaaaaaaaaaaaaaaaaaaaaaa";

int iteration = 128;

String value = "pM7VB/KomPjq2cKaxPr5cKT1tUZN5tGMI+u1XKJTG1la+ThraPpLKlL2plKk6vQE";
String valueDigest = "lbu+9OcLArnj6mS7KYOKDa4zRU0=";

//YOU NEED THIS GUY BELOW TO VERIFY
String macKey = "jq/NdikC7AZf0Z+HEL5NrCICV8XW+ttzl/8687hVGHceoyJAaFws+111plQH6Mlg";

byte[] cipherText = null;

//some parameters need to decode from Base64 to byte[]
byte[] data = base64Decode(value.getBytes());
//System.out.println("data(hex string) = " + HexBin.encode(data));//debug

byte[] salt = base64Decode(pbesalt.getBytes());
//System.out.println("salt(hex string) = " + HexBin.encode(salt));//debug

byte[] initVec = base64Decode(iv.getBytes());
//System.out.println("iv(hex string) = " + HexBin.encode(initVec));//debug

//perform PBE key generation and AES/CBC/PKCS5Padding decrpyption
HashMap hs = myFunction(data, password, base64Decode(macKey.getBytes()), salt, iteration);

String seedValue = (String) hs.get("DECRYPTED_SEED_VALUE");
byte[] temp = (byte[]) hs.get("HASH_OUTPUT");

//System.out.println("hashed output(hex string) = " + HexBin.encode(temp));//debug
//perform Base64 Encode 
byte[] out = base64Encode(temp);

String output = new String((out));
System.out.println("output = " + output);
System.out.println("valueD = " + valueDigest);
//System.out.println("hashed output(base64) = " + output);

//compare the result
if (output.equals(valueDigest)) {
  System.out.println("Hash verification successful for:-->");
  System.out.println("\n");

  //hs.put("SEED_VALUE", HexBin.encode(temp));
  hs.put("SEED_VALUE", seedValue);
  return hs;

} else {
  System.out.println("Hash verification failed  for :-->");

  return null;

}

}
public static HashMap myFunction(byte[] data, String password, byte[] macData,
      byte[] salt, int iteration) throws Exception
{

PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator();

byte[] pBytes = password.getBytes();

generator.init(pBytes, salt, iteration);

byte[] iv = new byte[16];
int ivsize = iv.length;
byte[] encryptedData = new byte[data.length - ivsize];
System.arraycopy(data, 0, iv, 0, iv.length);
System.arraycopy(data, ivsize, encryptedData, 0, encryptedData.length);

byte[] maciv = new byte[16];
byte[] encryptedMac = new byte[macData.length - maciv.length];
System.arraycopy(macData, 0, maciv, 0, maciv.length);
System.arraycopy(macData, maciv.length, encryptedMac, 0, encryptedMac.length);

int keysize = 128;//fixed at AES key of 16 bytes

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iteration, keysize);
SecretKey tmp = factory.generateSecret(spec);
SecretKey key = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));

byte[] decryptedData = dcipher.doFinal(encryptedData);
// decryptedData is your token value!

dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(maciv));

byte[] decryptedMac = dcipher.doFinal(encryptedMac);

//display the 20 bytes secret of the token 
//System.out.println("token secret(hex string) = " + HexBin.encode(secret));
//perform HMAC-SHA-1

//Use the decrypted MAC key here for hashing!
byte[] output = hmac_sha1(data, decryptedMac);

HashMap hs = new HashMap();

hs.put("ENCRYPTION_KEY", password);
hs.put("HASH_OUTPUT", output);

hs.put("DECRYPTED_SEED_VALUE", HexBin.encode(decryptedData));

return hs;
}

请记住,如上所述,MAC和令牌密钥可以使用不同的iv。

添加到bcharlton所描述的内容上;您没有做的是使用xml文档中描述的MACKey检查hmac_sha1中的加密数据(它以加密形式预先添加了iv)

AES-128 CBC明确定义了初始化向量,由于没有内置验证,因此使用HMAC进行验证

因此,以您的示例为例,以下内容将起作用:

public static HashMap decryptSeedValue() throws Exception
{

String password = "G?20R+I+3-/UcWIN";


String pbesalt = "EW0h0yUcDX72WU9UiKiCwDpXsJg=";
String iv = "aaaaaaaaaaaaaaaaaaaaaaaa";

int iteration = 128;

String value = "pM7VB/KomPjq2cKaxPr5cKT1tUZN5tGMI+u1XKJTG1la+ThraPpLKlL2plKk6vQE";
String valueDigest = "lbu+9OcLArnj6mS7KYOKDa4zRU0=";

//YOU NEED THIS GUY BELOW TO VERIFY
String macKey = "jq/NdikC7AZf0Z+HEL5NrCICV8XW+ttzl/8687hVGHceoyJAaFws+111plQH6Mlg";

byte[] cipherText = null;

//some parameters need to decode from Base64 to byte[]
byte[] data = base64Decode(value.getBytes());
//System.out.println("data(hex string) = " + HexBin.encode(data));//debug

byte[] salt = base64Decode(pbesalt.getBytes());
//System.out.println("salt(hex string) = " + HexBin.encode(salt));//debug

byte[] initVec = base64Decode(iv.getBytes());
//System.out.println("iv(hex string) = " + HexBin.encode(initVec));//debug

//perform PBE key generation and AES/CBC/PKCS5Padding decrpyption
HashMap hs = myFunction(data, password, base64Decode(macKey.getBytes()), salt, iteration);

String seedValue = (String) hs.get("DECRYPTED_SEED_VALUE");
byte[] temp = (byte[]) hs.get("HASH_OUTPUT");

//System.out.println("hashed output(hex string) = " + HexBin.encode(temp));//debug
//perform Base64 Encode 
byte[] out = base64Encode(temp);

String output = new String((out));
System.out.println("output = " + output);
System.out.println("valueD = " + valueDigest);
//System.out.println("hashed output(base64) = " + output);

//compare the result
if (output.equals(valueDigest)) {
  System.out.println("Hash verification successful for:-->");
  System.out.println("\n");

  //hs.put("SEED_VALUE", HexBin.encode(temp));
  hs.put("SEED_VALUE", seedValue);
  return hs;

} else {
  System.out.println("Hash verification failed  for :-->");

  return null;

}

}
public static HashMap myFunction(byte[] data, String password, byte[] macData,
      byte[] salt, int iteration) throws Exception
{

PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator();

byte[] pBytes = password.getBytes();

generator.init(pBytes, salt, iteration);

byte[] iv = new byte[16];
int ivsize = iv.length;
byte[] encryptedData = new byte[data.length - ivsize];
System.arraycopy(data, 0, iv, 0, iv.length);
System.arraycopy(data, ivsize, encryptedData, 0, encryptedData.length);

byte[] maciv = new byte[16];
byte[] encryptedMac = new byte[macData.length - maciv.length];
System.arraycopy(macData, 0, maciv, 0, maciv.length);
System.arraycopy(macData, maciv.length, encryptedMac, 0, encryptedMac.length);

int keysize = 128;//fixed at AES key of 16 bytes

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iteration, keysize);
SecretKey tmp = factory.generateSecret(spec);
SecretKey key = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));

byte[] decryptedData = dcipher.doFinal(encryptedData);
// decryptedData is your token value!

dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(maciv));

byte[] decryptedMac = dcipher.doFinal(encryptedMac);

//display the 20 bytes secret of the token 
//System.out.println("token secret(hex string) = " + HexBin.encode(secret));
//perform HMAC-SHA-1

//Use the decrypted MAC key here for hashing!
byte[] output = hmac_sha1(data, decryptedMac);

HashMap hs = new HashMap();

hs.put("ENCRYPTION_KEY", password);
hs.put("HASH_OUTPUT", output);

hs.put("DECRYPTED_SEED_VALUE", HexBin.encode(decryptedData));

return hs;
}

请记住,如上所述,MAC和令牌密钥可以使用不同的iv。

EJP,我无法直接跟进您的评论,但在本例中,PSKC(便携式对称密钥容器)是正确的。奇怪的是,PSKC标准(rfc6030)依赖PKC。我很想知道谁认为这是个好主意。EJP,我不能直接跟进您的评论,但在本例中,PSKC(便携式对称密钥容器)是正确的。奇怪的是,PSKC标准(rfc6030)依赖PKC。我很想知道谁认为这是个好主意。