74 lines
3.5 KiB
Java
74 lines
3.5 KiB
Java
package com.secure.demo;
|
|
|
|
import android.os.Bundle;
|
|
import android.widget.TextView;
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
import com.secure.device.DeviceCrypto;
|
|
import java.security.KeyFactory;
|
|
import java.security.Signature;
|
|
import java.security.spec.X509EncodedKeySpec;
|
|
import java.util.Base64;
|
|
|
|
/**
|
|
* 最精简演示:在 KeyStore(TEE) 中生成 RSA-2048 密钥对,
|
|
* 完成「信封加密 → 解密还原」与「元数据签名 → 公钥验签」全流程,
|
|
* 无需任何后端即可在真机/模拟器上验证 DeviceCrypto 可用。
|
|
*/
|
|
public class MainActivity extends AppCompatActivity {
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.activity_main);
|
|
TextView tv = findViewById(R.id.log);
|
|
|
|
new Thread(() -> {
|
|
StringBuilder sb = new StringBuilder();
|
|
try {
|
|
DeviceCrypto crypto = new DeviceCrypto(this);
|
|
|
|
String pub = crypto.getPublicKeyBase64();
|
|
sb.append("设备公钥(前48字符):\n").append(pub, 0, Math.min(48, pub.length()))
|
|
.append("...\n\n");
|
|
|
|
// 1) 信封加密(模拟拍照)
|
|
String plaintext = "私密照片数据 Hello TEE!";
|
|
DeviceCrypto.EncryptedPayload p = crypto.encryptData(plaintext.getBytes("UTF-8"));
|
|
sb.append("原始数据: ").append(plaintext).append("\n");
|
|
sb.append("密文: ").append(p.ciphertextBase64, 0, Math.min(32, p.ciphertextBase64.length()))
|
|
.append("...\n");
|
|
sb.append("IV: ").append(p.ivBase64).append("\n");
|
|
sb.append("DEK(明文, 实际应仅经HTTPS给服务端): ")
|
|
.append(p.dekBase64, 0, Math.min(24, p.dekBase64.length())).append("...\n\n");
|
|
|
|
// 2) 服务端用 UK 加密 DEK 后下发,此处用相同 DEK 还原,验证解密链路
|
|
byte[] dekBytes = Base64.getDecoder().decode(p.dekBase64);
|
|
byte[] decrypted = crypto.decryptPhoto(p.ciphertextBase64, p.ivBase64, dekBytes);
|
|
sb.append("解密还原: ").append(new String(decrypted, "UTF-8")).append("\n\n");
|
|
|
|
// 3) 元数据签名 + 公钥验签
|
|
String metadata = crypto.getDeviceSN() + "|" + System.currentTimeMillis() + "|photo001";
|
|
String sig = crypto.signMetadata(metadata);
|
|
sb.append("元数据: ").append(metadata).append("\n");
|
|
sb.append("签名(前32字符): ").append(sig, 0, Math.min(32, sig.length())).append("...\n");
|
|
boolean ok = verify(metadata, sig, pub);
|
|
sb.append("验签结果: ").append(ok ? "通过 ✅" : "失败 ❌").append("\n");
|
|
} catch (Exception e) {
|
|
sb.append("异常: ").append(e).append("\n");
|
|
e.printStackTrace();
|
|
}
|
|
final String text = sb.toString();
|
|
runOnUiThread(() -> tv.setText(text));
|
|
}).start();
|
|
}
|
|
|
|
private boolean verify(String metadata, String sigBase64, String pubKeyBase64) throws Exception {
|
|
java.security.PublicKey pub = KeyFactory.getInstance("RSA")
|
|
.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(pubKeyBase64)));
|
|
Signature s = Signature.getInstance("SHA256withRSA");
|
|
s.initVerify(pub);
|
|
s.update(metadata.getBytes("UTF-8"));
|
|
return s.verify(Base64.getDecoder().decode(sigBase64));
|
|
}
|
|
}
|