Improvements

This commit is contained in:
Thomas 2021-03-03 14:30:45 +01:00
parent 16ae642243
commit 5930f71fe6
3 changed files with 41 additions and 50 deletions

View File

@ -112,7 +112,6 @@ import app.fedilab.android.sqlite.TimelineCacheDAO;
import static app.fedilab.android.helper.ECDH.kp_private; import static app.fedilab.android.helper.ECDH.kp_private;
import static app.fedilab.android.helper.ECDH.kp_public; import static app.fedilab.android.helper.ECDH.kp_public;
import static app.fedilab.android.helper.ECDH.newPair;
/** /**
@ -5866,7 +5865,7 @@ public class API {
String strPriv = prefs.getString(kp_private, ""); String strPriv = prefs.getString(kp_private, "");
ECDH ecdh = ECDH.getInstance(); ECDH ecdh = ECDH.getInstance();
if (strPub.trim().isEmpty() || strPriv.trim().isEmpty()) { if (strPub.trim().isEmpty() || strPriv.trim().isEmpty()) {
newPair(context); ecdh.newPair(context);
} }
String pubKey = ecdh.getPublicKey(context); String pubKey = ecdh.getPublicKey(context);
byte[] randBytes = new byte[16]; byte[] randBytes = new byte[16];

View File

@ -19,28 +19,21 @@ import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.util.Base64; import android.util.Base64;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1ObjectIdentifier;
import org.spongycastle.asn1.x9.ECNamedCurveTable; import org.spongycastle.asn1.x9.ECNamedCurveTable;
import org.spongycastle.asn1.x9.X9ECParameters; import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.params.ECNamedDomainParameters; import org.spongycastle.crypto.params.ECNamedDomainParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.jce.spec.ECNamedCurveSpec; import org.spongycastle.jce.spec.ECNamedCurveSpec;
import org.spongycastle.jce.spec.ECParameterSpec; import org.spongycastle.jce.spec.ECParameterSpec;
import org.spongycastle.jce.spec.ECPrivateKeySpec; import org.spongycastle.jce.spec.ECPrivateKeySpec;
import org.spongycastle.jce.spec.ECPublicKeySpec; import org.spongycastle.jce.spec.ECPublicKeySpec;
import org.spongycastle.jce.spec.IEKeySpec;
import org.spongycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint; import org.spongycastle.math.ec.ECPoint;
import java.io.ByteArrayInputStream;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
@ -51,20 +44,16 @@ import java.security.PublicKey;
import java.security.Security; import java.security.Security;
import java.security.interfaces.ECPublicKey; import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec; import java.security.spec.ECGenParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.KeyAgreement; import javax.crypto.KeyAgreement;
import javax.crypto.spec.SecretKeySpec;
import app.fedilab.android.client.Entities.Account; import app.fedilab.android.client.Entities.Account;
import app.fedilab.android.sqlite.AccountDAO; import app.fedilab.android.sqlite.AccountDAO;
import app.fedilab.android.sqlite.Sqlite; import app.fedilab.android.sqlite.Sqlite;
// https://github.com/nelenkov/ecdh-kx/blob/master/src/org/nick/ecdhkx/Crypto.java
public class ECDH { public class ECDH {
@ -76,24 +65,26 @@ public class ECDH {
public static final String kp_private = "kp_private"; public static final String kp_private = "kp_private";
public static final String KEGEN_ALG = "ECDH"; public static final String KEGEN_ALG = "ECDH";
public static final String name = "prime256v1";
private static final String kp_public_affine_x = "kp_public_affine_x"; private static final String kp_public_affine_x = "kp_public_affine_x";
private static final String kp_public_affine_y = "kp_public_affine_y"; private static final String kp_public_affine_y = "kp_public_affine_y";
private static ECDH instance; private static ECDH instance;
static { static {
Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider()); Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());
} }
public static KeyFactory kf = null; public final KeyFactory kf;
private static KeyPairGenerator kpg = null; private final KeyPairGenerator kpg;
public ECDH() { public ECDH() {
try { try {
kf = KeyFactory.getInstance(KEGEN_ALG, PROVIDER); kf = KeyFactory.getInstance(KEGEN_ALG, PROVIDER);
kpg = KeyPairGenerator.getInstance(KEGEN_ALG, PROVIDER); kpg = KeyPairGenerator.getInstance(KEGEN_ALG, PROVIDER);
} catch (NoSuchAlgorithmException | NoSuchProviderException e) { } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
e.printStackTrace(); e.printStackTrace();
throw new RuntimeException(e); throw new RuntimeException(e);
@ -104,7 +95,6 @@ public class ECDH {
if (instance == null) { if (instance == null) {
instance = new ECDH(); instance = new ECDH();
} }
return instance; return instance;
} }
@ -119,16 +109,15 @@ public class ECDH {
return Base64.decode(str, Base64.DEFAULT); return Base64.decode(str, Base64.DEFAULT);
} }
static synchronized KeyPair generateKeyPair() synchronized KeyPair generateKeyPair()
throws Exception { throws Exception {
ECGenParameterSpec ecParamSpec = new ECGenParameterSpec("prime256v1"); ECGenParameterSpec ecParamSpec = new ECGenParameterSpec(name);
kpg.initialize(ecParamSpec); kpg.initialize(ecParamSpec);
return kpg.generateKeyPair(); return kpg.generateKeyPair();
} }
private static byte[] generateSecret(PrivateKey myPrivKey, PublicKey otherPubKey) throws Exception { private byte[] generateSecret(PrivateKey myPrivKey, PublicKey otherPubKey) throws Exception {
KeyAgreement keyAgreement = KeyAgreement.getInstance(KEGEN_ALG); KeyAgreement keyAgreement = KeyAgreement.getInstance(KEGEN_ALG);
keyAgreement.init(myPrivKey); keyAgreement.init(myPrivKey);
keyAgreement.doPhase(otherPubKey, true); keyAgreement.doPhase(otherPubKey, true);
@ -137,13 +126,13 @@ public class ECDH {
} }
static synchronized KeyPair readKeyPair(Context context) synchronized KeyPair readKeyPair(Context context)
throws Exception { throws Exception {
return new KeyPair(readMyPublicKey(context), readMyPrivateKey(context)); return new KeyPair(readMyPublicKey(context), readMyPrivateKey(context));
} }
@SuppressLint("ApplySharedPref") @SuppressLint("ApplySharedPref")
public static KeyPair newPair(Context context) { public KeyPair newPair(Context context) {
SharedPreferences.Editor prefsEditor = PreferenceManager SharedPreferences.Editor prefsEditor = PreferenceManager
.getDefaultSharedPreferences(context).edit(); .getDefaultSharedPreferences(context).edit();
KeyPair kp; KeyPair kp;
@ -159,8 +148,8 @@ public class ECDH {
byte[] y = key.getW().getAffineY().toByteArray(); byte[] y = key.getW().getAffineY().toByteArray();
BigInteger xbi = new BigInteger(1, x); BigInteger xbi = new BigInteger(1, x);
BigInteger ybi = new BigInteger(1, y); BigInteger ybi = new BigInteger(1, y);
X9ECParameters x9 = ECNamedCurveTable.getByName("prime256v1"); X9ECParameters x9 = ECNamedCurveTable.getByName(name);
ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID("prime256v1"); ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID(name);
ECCurve curve = x9.getCurve(); ECCurve curve = x9.getCurve();
ECPoint point = curve.createPoint(xbi, ybi); ECPoint point = curve.createPoint(xbi, ybi);
@ -184,10 +173,10 @@ public class ECDH {
} }
static synchronized PublicKey readMyPublicKey(Context context) throws Exception { synchronized PublicKey readMyPublicKey(Context context) throws Exception {
X9ECParameters x9 = ECNamedCurveTable.getByName("prime256v1"); X9ECParameters x9 = ECNamedCurveTable.getByName(name);
ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID("prime256v1"); ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID(name);
SharedPreferences prefs = PreferenceManager SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context); .getDefaultSharedPreferences(context);
@ -198,24 +187,23 @@ public class ECDH {
x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
ECNamedCurveSpec ecNamedCurveSpec = new ECNamedCurveSpec("prime256v1", dParams.getCurve(), dParams.getG(), dParams.getN()); ECNamedCurveSpec ecNamedCurveSpec = new ECNamedCurveSpec(name, dParams.getCurve(), dParams.getG(), dParams.getN());
java.security.spec.ECPoint w = new java.security.spec.ECPoint(xbi, ybi); java.security.spec.ECPoint w = new java.security.spec.ECPoint(xbi, ybi);
return kf.generatePublic(new java.security.spec.ECPublicKeySpec(w, ecNamedCurveSpec)); return kf.generatePublic(new java.security.spec.ECPublicKeySpec(w, ecNamedCurveSpec));
} }
public static String uncryptMessage(Context context, String cyphered, String slug) { public String uncryptMessage(Context context, String cyphered, String slug) {
getInstance(); getInstance();
SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
String[] slugArray = slug.split("@"); String[] slugArray = slug.split("@");
Account account = new AccountDAO(context, db).getUniqAccountUsernameInstance(slugArray[0], slugArray[1]); Account account = new AccountDAO(context, db).getUniqAccountUsernameInstance(slugArray[0], slugArray[1]);
byte[] privateKey = getSharedSecret(context, account); byte[] privateKey = getSharedSecret(context, account);
try { try {
Cipher outCipher = Cipher.getInstance("ECIES", "SC"); Cipher outCipher = Cipher.getInstance("ECIES", PROVIDER);
// outCipher.init(Cipher.DECRYPT_MODE, readPrivateKey(privateKey)); // outCipher.init(Cipher.DECRYPT_MODE, readPrivateKey(privateKey));
outCipher.init(Cipher.DECRYPT_MODE, readPrivateKey(privateKey)); outCipher.init(Cipher.DECRYPT_MODE, readPrivateKey(privateKey));
byte[] plaintext = outCipher.doFinal(Base64.decode(cyphered, Base64.DEFAULT));
byte[] plaintext = outCipher.doFinal(cyphered.getBytes(StandardCharsets.UTF_8));
String finalText = new String(plaintext); String finalText = new String(plaintext);
return finalText; return finalText;
} catch (Exception e) { } catch (Exception e) {
@ -226,9 +214,8 @@ public class ECDH {
} }
public static PublicKey readPublicKey(String keyStr) throws Exception { public PublicKey readPublicKey(String keyStr) throws Exception {
KeyFactory kf = KeyFactory.getInstance("ECDH", new BouncyCastleProvider()); ECParameterSpec parameterSpec = org.spongycastle.jce.ECNamedCurveTable.getParameterSpec(name);
ECParameterSpec parameterSpec = org.spongycastle.jce.ECNamedCurveTable.getParameterSpec("prime256v1");
ECCurve curve = parameterSpec.getCurve(); ECCurve curve = parameterSpec.getCurve();
ECPoint point = curve.decodePoint(base64Decode(keyStr)); ECPoint point = curve.decodePoint(base64Decode(keyStr));
ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, parameterSpec); ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, parameterSpec);
@ -236,33 +223,32 @@ public class ECDH {
} }
public static PrivateKey readPrivateKey(byte[] key) throws Exception { public PrivateKey readPrivateKey(byte[] key) throws Exception {
KeyFactory kf = KeyFactory.getInstance("ECDH", new BouncyCastleProvider()); ECParameterSpec parameterSpec = org.spongycastle.jce.ECNamedCurveTable.getParameterSpec(name);
ECParameterSpec parameterSpec = org.spongycastle.jce.ECNamedCurveTable.getParameterSpec("prime256v1");
ECPrivateKeySpec pubSpec = new ECPrivateKeySpec(new BigInteger(1, key), parameterSpec); ECPrivateKeySpec pubSpec = new ECPrivateKeySpec(new BigInteger(1, key), parameterSpec);
return kf.generatePrivate(pubSpec); return kf.generatePrivate(pubSpec);
} }
static synchronized PrivateKey readMyPrivateKey(Context context) throws Exception { synchronized PrivateKey readMyPrivateKey(Context context) throws Exception {
X9ECParameters x9 = ECNamedCurveTable.getByName("prime256v1"); X9ECParameters x9 = ECNamedCurveTable.getByName(name);
ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID("prime256v1"); ASN1ObjectIdentifier oid = ECNamedCurveTable.getOID(name);
SharedPreferences prefs = PreferenceManager SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context); .getDefaultSharedPreferences(context);
BigInteger ybi = new BigInteger(prefs.getString(kp_public_affine_y, "0")); BigInteger ybi = new BigInteger(prefs.getString(kp_public_affine_y, "0"));
ECNamedDomainParameters dParams = new ECNamedDomainParameters(oid, ECNamedDomainParameters dParams = new ECNamedDomainParameters(oid,
x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed()); x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
ECNamedCurveSpec ecNamedCurveSpec = new ECNamedCurveSpec("prime256v1", dParams.getCurve(), dParams.getG(), dParams.getN()); ECNamedCurveSpec ecNamedCurveSpec = new ECNamedCurveSpec(name, dParams.getCurve(), dParams.getG(), dParams.getN());
return kf.generatePrivate(new java.security.spec.ECPrivateKeySpec(ybi, ecNamedCurveSpec)); return kf.generatePrivate(new java.security.spec.ECPrivateKeySpec(ybi, ecNamedCurveSpec));
} }
private static synchronized KeyPair getPair(Context context) { private synchronized KeyPair getPair(Context context) {
SharedPreferences prefs = PreferenceManager SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context); .getDefaultSharedPreferences(context);
String strPub = prefs.getString(kp_public, ""); String strPub = prefs.getString(kp_public, "");
String strPriv = prefs.getString(kp_private, ""); String strPriv = prefs.getString(kp_private, "");
if (strPub.trim().isEmpty() || strPriv.trim().isEmpty() || 1 == 1) { if (strPub.trim().isEmpty() || strPriv.trim().isEmpty()) {
return newPair(context); return newPair(context);
} }
try { try {
@ -273,7 +259,7 @@ public class ECDH {
return null; return null;
} }
static PublicKey getServerKey(Context context, Account account) throws Exception { PublicKey getServerKey(Context context, Account account) throws Exception {
SharedPreferences prefs = PreferenceManager SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context); .getDefaultSharedPreferences(context);
String serverKey = prefs.getString(peer_public + account.getId() + account.getInstance(), ""); String serverKey = prefs.getString(peer_public + account.getId() + account.getInstance(), "");
@ -281,13 +267,17 @@ public class ECDH {
} }
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})
public static byte[] getSharedSecret(Context context, Account account) { public byte[] getSharedSecret(Context context, Account account) {
try { try {
return generateSecret(getPair(context).getPrivate(), getServerKey(context, account)); KeyPair keyPair = getPair(context);
if (keyPair != null) {
return generateSecret(keyPair.getPrivate(), getServerKey(context, account));
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
return null;
} }
public String getPublicKey(Context context) { public String getPublicKey(Context context) {

View File

@ -23,6 +23,7 @@ import org.unifiedpush.android.connector.MessagingReceiverHandler;
import app.fedilab.android.client.Entities.Account; import app.fedilab.android.client.Entities.Account;
import app.fedilab.android.helper.ECDH;
import app.fedilab.android.helper.NotificationsHelper; import app.fedilab.android.helper.NotificationsHelper;
import app.fedilab.android.helper.PushNotifications; import app.fedilab.android.helper.PushNotifications;
import app.fedilab.android.sqlite.AccountDAO; import app.fedilab.android.sqlite.AccountDAO;
@ -39,7 +40,8 @@ class handler implements MessagingReceiverHandler {
if (context != null) { if (context != null) {
SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
String[] slugArray = slug.split("@"); String[] slugArray = slug.split("@");
//ECDH.uncryptMessage(context, s, slug); ECDH ecdh = ECDH.getInstance();
//ecdh.uncryptMessage(context, s, slug);
Account account = new AccountDAO(context, db).getUniqAccountUsernameInstance(slugArray[0], slugArray[1]); Account account = new AccountDAO(context, db).getUniqAccountUsernameInstance(slugArray[0], slugArray[1]);
NotificationsHelper.task(context, account); NotificationsHelper.task(context, account);
} }