Support rsa and multipart

pull/149/head
FongMi 3 years ago
parent c57737617a
commit 6f679e3611
  1. 39
      quickjs/src/main/java/com/fongmi/quickjs/method/Global.java
  2. 17
      quickjs/src/main/java/com/fongmi/quickjs/utils/Connect.java
  3. 82
      quickjs/src/main/java/com/fongmi/quickjs/utils/Crypto.java

@ -1,16 +1,16 @@
package com.fongmi.quickjs.method;
import android.util.Base64;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import com.fongmi.quickjs.bean.Req;
import com.fongmi.quickjs.utils.Connect;
import com.fongmi.quickjs.utils.Crypto;
import com.fongmi.quickjs.utils.JSUtil;
import com.fongmi.quickjs.utils.Parser;
import com.fongmi.quickjs.utils.Proxy;
import com.github.catvod.utils.Trans;
import com.orhanobut.logger.Logger;
import com.whl.quickjs.wrapper.JSArray;
import com.whl.quickjs.wrapper.JSFunction;
import com.whl.quickjs.wrapper.JSMethod;
@ -20,15 +20,10 @@ import com.whl.quickjs.wrapper.QuickJSContext;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
@ -105,7 +100,7 @@ public class Global {
public JSObject _http(String url, JSObject options) {
JSFunction complete = options.getJSFunction("complete");
if (complete == null) return req(url, options);
Req req = Req.objectFrom(ctx.stringify(options));
Req req = Req.objectFrom(options.stringify());
Connect.to(url, req).enqueue(getCallback(complete, req));
return null;
}
@ -114,7 +109,7 @@ public class Global {
@JSMethod
public JSObject req(String url, JSObject options) {
try {
Req req = Req.objectFrom(ctx.stringify(options));
Req req = Req.objectFrom(options.stringify());
Response res = Connect.to(url, req).execute();
return Connect.success(ctx, req, res);
} catch (Exception e) {
@ -155,21 +150,17 @@ public class Global {
@Keep
@JSMethod
public String aesX(String mode, boolean encrypt, String input, boolean inBase64, String key, String iv, boolean outBase64) {
try {
byte[] keyBuf = key.getBytes();
if (keyBuf.length < 16) keyBuf = Arrays.copyOf(keyBuf, 16);
byte[] ivBuf = iv == null ? new byte[0] : iv.getBytes();
if (ivBuf.length < 16) ivBuf = Arrays.copyOf(ivBuf, 16);
Cipher cipher = Cipher.getInstance(mode + "Padding");
SecretKeySpec keySpec = new SecretKeySpec(keyBuf, "AES");
if (iv == null) cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, keySpec);
else cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivBuf));
byte[] inBuf = inBase64 ? Base64.decode(input, Base64.DEFAULT) : input.getBytes("UTF-8");
return outBase64 ? Base64.encodeToString(cipher.doFinal(inBuf), Base64.DEFAULT) : new String(cipher.doFinal(inBuf), "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return "";
}
String result = Crypto.aes(mode, encrypt, input, inBase64, key, iv, outBase64);
Logger.t("aesX").d("mode:%s\nencrypt:%s\ninBase64:%s\noutBase64:%s\nkey:%s\niv:%s\ninput:\n%s\nresult:\n%s", mode, encrypt, inBase64, outBase64, key, iv, input, result);
return result;
}
@Keep
@JSMethod
public String rsaX(String mode, boolean pub, boolean encrypt, String input, boolean inBase64, String key, boolean outBase64) {
String result = Crypto.rsa(pub, encrypt, input, inBase64, key, outBase64);
Logger.t("rsaX").d("mode:%s\npub:%s\nencrypt:%s\ninBase64:%s\noutBase64:%s\nkey:\n%s\ninput:\n%s\nresult:\n%s", mode, pub, encrypt, inBase64, outBase64, key, input, result);
return result;
}
private Callback getCallback(JSFunction complete, Req req) {

@ -10,11 +10,13 @@ import com.whl.quickjs.wrapper.QuickJSContext;
import java.util.List;
import java.util.Map;
import java.util.Random;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
@ -63,6 +65,7 @@ public class Connect {
private static RequestBody getPostBody(Req req, String contentType) {
if (req.getData() != null && req.getPostType().equals("json")) return getJsonBody(req);
if (req.getData() != null && req.getPostType().equals("form")) return getFormBody(req);
if (req.getData() != null && req.getPostType().equals("form-data")) return getFormDataBody(req);
if (req.getBody() != null && contentType != null) return RequestBody.create(req.getBody(), MediaType.get(contentType));
return RequestBody.create("", null);
}
@ -72,10 +75,18 @@ public class Connect {
}
private static RequestBody getFormBody(Req req) {
FormBody.Builder formBody = new FormBody.Builder();
FormBody.Builder builder = new FormBody.Builder();
Map<String, String> params = Json.toMap(req.getData());
for (String key : params.keySet()) formBody.add(key, params.get(key));
return formBody.build();
for (String key : params.keySet()) builder.add(key, params.get(key));
return builder.build();
}
private static RequestBody getFormDataBody(Req req) {
String boundary = "--dio-boundary-" + new Random().nextInt(42949) + "" + new Random().nextInt(67296);
MultipartBody.Builder builder = new MultipartBody.Builder(boundary).setType(MultipartBody.FORM);
Map<String, String> params = Json.toMap(req.getData());
for (String key : params.keySet()) builder.addFormDataPart(key, params.get(key));
return builder.build();
}
private static void setHeader(QuickJSContext ctx, Response res, JSObject object) {

@ -0,0 +1,82 @@
package com.fongmi.quickjs.utils;
import android.util.Base64;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Crypto {
public static String aes(String mode, boolean encrypt, String input, boolean inBase64, String key, String iv, boolean outBase64) {
try {
byte[] keyBuf = key.getBytes();
if (keyBuf.length < 16) keyBuf = Arrays.copyOf(keyBuf, 16);
byte[] ivBuf = iv == null ? new byte[0] : iv.getBytes();
if (ivBuf.length < 16) ivBuf = Arrays.copyOf(ivBuf, 16);
Cipher cipher = Cipher.getInstance(mode + "Padding");
SecretKeySpec keySpec = new SecretKeySpec(keyBuf, "AES");
if (iv == null) cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, keySpec);
else cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivBuf));
byte[] inBuf = inBase64 ? Base64.decode(input.replaceAll("_", "/").replaceAll("-", "+"), Base64.DEFAULT) : input.getBytes("UTF-8");
return outBase64 ? Base64.encodeToString(cipher.doFinal(inBuf), Base64.DEFAULT) : new String(cipher.doFinal(inBuf), "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public static String rsa(boolean pub, boolean encrypt, String input, boolean inBase64, String key, boolean outBase64) {
try {
Key rsaKey = generateKey(pub, key);
int len = getModulusLength(rsaKey);
byte[] outBytes = new byte[0];
byte[] inBytes = inBase64 ? Base64.decode(input.replaceAll("_", "/").replaceAll("-", "+"), Base64.DEFAULT) : input.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, rsaKey);
int blockLen = encrypt ? len / 8 - 11 : len / 8;
int bufIdx = 0;
while (bufIdx < inBytes.length) {
int bufEndIdx = Math.min(bufIdx + blockLen, inBytes.length);
byte[] tmpInBytes = new byte[bufEndIdx - bufIdx];
System.arraycopy(inBytes, bufIdx, tmpInBytes, 0, tmpInBytes.length);
byte[] tmpBytes = cipher.doFinal(tmpInBytes);
bufIdx = bufEndIdx;
outBytes = concatArrays(outBytes, tmpBytes);
}
return outBase64 ? Base64.encodeToString(outBytes, Base64.DEFAULT) : new String(outBytes, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
private static Key generateKey(boolean pub, String key) throws Exception {
if (pub) key = key.replaceAll(System.lineSeparator(), "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
else key = key.replaceAll(System.lineSeparator(), "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");
return pub ? KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decode(key, Base64.DEFAULT))) : KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decode(key, Base64.DEFAULT)));
}
private static int getModulusLength(Key key) {
if (key instanceof PublicKey) return ((RSAPublicKey) key).getModulus().bitLength();
else return ((RSAPrivateKey) key).getModulus().bitLength();
}
private static byte[] concatArrays(byte[] a, byte[] b) {
int aLen = a.length;
int bLen = b.length;
byte[] result = new byte[aLen + bLen];
System.arraycopy(a, 0, result, 0, aLen);
System.arraycopy(b, 0, result, aLen, bLen);
return result;
}
}
Loading…
Cancel
Save