如何使用TPM EK进行加密和解密



我正在使用Microsoft提供的TPM Java库。模拟器的连接正在工作。陷入如何使用TPM Endrosment公钥加密字符串和使用TPM Endrosement私钥解密的困境。

以下是功能不正确的代码,若TPM私有EK在外界不可见,那个么如何使用私有EK进行解密。

public class Sample {
boolean usesTbs;
Tpm tpm;
Cipher cipher;
public static byte[] nullVec = new byte[36];
private static final String SHA_256 = "SHA-256";
private static final String EQUALS = "=";
private final String registrationId;
private TPMT_PUBLIC ekPublic = null;
private TPMT_PUBLIC srkPublic = null;
private TPM2B_PUBLIC idKeyPub = null;
private static final TPM_HANDLE SRK_PERSISTENT_HANDLE = TPM_HANDLE.persistent(0x00000001);
private static final TPM_HANDLE EK_PERSISTENT_HANDLE = TPM_HANDLE.persistent(0x00010001);
private static final TPM_HANDLE ID_KEY_PERSISTENT_HANDLE = TPM_HANDLE.persistent(0x00000100);
private static final TPMT_SYM_DEF_OBJECT AES_128_SYM_DEF = new TPMT_SYM_DEF_OBJECT(TPM_ALG_ID.AES, 128, TPM_ALG_ID.CFB);
private static final TPMT_PUBLIC EK_TEMPLATE = new TPMT_PUBLIC(
// TPMI_ALG_HASH    nameAlg
TPM_ALG_ID.SHA256,
// TPMA_OBJECT  objectAttributes
new TPMA_OBJECT(TPMA_OBJECT.restricted, TPMA_OBJECT.decrypt, TPMA_OBJECT.fixedTPM, TPMA_OBJECT.fixedParent,
TPMA_OBJECT.adminWithPolicy, TPMA_OBJECT.sensitiveDataOrigin),
// TPM2B_DIGEST authPolicy
javax.xml.bind.DatatypeConverter.parseHexBinary("837197674484b3f81a90cc8d46a5d724fd52d76e06520b64f2a1da1b331469aa"),
// TPMU_PUBLIC_PARMS    parameters
new TPMS_RSA_PARMS(AES_128_SYM_DEF, new TPMS_NULL_ASYM_SCHEME(), 2048, 0),
// TPMU_PUBLIC_ID       unique
new TPM2B_PUBLIC_KEY_RSA());
private static final TPMT_PUBLIC SRK_TEMPLATE = new TPMT_PUBLIC(
// TPMI_ALG_HASH    nameAlg
TPM_ALG_ID.SHA256,
// TPMA_OBJECT  objectAttributes
new TPMA_OBJECT(TPMA_OBJECT.restricted, TPMA_OBJECT.decrypt, TPMA_OBJECT.fixedTPM, TPMA_OBJECT.fixedParent,
TPMA_OBJECT.noDA, TPMA_OBJECT.userWithAuth, TPMA_OBJECT.sensitiveDataOrigin),
// TPM2B_DIGEST authPolicy
new byte[0],
// TPMU_PUBLIC_PARMS    parameters
new TPMS_RSA_PARMS(AES_128_SYM_DEF, new TPMS_NULL_ASYM_SCHEME(), 2048, 0),
// TPMU_PUBLIC_ID       unique
new TPM2B_PUBLIC_KEY_RSA());
public TpmSample() throws Exception {
System.out.println("===> PATH = " + System.getenv("PATH"));
System.out.println("===> path = " + System.getenv("path"));
usesTbs = CmdLine.isOptionPresent("tbs", "t");
System.out.println("Connecting to " + (usesTbs ? "OS TPM" : "TPM Simulator"));
tpm = usesTbs ? TpmFactory.platformTpm() : TpmFactory.localTpmSimulator();
clearPersistent(tpm, EK_PERSISTENT_HANDLE, "EK");
clearPersistent(tpm, SRK_PERSISTENT_HANDLE, "SRK");
ekPublic = createPersistentPrimary(tpm, EK_PERSISTENT_HANDLE, TPM_RH.OWNER, EK_TEMPLATE, "EK");
srkPublic = createPersistentPrimary(tpm, SRK_PERSISTENT_HANDLE, TPM_RH.OWNER, SRK_TEMPLATE, "SRK");
//SRS_SecurityProviderTPMEmulator_25_002: [ The constructor shall set the registration Id to null if none was provided. ]
this.registrationId = null;
}
private void cleanSlots(TPM_HT slotType) {
GetCapabilityResponse caps = tpm.GetCapability(TPM_CAP.HANDLES, slotType.toInt() << 24, 8);
TPML_HANDLE handles = (TPML_HANDLE) caps.capabilityData;
if (handles.handle.length == 0)
System.out.println("No dangling " + slotType.name() + " handles");
else
for (TPM_HANDLE h : handles.handle) {
System.out.printf("Dangling " + slotType.name() + " handle 0x%08Xn", h.handle);
tpm.FlushContext(h);
}
}
public byte[] getEndrosmentPrivateKey() {
return (new TPM2B_PRIVATE()).toTpm();
}
public byte[] getEndorsementKey() {
//SRS_SecurityProviderTPMEmulator_25_032: [ This method shall return the TPM2B_PUBLIC form of EK. ]
return (new TPM2B_PUBLIC(ekPublic)).toTpm();
}
public byte[] getStorageRootKey() {
//SRS_SecurityProviderTPMEmulator_25_033: [ This method shall return the TPM2B_PUBLIC form of SRK. ]
return (new TPM2B_PUBLIC(srkPublic)).toTpm();
}
private TPMT_PUBLIC createPersistentPrimary(Tpm tpm, TPM_HANDLE hPersistent, TPM_RH hierarchy, TPMT_PUBLIC inPub, String primaryRole) throws Exception {
ReadPublicResponse rpResp = tpm._allowErrors().ReadPublic(hPersistent);
if (rpResp == null) {
throw new Exception("ReadPublicResponse cannot be null");
}
TPM_RC rc = tpm._getLastResponseCode();
if (rc == TPM_RC.SUCCESS) {
// TODO: Check if the public area of the existing key matches the requested one
return rpResp.outPublic;
}
if (rc != TPM_RC.HANDLE) {
throw new Exception("Unexpected failure {" + rc.name() + "} of TPM2_ReadPublic for {" + primaryRole + "}");
}
TPMS_SENSITIVE_CREATE sens = new TPMS_SENSITIVE_CREATE(new byte[0], new byte[0]);
CreatePrimaryResponse cpResp = tpm.CreatePrimary(TPM_HANDLE.from(hierarchy), sens, inPub,
new byte[0], new TPMS_PCR_SELECTION[0]);
//        System.out.println("RSA Primary Key: n" + cpResp.toString());
if (cpResp == null) {
throw new Exception("CreatePrimaryResponse cannot be null");
}
tpm.EvictControl(TPM_HANDLE.from(TPM_RH.OWNER), cpResp.handle, hPersistent);
tpm.FlushContext(cpResp.handle);
return cpResp.outPublic;
}
private void clearPersistent(Tpm tpm, TPM_HANDLE hPersistent, String keyRole) throws Exception {
tpm._allowErrors().ReadPublic(hPersistent);
TPM_RC rc = tpm._getLastResponseCode();
if (rc == TPM_RC.SUCCESS) {
tpm.EvictControl(TPM_HANDLE.from(TPM_RH.OWNER), hPersistent, hPersistent);
} else if (rc != TPM_RC.HANDLE) {
throw new Exception("Unexpected failure for {" + rc.name() + "} of TPM2_ReadPublic for " + keyRole + " 0x" + hPersistent.handle);
}
}
public SecretKeySpec setKey(byte[] key) {
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance(SHA_256);
key = digest.digest(key);
key = Arrays.copyOf(key, 16);
return new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public byte[] encrypt(String data, byte[] publicEKey) throws Exception {
SecretKeySpec secretKeySpec = setKey(publicEKey);
cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(new byte[16]));
byte[] cipherText = cipher.doFinal(data.getBytes("UTF-8"));
System.out.println("Encrypted Data from Method:->" + new String(cipherText, "UTF-8"));
return cipherText;
}
public byte[] decrypt(byte[] cipherText, byte[] privateEKey) throws Exception {
SecretKeySpec secretKeySpec = setKey(privateEKey);
Cipher cipherDecrypt = Cipher.getInstance("AES/CFB/NoPadding");
cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(new byte[16]));
byte[] decipheredText = cipher.doFinal(cipherText);
System.out.println("Decrypted Data from Method:-> " + new String(decipheredText));
return decipheredText;
}

