From e813c33cf586506744ed99d1445e8bf12605ab38 Mon Sep 17 00:00:00 2001 From: Power Li Date: Sat, 2 Mar 2024 01:35:45 +0800 Subject: [PATCH] update BC version, use internal crypto lib instead of BC on EC --- app/build.gradle | 7 +- .../wearos/teslanak/nfc/TeslaNAKService.java | 79 ++++++++++--------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6d3a281..b145f36 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,8 +12,8 @@ android { applicationId "li.power.app.wearos.teslanak" minSdkVersion 24 targetSdkVersion 30 - versionCode 10 - versionName "1.3.1" + versionCode 14 + versionName "1.3.5" } @@ -31,8 +31,7 @@ android { dependencies { implementation 'com.google.android.material:material:1.11.0' implementation 'androidx.wear:wear:1.1.0' - implementation "org.bouncycastle:bcprov-jdk15on:1.68" - // https://mvnrepository.com/artifact/commons-codec/commons-codec + implementation "org.bouncycastle:bcprov-jdk18on:1.77" implementation group: 'commons-codec', name: 'commons-codec', version: '1.15' implementation "androidx.core:core-splashscreen:1.0.1" diff --git a/app/src/main/java/li/power/app/wearos/teslanak/nfc/TeslaNAKService.java b/app/src/main/java/li/power/app/wearos/teslanak/nfc/TeslaNAKService.java index 7543002..a0bc139 100644 --- a/app/src/main/java/li/power/app/wearos/teslanak/nfc/TeslaNAKService.java +++ b/app/src/main/java/li/power/app/wearos/teslanak/nfc/TeslaNAKService.java @@ -3,17 +3,8 @@ import android.content.SharedPreferences; import android.nfc.cardemulation.HostApduService; import android.os.Bundle; -import android.util.Log; import android.widget.Toast; - import org.bouncycastle.jce.ECNamedCurveTable; -import org.bouncycastle.jce.interfaces.ECPrivateKey; -import org.bouncycastle.jce.interfaces.ECPublicKey; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.jce.spec.ECParameterSpec; -import org.bouncycastle.jce.spec.ECPrivateKeySpec; -import org.bouncycastle.jce.spec.ECPublicKeySpec; -import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.util.encoders.Hex; import javax.crypto.*; @@ -23,7 +14,9 @@ import java.math.BigInteger; import java.security.*; import java.security.cert.CertificateException; -import java.security.spec.InvalidKeySpecException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.*; /* * @@ -54,7 +47,6 @@ public class TeslaNAKService extends HostApduService { @Override public void onCreate() { - setupBouncyCastle(); sharedPreferences = getSharedPreferences(KEY_ALIAS, MODE_PRIVATE); try { keyStore = KeyStore.getInstance(KEYSTORE_PROVIDER); @@ -104,32 +96,47 @@ private byte[] processGetCardInfo() { return new byte[]{0x00, 0x01, (byte) 0x90, 0x00}; } - public static PrivateKey loadPrivateKey(byte[] data) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException { - ECParameterSpec params = ECNamedCurveTable.getParameterSpec(CURVE); + public static PrivateKey loadPrivateKey(byte[] data) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, InvalidParameterSpecException { + AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); + parameters.init(new ECGenParameterSpec("secp256r1")); + ECParameterSpec params = parameters.getParameterSpec(ECParameterSpec.class); ECPrivateKeySpec prvkey = new ECPrivateKeySpec(new BigInteger(data), params); - KeyFactory kf = KeyFactory.getInstance("EC", "BC"); + KeyFactory kf = KeyFactory.getInstance("EC"); return kf.generatePrivate(prvkey); } public static PublicKey loadPublicKey(byte[] data) throws Exception { - ECParameterSpec params = ECNamedCurveTable.getParameterSpec(CURVE); - ECPublicKeySpec pubKey = new ECPublicKeySpec( - params.getCurve().decodePoint(data), params); - KeyFactory kf = KeyFactory.getInstance("EC", "BC"); - return kf.generatePublic(pubKey); + + AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); + parameters.init(new ECGenParameterSpec("secp256r1")); + ECParameterSpec params = parameters.getParameterSpec(ECParameterSpec.class); + ECPublicKeySpec pubSpec = new ECPublicKeySpec(getPointFromEncoded(data), params); + KeyFactory kf = KeyFactory.getInstance("EC"); + return (ECPublicKey) kf.generatePublic(pubSpec); } private ECPublicKey getPublicKeyFromPrivate(ECPrivateKey privateKey) throws Exception { - KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC"); + KeyFactory keyFactory = KeyFactory.getInstance("EC"); + + AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); + parameters.init(new ECGenParameterSpec("secp256r1")); + ECParameterSpec params = parameters.getParameterSpec(ECParameterSpec.class); - BigInteger d = privateKey.getD(); org.bouncycastle.jce.spec.ECParameterSpec ecSpec = - privateKey.getParameters(); - ECPoint Q = privateKey.getParameters().getG().multiply(d); + ECNamedCurveTable.getParameterSpec("secp256r1"); + org.bouncycastle.math.ec.ECPoint q = ecSpec.getG().multiply(privateKey.getS()); + ECPublicKeySpec spec = new ECPublicKeySpec(getPointFromEncoded(q.getEncoded(false)), params); + + return (ECPublicKey) keyFactory.generatePublic(spec); + } - org.bouncycastle.jce.spec.ECPublicKeySpec pubSpec = new - org.bouncycastle.jce.spec.ECPublicKeySpec(Q, ecSpec); - return (ECPublicKey) keyFactory.generatePublic(pubSpec); + private static ECPoint getPointFromEncoded(byte[] encoded){ + byte[] rawX = new byte[32]; + byte[] rawY = new byte[32]; + System.arraycopy(encoded,1,rawX, 0,32); + System.arraycopy(encoded,33,rawY, 0,32); + + return new ECPoint(new BigInteger(1,rawX), new BigInteger(1,rawY)); } private byte[] processGetPublicKey() { @@ -139,7 +146,12 @@ private byte[] processGetPublicKey() { ECPublicKey pubKey = getPublicKeyFromPrivate(privKey); byte[] resp = new byte[67]; - System.arraycopy(pubKey.getQ().getEncoded(false), 0, resp, 0, 65); + byte[] x = pubKey.getW().getAffineX().toByteArray(); + byte[] y = pubKey.getW().getAffineY().toByteArray(); + + System.arraycopy(x, 0, resp, 1, 32); + System.arraycopy(y, 0, resp, 33, 32); + resp[0] = 0x04; resp[65] = (byte) 0x90; resp[66] = 0x00; @@ -175,7 +187,7 @@ private byte[] processAuthenticate(byte[] buffer) { private byte[] doECDH(PrivateKey privKey, byte[] pubKey) throws Exception { - KeyAgreement ka = KeyAgreement.getInstance("ECDH", "BC"); + KeyAgreement ka = KeyAgreement.getInstance("ECDH"); ka.init(privKey); ka.doPhase(loadPublicKey(pubKey), true); return ka.generateSecret(); @@ -213,17 +225,6 @@ private byte[] decryptRSA(byte[] ciphertext) throws UnrecoverableKeyException, K return cipher.doFinal(ciphertext); } - private void setupBouncyCastle() { - final Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); - if (provider == null) { - return; - } - if (provider.getClass().equals(BouncyCastleProvider.class)) { - return; - } - Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME); - Security.insertProviderAt(new BouncyCastleProvider(), 1); - } @Override public void onDeactivated(int reason) {