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

View File

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