public static void main(String[] args) throws Exception {
String data = "asdfqwert";
Sample tpmSample = new Sample();
tpmSample.cleanSlots(TPM_HT.TRANSIENT);
tpmSample.cleanSlots(TPM_HT.LOADED_SESSION);
tpmSample.getTpmInformation();
System.out.println("Endrosment Key :->" + new String(org.bouncycastle.util.encoders.Base64.encode(tpmSample.getEndorsementKey())));
System.out.println("Private Endrosment Key :->" + new String(org.bouncycastle.util.encoders.Base64.encode(tpmSample.getEndrosmentPrivateKey())));
byte[] publicEKey = new String(Base64.encode(tpmSample.getEndorsementKey())).getBytes("UTF-8");
byte[] privateEKey = new String(Base64.encode(tpmSample.getEndrosmentPrivateKey())).getBytes("UTF-8");
System.out.println("Original Data ->" + data);
byte[] enc = tpmSample.encrypt(data, publicEKey);
tpmSample.decrypt(enc, privateEKey);
}
}

背书密钥(EK(不允许直接用于加密。相反,您应该使用主键创建StorageKey(SK(或Storage Key层次结构。然后,创建另一个加密密钥,并使用该密钥加密硬盘驱动器或文件的一部分。

这可以使用TPM2密封/不密封来实现。如果是单个字符串的问题,您可以使用TPM2加密/解密来欺骗,但不建议这样做。最好有一个带有秘密的文件并加密该文件。

我可以建议的是,看看这个关于TPM的一些基础https://google.github.io/tpm-js/这里有一个关于使用Seal/Unsecal和EncryptDecrypt之间区别的很好的讨论https://developers.tpm.dev/posts/8628948

这两个资源应该可以消除您的困惑,然后就可以编写代码了。我不确定Java和Microsoft TPM2.0堆栈是否是实现您想要的东西的最快方法,但一旦您正确地理解了概念,那么它实际上只是实现:(

相关内容

  • 没有找到相关文章

最新更新