使用java进行PSKC文件解密

时间:2013-06-04 09:18:16

标签: java

我是加密和解密的新手。我得到了一个PSKC文件并要求解密。我获得了解密密码。 PSKC文件doenot具有初始化向量值。 我写了试图解密它的代码。但我没有成功实现结果。 下面是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>

下面是我为解密而编写的java代码。

import java.security.NoSuchAlgorithmException;
import java.util.HashMap;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;


import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;


public class test {

/**
 * @param args
 */
public static void main(String[] args) {
    test te = new test();
    try {
        te.decryptSeedValue();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
    // TODO Auto-generated method stub

}

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=";




    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, initVec, 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[] initVec,
                              byte[] salt, int iteration) throws Exception{

    PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator();

    byte[] pBytes = password.getBytes();

    generator.init(pBytes, salt, iteration);

    int keysize = 128;//fixed at AES key of 16 bytes
    int ivsize = initVec.length;

    ParametersWithIV params = (ParametersWithIV) generator.generateDerivedParameters(keysize, ivsize);

    KeyParameter keyParam = (KeyParameter) params.getParameters();

    //System.out.println("derived key = " + HexBin.encode(keyParam.getKey()));

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

    IvParameterSpec paramSpec = new IvParameterSpec(initVec);

    SecretKeySpec key = new SecretKeySpec(keyParam.getKey(), "AES");

    cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

    //perform decryption
    byte[] secret = cipher.doFinal(data);

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

    //perform HMAC-SHA-1
    byte[] output = hmac_sha1(secret, keyParam.getKey());

    HashMap hs = new HashMap();

    hs.put("ENCRYPTION_KEY", HexBin.encode(keyParam.getKey()));
    hs.put("HASH_OUTPUT", output);

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

    return hs;
}

public static byte[] base64Encode(byte[] passwordBytes) throws NoSuchAlgorithmException {
    Base64 base64 = new Base64();
    byte[] hashBytes2 = base64.encode(passwordBytes);
    return hashBytes2;
}

public static byte[] base64Decode(byte[] passwordBytes) throws NoSuchAlgorithmException {
    Base64 base64 = new Base64();
    byte[] hashBytes2 = base64.decode(passwordBytes);
    return hashBytes2;
}

public static byte[] hmac_sha1(byte[] dataByte, byte[] keyByte) throws Exception{
    Mac hmacSha1;
    hmacSha1 = Mac.getInstance("HmacSHA1");

    SecretKeySpec macKey = new SecretKeySpec(keyByte, "HmacSHA1");
    hmacSha1.init(macKey);
    byte[] result = hmacSha1.doFinal(dataByte);
    return result;

}
/**
 * Convert a byte array of 8 bit characters into a String.
 * 
 * @param bytes the array containing the characters
 * @param length the number of bytes to process
 * @return a String representation of bytes
 */
private static String toString(
    byte[] bytes,
    int    length)
{
    char[]  chars = new char[length];

    for (int i = 0; i != chars.length; i++)
    {
        chars[i] = (char)(bytes[i] & 0xff);
    }

    return new String(chars);
}

} 

它不会抛出任何异常,但会打印出“哈希验证失败”,这在解密失败时在我的代码中定义。 有人可以帮助我。

2 个答案:

答案 0 :(得分:1)

根据pskc标准http://www.rfc-editor.org/rfc/rfc6030.txt,IV被加在密码值之前。这是aes128,所以一旦它被base64解码,它将是前16个字节。

答案 1 :(得分:0)

添加到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;
}

请记住,正如https://tools.ietf.org/html/rfc6030#section-6.2所述,不同的iv可用于MAC和令牌密钥。