Generate ECDH with SC key pair
This commit is contained in:
parent
48312017ef
commit
5215576c8f
|
@ -173,10 +173,9 @@ dependencies {
|
|||
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
|
||||
implementation 'com.huangyz0918:androidwm-light:0.1.2'
|
||||
|
||||
|
||||
implementation "com.madgag.spongycastle:bctls-jdk15on:1.58.0.0"
|
||||
implementation "com.madgag.spongycastle:prov:1.58.0.0"
|
||||
implementation "com.madgag.spongycastle:bcpkix-jdk15on:1.58.0.0"
|
||||
implementation "com.madgag.spongycastle:bcpg-jdk15on:1.58.0.0"
|
||||
//implementation 'org.bouncycastle:bcprov-jdk15on:1.64'
|
||||
|
||||
implementation 'com.github.UnifiedPush:android-connector:1.0.0'
|
||||
//Flavors
|
||||
|
|
|
@ -48,11 +48,11 @@ public class PostSubscriptionAsyncTask {
|
|||
protected void doInBackground() {
|
||||
new Thread(() -> {
|
||||
apiResponse = new API(contextReference.get(), account.getInstance(), account.getToken()).getPushSubscription();
|
||||
if (apiResponse == null || apiResponse.getPushSubscription() == null) {
|
||||
if (apiResponse == null || apiResponse.getPushSubscription() == null || endpoint.compareTo(apiResponse.getPushSubscription().getEndpoint()) != 0) {
|
||||
apiResponse = new API(contextReference.get(), account.getInstance(), account.getToken()).pushSubscription(endpoint, account);
|
||||
} else if (apiResponse != null && endpoint.compareTo(apiResponse.getPushSubscription().getEndpoint()) != 0) {
|
||||
apiResponse = new API(contextReference.get(), account.getInstance(), account.getToken()).updatePushSubscription(endpoint);
|
||||
}
|
||||
//TODO: remove this line
|
||||
apiResponse = new API(contextReference.get(), account.getInstance(), account.getToken()).pushSubscription(endpoint, account);
|
||||
List<Account> accountList = new ArrayList<>();
|
||||
accountList.add(account);
|
||||
apiResponse.setAccounts(accountList);
|
||||
|
|
|
@ -27,7 +27,7 @@ import android.util.Log;
|
|||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
@ -5790,8 +5790,8 @@ public class API {
|
|||
PushSubscription pushSubscription = null;
|
||||
try {
|
||||
String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/push/subscription"), 10, null, prefKeyOauthTokenT);
|
||||
Log.v(Helper.TAG, "response GET: " + response);
|
||||
pushSubscription = parsePushNotifications(new JSONObject(response));
|
||||
Log.v(Helper.TAG, "response2: " + response);
|
||||
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||
setError(e.getStatusCode(), e);
|
||||
e.printStackTrace();
|
||||
|
@ -5818,14 +5818,21 @@ public class API {
|
|||
boolean notif_status = sharedpreferences.getBoolean(Helper.SET_NOTIF_STATUS, true);
|
||||
boolean notif_poll = sharedpreferences.getBoolean(Helper.SET_NOTIF_POLL, true);
|
||||
|
||||
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
try {
|
||||
endpoint = URLEncoder.encode(endpoint, "UTF-8");
|
||||
} catch (UnsupportedEncodingException ignored) {
|
||||
}
|
||||
params.put("subscription[endpoint]", endpoint);
|
||||
params.put("data[alerts][follow]", String.valueOf(notif_follow));
|
||||
params.put("data[alerts][mention]", String.valueOf(notif_mention));
|
||||
params.put("data[alerts][favourite]", String.valueOf(notif_add));
|
||||
params.put("data[alerts][reblog]", String.valueOf(notif_share));
|
||||
params.put("data[alerts][poll]", String.valueOf(notif_poll));
|
||||
params.put("subscription[endpoint]", endpoint);
|
||||
|
||||
try {
|
||||
|
||||
String response = new HttpsConnection(context, this.instance).put(getAbsoluteUrl("/push/subscription"), 10, params, prefKeyOauthTokenT);
|
||||
pushSubscription = parsePushNotifications(new JSONObject(response));
|
||||
Log.v(Helper.TAG, "response3: " + response);
|
||||
|
@ -5855,23 +5862,56 @@ public class API {
|
|||
boolean notif_poll = sharedpreferences.getBoolean(Helper.SET_NOTIF_POLL, true);
|
||||
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
params.put("data[alerts][follow]", String.valueOf(notif_follow));
|
||||
params.put("data[alerts][mention]", String.valueOf(notif_mention));
|
||||
params.put("data[alerts][favourite]", String.valueOf(notif_add));
|
||||
params.put("data[alerts][reblog]", String.valueOf(notif_share));
|
||||
params.put("data[alerts][poll]", String.valueOf(notif_poll));
|
||||
|
||||
params.put("subscription[endpoint]", endpoint);
|
||||
/*try {
|
||||
endpoint = URLEncoder.encode(endpoint, "UTF-8");
|
||||
} catch (UnsupportedEncodingException ignored) {
|
||||
}*/
|
||||
|
||||
|
||||
ECDH ecdh = ECDH.getInstance();
|
||||
String pubKey = ecdh.getPublicKey(context);
|
||||
byte[] randBytes = new byte[16];
|
||||
new Random().nextBytes(randBytes);
|
||||
String auth = Base64.encodeToString(randBytes, Base64.DEFAULT);
|
||||
params.put("subscription[keys][p256dh]", pubKey);
|
||||
params.put("subscription[keys][auth]", auth);
|
||||
String auth = ECDH.base64Encode(randBytes);
|
||||
|
||||
/*try {
|
||||
pubKey = URLEncoder.encode(pubKey.replaceAll("\n",""), "UTF-8");
|
||||
} catch (UnsupportedEncodingException ignored) {
|
||||
}
|
||||
try {
|
||||
String response = new HttpsConnection(context, this.instance).post(getAbsoluteUrl("/push/subscription"), 10, params, prefKeyOauthTokenT);
|
||||
auth = URLEncoder.encode(auth.replaceAll("\n",""), "UTF-8");
|
||||
} catch (UnsupportedEncodingException ignored) {
|
||||
}*/
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
|
||||
|
||||
try {
|
||||
JSONObject jsonObjectSub = new JSONObject();
|
||||
|
||||
jsonObjectSub.put("endpoint", endpoint);
|
||||
JSONObject jsonObjectkey = new JSONObject();
|
||||
jsonObjectkey.put("p256dh", pubKey);
|
||||
jsonObjectkey.put("auth", auth);
|
||||
jsonObjectSub.put("keys", jsonObjectkey);
|
||||
jsonObject.put("subscription", jsonObjectSub);
|
||||
|
||||
JSONObject jsonObjectdata = new JSONObject();
|
||||
JSONObject jsonObjectarlerts = new JSONObject();
|
||||
jsonObjectarlerts.put("follow", notif_follow);
|
||||
jsonObjectarlerts.put("mention", notif_mention);
|
||||
jsonObjectarlerts.put("favourite", notif_add);
|
||||
jsonObjectarlerts.put("reblog", notif_share);
|
||||
jsonObjectarlerts.put("poll", notif_poll);
|
||||
jsonObjectdata.put("alerts", jsonObjectarlerts);
|
||||
jsonObject.put("data", jsonObjectdata);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Log.v(Helper.TAG, "jsonObject: " + jsonObject);
|
||||
try {
|
||||
String response = new HttpsConnection(context, this.instance).postJson(getAbsoluteUrl("/push/subscription"), 10, jsonObject, prefKeyOauthTokenT);
|
||||
pushSubscription = parsePushNotifications(new JSONObject(response));
|
||||
Log.v(Helper.TAG, "response: " + response);
|
||||
ecdh.saveServerKey(context, account, pushSubscription.getServer_key());
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.content.SharedPreferences;
|
|||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableString;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
|
@ -368,6 +369,7 @@ public class HttpsConnection {
|
|||
postData.append('=');
|
||||
postData.append(param.getValue());
|
||||
}
|
||||
Log.v(Helper.TAG, "postData: " + postData);
|
||||
byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
|
||||
if (proxy != null)
|
||||
httpURLConnection = (HttpsURLConnection) url.openConnection(proxy);
|
||||
|
|
|
@ -8,7 +8,15 @@ import android.util.Log;
|
|||
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.ECPublicKeyParameters;
|
||||
import org.spongycastle.math.ec.ECCurve;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
|
@ -37,14 +45,15 @@ public class ECDH {
|
|||
|
||||
private static final String TAG = ECDH.class.getSimpleName();
|
||||
|
||||
private static final String PROVIDER = "SC";
|
||||
private static final String PROVIDER = org.spongycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;
|
||||
|
||||
private static final String KEGEN_ALG = "ECDH";
|
||||
|
||||
private static ECDH instance;
|
||||
|
||||
static {
|
||||
Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
|
||||
// Security.removeProvider("BC");
|
||||
Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());
|
||||
}
|
||||
|
||||
private final KeyFactory kf;
|
||||
|
@ -68,8 +77,11 @@ public class ECDH {
|
|||
return instance;
|
||||
}
|
||||
|
||||
static String base64Encode(byte[] b) {
|
||||
return Base64.encodeToString(b, Base64.DEFAULT);
|
||||
public static String base64Encode(byte[] b) {
|
||||
|
||||
byte[] encoded = Base64.encode(
|
||||
b, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
|
||||
return new String(encoded);
|
||||
}
|
||||
|
||||
static byte[] base64Decode(String str) {
|
||||
|
@ -78,7 +90,7 @@ public class ECDH {
|
|||
|
||||
synchronized KeyPair generateKeyPair()
|
||||
throws Exception {
|
||||
ECGenParameterSpec ecParamSpec = new ECGenParameterSpec("secp256k1");
|
||||
ECGenParameterSpec ecParamSpec = new ECGenParameterSpec("prime256v1");
|
||||
kpg.initialize(ecParamSpec);
|
||||
|
||||
return kpg.generateKeyPair();
|
||||
|
@ -119,17 +131,29 @@ public class ECDH {
|
|||
KeyPair newPair(Context context) {
|
||||
SharedPreferences.Editor prefsEditor = PreferenceManager
|
||||
.getDefaultSharedPreferences(context).edit();
|
||||
|
||||
KeyPair kp = null;
|
||||
|
||||
KeyPair kp;
|
||||
try {
|
||||
kp = generateKeyPair();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
ECPublicKey key = (ECPublicKey) kp.getPublic();
|
||||
byte[] x = key.getW().getAffineX().toByteArray();
|
||||
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");
|
||||
ECCurve curve = x9.getCurve();
|
||||
ECPoint point = curve.createPoint(xbi, ybi);
|
||||
ECNamedDomainParameters dParams = new ECNamedDomainParameters(oid,
|
||||
x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
|
||||
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(point, dParams);
|
||||
|
||||
prefsEditor.putString(kp_public, base64Encode(kp.getPublic().getEncoded()));
|
||||
String keyString = base64Encode(pubKey.getQ().getEncoded(false));
|
||||
|
||||
prefsEditor.putString(kp_public, keyString);
|
||||
prefsEditor.putString(kp_private, base64Encode(kp.getPrivate().getEncoded()));
|
||||
prefsEditor.commit();
|
||||
return kp;
|
||||
|
@ -142,7 +166,7 @@ public class ECDH {
|
|||
String strPub = prefs.getString(kp_public, "");
|
||||
String strPriv = prefs.getString(kp_private, "");
|
||||
|
||||
if (strPub.isEmpty() || strPriv.isEmpty()) {
|
||||
if (strPub.isEmpty() || strPriv.isEmpty() || 1 == 1) {
|
||||
return newPair(context);
|
||||
}
|
||||
try {
|
||||
|
@ -154,7 +178,11 @@ public class ECDH {
|
|||
}
|
||||
|
||||
public String getPublicKey(Context context) {
|
||||
return base64Encode(getPair(context).getPublic().getEncoded());
|
||||
SharedPreferences prefs = PreferenceManager
|
||||
.getDefaultSharedPreferences(context);
|
||||
|
||||
String strPub = prefs.getString(kp_public, "");
|
||||
return strPub;
|
||||
}
|
||||
|
||||
public void saveServerKey(Context context, Account account, String strPeerPublic) {
|
||||
|
|
Loading…
Reference in New Issue