IDA 反编译so文件导出函数地址
Name |
Addres |
Java_com_nice_main_helpers_utils_NiceSignUtils_getSignRequest |
0000000000001D20 |
Java_com_nice_main_helpers_utils_NiceSignUtils_getSignCode |
0000000000001F9C |
app主要代码
package com.nice.main.helpers.utils;
import java.nio.charset.StandardCharsets;
/* loaded from: classes4.dex */
public class NiceSignUtils {
static {
try {
System.loadLibrary("salt");
} catch (Throwable th) {
th.printStackTrace();
}
}
private static boolean a(byte[] bArr) {
return bArr != null && bArr.length > 0;
}
public static synchronized String b(String str, String str2, String str3, String str4) {
// 省略部分代码
if (a(bArr2) && a(bArr) && a(bArr3)) {
String str52 = "";
str52 = getSignRequest(str2, bArr2, bArr, bArr3)[2];
return str52;
}
return "";
}
}
public static String c(String str, String str2, String str3) {
// 省略部分代码
if (!a(bArr) && a(bArr2) && a(bArr3)) {
return getSignCode(bArr, bArr2, bArr3);
}
return "";
}
private static native String getSignCode(byte[] bArr, byte[] bArr2, byte[] bArr3);
private static native String[] getSignRequest(String str, byte[] bArr, byte[] bArr2, byte[] bArr3);
}
unidbg模拟执行
先搭建好架子
package com.nice.sign;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import java.io.File;
public class test extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
test() {
emulator = AndroidEmulatorBuilder.for64Bit().setProcessName("com.nice.main").build(); // 创建模拟器实例
final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析
vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/example_binaries/nice.apk")); // 创建Android虚拟机
vm.setJni(this);
vm.setVerbose(true); // 设置是否打印Jni调用细节
DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/arm64-v8a/libsalt.so"), true);
module = dm.getModule(); //
dm.callJNI_OnLoad(emulator);
}
public static void main(String[] args) {
test TEST = new test();
}
}
构造函数
public String getSignRequest(String str, byte[] bArr, byte[] bArr2, byte[] bArr3) {
List<Object> list = new ArrayList<>();
list.add(vm.getJNIEnv());
list.add(0);
list.add(vm.addLocalObject(new StringObject(vm, str)));
list.add(vm.addLocalObject(new ByteArray(vm, bArr)));
list.add(vm.addLocalObject(new ByteArray(vm, bArr2)));
list.add(vm.addLocalObject(new ByteArray(vm, bArr3)));
Number number = module.callFunction(emulator, 0x1F9C, list.toArray());
DvmObject[] result = (DvmObject[]) vm.getObject(number.intValue()).getValue();
return result[2].getValue().toString();
}
public static void main(String[] args) throws NoSuchAlgorithmException {
niceSign SDK = new niceSign();
byte[] arr = "{\"country\":\"1\",\"mobile\":\"test\",\"password\":\"B7cteuae3Ndw0Ty\\/LNF9deUrY+K3NAu5Fwdekfg0hHctSwyfGx1aRhuNj1SYFUsURcvjtcMc7t4P\\nkT4\\/jMw16KMp8Ib85U2qrJB1jHuiLnrBjTarlFgjeHKUH3r1fh03p7UfEYqjp+CPzAeF41\\/WRxXZ\\n846NrxSswxEybYOC5FU=\\n\",\"platform\":\"mobile\"}".getBytes();
byte[] arr2 = getDid().getBytes();
byte[] arr3 = getRandom().getBytes();
String sign = SDK.getSignRequest(new String(arr), arr, arr2, arr3);
System.out.println("nice sign算法:" + sign);
}
补环境
报错1
java.lang.UnsupportedOperationException: com/nice/main/data/enumerable/User->ach(Ljava/lang/String;)Ljava/lang/String;
at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:432)
at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:421)
at com.github.unidbg.linux.android.dvm.DvmMethod.callStaticObjectMethod(DvmMethod.java:59)
at com.github.unidbg.linux.android.dvm.DalvikVM64$111.handle(DalvikVM64.java:1723)
at com.github.unidbg.linux.ARM64SyscallHandler.hook(ARM64SyscallHandler.java:118)
at com.github.unidbg.arm.backend.UnicornBackend$11.hook(UnicornBackend.java:345)
at unicorn.Unicorn$NewHook.onInterrupt(Unicorn.java:128)
at unicorn.Unicorn.emu_start(Native Method)
at com.github.unidbg.arm.backend.UnicornBackend.emu_start(UnicornBackend.java:376)
at com.github.unidbg.AbstractEmulator.emulate(AbstractEmulator.java:380)
at com.github.unidbg.thread.Function64.run(Function64.java:39)
at com.github.unidbg.thread.MainTask.dispatch(MainTask.java:19)
at com.github.unidbg.thread.UniThreadDispatcher.run(UniThreadDispatcher.java:175)
at com.github.unidbg.thread.UniThreadDispatcher.runMainForResult(UniThreadDispatcher.java:99)
at com.github.unidbg.AbstractEmulator.runMainForResult(AbstractEmulator.java:340)
at com.github.unidbg.arm.AbstractARM64Emulator.eFunc(AbstractARM64Emulator.java:262)
at com.github.unidbg.Module.emulateFunction(Module.java:163)
at com.github.unidbg.linux.LinuxModule.callFunction(LinuxModule.java:262)
at com.nice.sign.niceSign.getSignRequest(niceSign.java:78)
at com.nice.sign.niceSign.main(niceSign.java:158)
通过分析jadx反编译的代码发现这里是一个取随机数的函数
public static String ach(String str) {
Random random = new Random();
StringBuffer stringBuffer = new StringBuffer();
while (stringBuffer.length() < 16) {
stringBuffer.append(Integer.toString(random.nextInt() & Integer.MAX_VALUE, 36));
}
return stringBuffer.substring(0, 16);
}
补环境代码
public static String getRandom() {
Random random = new Random();
StringBuilder strBuffer = new StringBuilder();
while (strBuffer.length() < 16) {
strBuffer.append(Integer.toString(random.nextInt() & Integer.MAX_VALUE, 36));
}
return strBuffer.substring(0, 16);
}
@Override
public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass DvmClass, String signature, VarArg varArg) {
switch (signature) {
case "com/nice/main/data/enumerable/User->ach(Ljava/lang/String;)Ljava/lang/String;":
return new StringObject(vm, getRandom());
}
return super.callStaticObjectMethod(vm, DvmClass, signature, varArg);
}
报错2
java.lang.UnsupportedOperationException: com/nice/main/data/enumerable/Sticker->ach(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:432)
at com.nice.sign.niceSign.callStaticObjectMethod(niceSign.java:145)
at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:421)
at com.github.unidbg.linux.android.dvm.DvmMethod.callStaticObjectMethod(DvmMethod.java:59)
at com.github.unidbg.linux.android.dvm.DalvikVM64$111.handle(DalvikVM64.java:1723)
at com.github.unidbg.linux.ARM64SyscallHandler.hook(ARM64SyscallHandler.java:118)
at com.github.unidbg.arm.backend.UnicornBackend$11.hook(UnicornBackend.java:345)
at unicorn.Unicorn$NewHook.onInterrupt(Unicorn.java:128)
at unicorn.Unicorn.emu_start(Native Method)
at com.github.unidbg.arm.backend.UnicornBackend.emu_start(UnicornBackend.java:376)
at com.github.unidbg.AbstractEmulator.emulate(AbstractEmulator.java:380)
at com.github.unidbg.thread.Function64.run(Function64.java:39)
at com.github.unidbg.thread.MainTask.dispatch(MainTask.java:19)
at com.github.unidbg.thread.UniThreadDispatcher.run(UniThreadDispatcher.java:175)
at com.github.unidbg.thread.UniThreadDispatcher.runMainForResult(UniThreadDispatcher.java:99)
at com.github.unidbg.AbstractEmulator.runMainForResult(AbstractEmulator.java:340)
at com.github.unidbg.arm.AbstractARM64Emulator.eFunc(AbstractARM64Emulator.java:262)
at com.github.unidbg.Module.emulateFunction(Module.java:163)
at com.github.unidbg.linux.LinuxModule.callFunction(LinuxModule.java:262)
at com.nice.sign.niceSign.getSignRequest(niceSign.java:78)
at com.nice.sign.niceSign.main(niceSign.java:167)
这里是拼接字符串操作
public static String ach(String str, String str2, String str3, String str4) {
return NetworkUtils.getNiceURL(str, str2, str3, str4);
}
public static String getNiceURL(String firstpart, String secondpart, String thirdpart, String forthpart) {
return firstpart + secondpart + ":" + thirdpart + "/" + forthpart;
}
补环境代码
public static String getNiceURL(String firstpart, String secondpart, String thirdpart, String forthpart) {
return firstpart + secondpart + ":" + thirdpart + "/" + forthpart;
}
@Override
public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass DvmClass, String signature, VarArg varArg) {
switch (signature) {
case "com/nice/main/data/enumerable/Sticker->ach(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;":
try {
String value = getNiceURL(varArg.getObjectArg(0).getValue().toString(), varArg.getObjectArg(1).getValue().toString(), varArg.getObjectArg(2).getValue().toString(), varArg.getObjectArg(3).getValue().toString());
return new StringObject(vm, value);
} catch (ArithmeticException e) {
return new StringObject(vm, "10086");
}
}
return super.callStaticObjectMethod(vm, DvmClass, signature, varArg);
}
最终补完环境的代码如下(直接Copy的自己的代码 没有按照教程上面的写 基本上都一样的):
package com.nice.sign;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.HookStatus;
import com.github.unidbg.debugger.Debugger;
import com.github.unidbg.hook.HookContext;
import com.github.unidbg.hook.ReplaceCallback;
import com.github.unidbg.hook.hookzz.HookEntryInfo;
import com.github.unidbg.hook.hookzz.HookZz;
import com.github.unidbg.hook.hookzz.HookZzArm64RegisterContext;
import com.github.unidbg.hook.hookzz.WrapCallback;
import com.github.unidbg.hook.xhook.IxHook;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.XHookImpl;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.android.dvm.array.ByteArray;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.utils.Inspector;
import com.sun.jna.Pointer;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
public class SignUtil extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
SignUtil() {
emulator = AndroidEmulatorBuilder.for64Bit().setProcessName("com.nice.main").build(); // 创建模拟器实例
final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析
vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/example_binaries/nice.apk")); // 创建Android虚拟机
vm.setJni(this);
vm.setVerbose(false); // 设置是否打印Jni调用细节
DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/arm64-v8a/libsalt.so"), true);
module = dm.getModule(); //
dm.callJNI_OnLoad(emulator);
}
public static String getRandom() {
Random random = new Random();
StringBuilder strBuffer = new StringBuilder();
while (strBuffer.length() < 16) {
strBuffer.append(Integer.toString(random.nextInt() & Integer.MAX_VALUE, 36));
}
return strBuffer.substring(0, 16);
}
public static String getNiceURL(String firstpart, String secondpart, String thirdpart, String forthpart) {
return firstpart + secondpart + ":" + thirdpart + "/" + forthpart;
}
@Override
public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass DvmClass, String signature, VarArg varArg) {
switch (signature) {
case "com/nice/main/data/enumerable/User->ach(Ljava/lang/String;)Ljava/lang/String;":
return new StringObject(vm, getRandom());
case "com/nice/main/data/enumerable/Sticker->ach(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;":
try {
String value = getNiceURL(varArg.getObjectArg(0).getValue().toString(), varArg.getObjectArg(1).getValue().toString(), varArg.getObjectArg(2).getValue().toString(), varArg.getObjectArg(3).getValue().toString());
return new StringObject(vm, value);
} catch (ArithmeticException e) {
return new StringObject(vm, "10086");
}
}
return super.callStaticObjectMethod(vm, DvmClass, signature, varArg);
}
public static String getDid() throws NoSuchAlgorithmException {
MessageDigest Hash = MessageDigest.getInstance("MD5");
byte[] digest = Hash.digest(getRandom().getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
public String getSignRequest(String str, byte[] bArr, byte[] bArr2, byte[] bArr3) {
List<Object> list = new ArrayList<>();
list.add(vm.getJNIEnv()); // 第一个参数是env
list.add(0); // 第二个参数,实例方法是jobject,静态方法是jclazz,直接填0,一般用不到。
list.add(vm.addLocalObject(new StringObject(vm, str)));
list.add(vm.addLocalObject(new ByteArray(vm, bArr)));
list.add(vm.addLocalObject(new ByteArray(vm, bArr2)));
list.add(vm.addLocalObject(new ByteArray(vm, bArr3)));
Number number = module.callFunction(emulator, 0x1F9C, list.toArray());
DvmObject[] result = (DvmObject[]) vm.getObject(number.intValue()).getValue();
return result[2].getValue().toString();
}
public static void main(String[] args) throws NoSuchAlgorithmException {
SignUtil SDK = new SignUtil();
byte[] arr = "{\"country\":\"1\",\"mobile\":\"test\",\"password\":\"B7cteuae3Ndw0Ty\\/LNF9deUrY+K3NAu5Fwdekfg0hHctSwyfGx1aRhuNj1SYFUsURcvjtcMc7t4P\\nkT4\\/jMw16KMp8Ib85U2qrJB1jHuiLnrBjTarlFgjeHKUH3r1fh03p7UfEYqjp+CPzAeF41\\/WRxXZ\\n846NrxSswxEybYOC5FU=\\n\",\"platform\":\"mobile\"}".getBytes();
byte[] arr2 = getDid().getBytes();
byte[] arr3 = getRandom().getBytes();
String sign = SDK.getSignRequest(new String(arr), arr, arr2, arr3);
System.out.println("nice sign算法:" + sign);
}
}
算法还原
ida静态分析
主要代码其实是在 nice_sign_v3函数中
jobjectArray __fastcall Java_com_nice_main_helpers_utils_NiceSignUtils_getSignRequest(_JNIEnv *a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5)
{
//省略N行
v27 = nice_sign_v3(v16, v20, v11);
v28 = a1->functions->SetObjectArrayElement;
v29 = a1->functions->NewStringUTF(a1, v11);
v28(&a1->functions, v24, 1LL, v29);
free(v16);
free(v20);
v30 = a1->functions->NewStringUTF(a1, v27);
v31 = a1->functions->CallStaticObjectMethod(a1, GenerateSignClass, createSign, v12, v30, v10, a3);
a1->functions->ReleaseStringUTFChars(a1, v10, v11);
a1->functions->DeleteLocalRef(a1, v10);
a1->functions->DeleteLocalRef(a1, v12);
a1->functions->DeleteLocalRef(a1, v30);
a1->functions->SetObjectArrayElement(a1, v24, 2LL, v31);
return v24;
}
nice_sign_v3
char *__fastcall nice_sign_v3(const char *a1, const char *a2, const char *a3)
{
// 省略N行
v70 = *(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
v69 = 0;
*v67 = 0u;
v68 = 0u;
v66 = 0;
v65 = 0u;
*v64 = 0u;
strcpy(v64, a2);
v5 = strlen(v64) >> 1;
if ( v5 >= 1 )
{
v6 = (v5 - 1) + 1LL;
v7 = v5;
if ( v6 < 0x20 )
{
LODWORD(v8) = 0;
v9 = v64;
goto LABEL_11;
}
v8 = v6 & 0x1FFFFFFE0LL;
v9 = v64;
if ( (v6 & 0x1FFFFFFE0LL) == 0 )
{
LABEL_11:
v17 = v5 - v8;
do
{
v18 = *v9;
--v17;
*v9 = v9[v7];
(v9++)[v7] = v18;
}
while ( v17 );
goto LABEL_13;
}
v10 = (v5 - 1);
if ( v64 < &v64[v5 + 1 + v10] && &v64[v5] < &v64[v10 + 1] )
{
LODWORD(v8) = 0;
goto LABEL_11;
}
v9 = &v64[v8];
v11 = v64;
v12 = v6 & 0x1FFFFFFE0LL;
do
{
v13 = &v11[v5];
v14 = *(v13 + 1);
v15 = *v11;
v16 = *(v11 + 1);
v12 -= 32LL;
*v11 = *v13;
*(v11 + 1) = v14;
v11 += 32;
*v13 = v15;
*(v13 + 1) = v16;
}
while ( v12 );
if ( v6 != v8 )
goto LABEL_11;
}
LABEL_13:
v19 = strlen(a1);
v20 = malloc(v19 + 101);
v21 = v20;
if ( !v20 )
return 0LL;
strcpy(v20, a3);
v22 = nice_md5(v64);
strcat(v21, v22);
strcpy(&v21[strlen(v21)], "8a5f746c1c9c99c0b458e1ed510845e5");
v23 = nice_md5(v21);
strcpy(v67, v23);
v24 = strlen(v67) >> 1;
if ( v24 >= 1 )
{
v25 = (v24 - 1) + 1LL;
v26 = v24;
if ( v25 < 0x20 )
{
LODWORD(v27) = 0;
v28 = v67;
goto LABEL_24;
}
v27 = v25 & 0x1FFFFFFE0LL;
v28 = v67;
if ( (v25 & 0x1FFFFFFE0LL) == 0 )
{
LABEL_24:
v36 = v24 - v27;
do
{
v37 = *v28;
--v36;
*v28 = v28[v26];
(v28++)[v26] = v37;
}
while ( v36 );
goto LABEL_26;
}
v29 = (v24 - 1);
if ( v67 < &v67[v24 + 1 + v29] && &v67[v24] < &v67[v29 + 1] )
{
LODWORD(v27) = 0;
goto LABEL_24;
}
v28 = &v67[v27];
v30 = v67;
v31 = v25 & 0x1FFFFFFE0LL;
do
{
v32 = &v30[v24];
v33 = *(v32 + 1);
v34 = *v30;
v35 = *(v30 + 1);
v31 -= 32LL;
*v30 = *v32;
*(v30 + 1) = v33;
v30 += 32;
*v32 = v34;
*(v32 + 1) = v35;
}
while ( v31 );
if ( v25 != v27 )
goto LABEL_24;
}
LABEL_26:
v38 = cJSON_Parse(a1);
v39 = v38;
if ( !v38 )
return 0LL;
v40 = sub_25B0(v38);
cJSON_Delete(v39);
if ( strlen(v40) < 2uLL )
{
v41 = 0LL;
v46 = 32LL;
}
else
{
v41 = 0LL;
v42 = v40 + 1;
v43 = 0x2000000000LL;
do
{
v44 = *(v42 - 1);
v45 = *v42;
v42 += 2;
v21[v41++] = v44 & 0xF0 | v45 & 0xF;
v43 += 0x100000000LL;
}
while ( strlen(v40) >> 1 > v41 );
v46 = v43 >> 32;
}
free(v40);
strncpy(&v21[v41], v67, 0x20u);
v21[v46] = 0;
v48 = nice_sha1(v21);
v47 = byte_1A041;
strncpy(byte_1A041, (v48 + 8), 0x20u);
free(v21);
v49 = strlen(byte_1A041) >> 1;
if ( v49 >= 1 )
{
v50 = (v49 - 1) + 1LL;
v51 = v49;
if ( v50 >= 0x20 )
{
v52 = v50 & 0x1FFFFFFE0LL;
v53 = byte_1A041;
if ( (v50 & 0x1FFFFFFE0LL) != 0 )
{
v54 = (v49 - 1);
if ( &byte_1A041[v49 + 1 + v54] <= byte_1A041 || &byte_1A041[v49] >= &byte_1A041[v54 + 1] )
{
v53 = &byte_1A041[v52];
v55 = byte_1A041;
v56 = v50 & 0x1FFFFFFE0LL;
do
{
v57 = &v55[v49];
v58 = *(v57 + 1);
v59 = *v55;
v60 = *(v55 + 1);
v56 -= 32LL;
*v55 = *v57;
*(v55 + 1) = v58;
v55 += 32;
*v57 = v59;
*(v57 + 1) = v60;
}
while ( v56 );
if ( v50 == v52 )
return byte_1A041;
}
else
{
LODWORD(v52) = 0;
}
}
}
else
{
LODWORD(v52) = 0;
v53 = byte_1A041;
}
v61 = v49 - v52;
v47 = byte_1A041;
do
{
v62 = *v53;
--v61;
*v53 = v53[v51];
(v53++)[v51] = v62;
}
while ( v61 );
}
return v47;
}
执行流程请执行GhatGPT 这里讲一下主要的位置
LABEL_26:
v38 = cJSON_Parse(a1); // JSON解析文本
v39 = v38;
if ( !v38 )
return 0LL;
v40 = sub_25B0(v38); // 将 CJson对象转换成 键值对形式
cJSON_Delete(v39); // 释放Cjson对象
if ( strlen(v40) < 2uLL )
{
v41 = 0LL;
v46 = 32LL;
}
else
{
v41 = 0LL;
v42 = v40 + 1; // 初始化指针v42指向字符串v40的第一个字符
v43 = 0x2000000000LL;
do
{
v44 = *(v42 - 1); //从v42指向的字符串中读取一个字符
v45 = *v42; //从v42指向的字符串中读取下一个字符
v42 += 2; // 指针v42向后移动2个字节
v21[v41++] = v44 & 0xF0 | v45 & 0xF; // 将读取的两个字符转换为一个字节,并存储在数组v21中
v43 += 0x100000000LL; // 增加变量变量的值
}
while ( strlen(v40) >> 1 > v41 ); // 当已经转换的字节数小于字符串长度除以2时继续循环
v46 = v43 >> 32;
}
free(v40);
strncpy(&v21[v41], v67, 0x20u); //字符串拼接
v21[v46] = 0;
v48 = nice_sha1(v21); // 标准的sha1加密
v47 = byte_1A041;
strncpy(byte_1A041, (v48 + 8), 0x20u);
free(v21);
v49 = strlen(byte_1A041) >> 1;
以下是使用JavaScript还原的代码(请自行导入Crypto库)
function Hash_sha1(word) {
return CryptoJS.SHA1(word).toString(CryptoJS.enc.Hex);
}
function Hash_md5(word) {
return CryptoJS.MD5(word).toString(CryptoJS.enc.Hex);
}
function get_random(len) {
let r = Math.random().toString(36).substring(2);
if (r.length < len) {
r += get_random(len - r.length)
}
return r;
}
function get_did() {
return Hash_md5(get_random(16));
}
function Build_NiceSignText(input) {
let output = []
let ptr = input;
let output_index = 4;
while (input.length >> 1 > output_index - 4) {
const c1 = ptr.charCodeAt(0);
const c2 = ptr.charCodeAt(1);
const byte = ((c1 & 0xF0) | (c2 & 0xF));
output[output_index++] = byte;
ptr = ptr.slice(2);
}
return output.map(value => {
return String.fromCharCode(value)
}).join('')
}
function nice_sign_v3(JsonData, did, random) {
let result = {
data: "",
random: random || get_random(),
did: did || get_did()
}
let md5 = [];
md5.push(Hash_md5(result.did.substring(16, 32) + result.did.substring(0, 16)));
md5.push(Hash_md5(result.random + md5[0] + "8a5f746c1c9c99c0b458e1ed510845e5"));
md5[1] = md5[1].substring(16, 32) + md5[1].substring(0, 16)
let obj = JsonData === "" ? {} : typeof JsonData === "string" ? JSON.parse(JsonData) : JsonData
let SignText = Build_NiceSignText(Object.keys(obj).sort().map(value => {
return value + "=" + obj[value];
}).join('&'))
console.log(SignText + md5[1])
let Sign = Hash_sha1(SignText + md5[1])
console.log(Sign.substring(24, 41) ,Sign.substring(8, 24))
result.data = `nice-sign-v1://${Sign.substring(24, 41) + Sign.substring(8, 24)}:${result.random}/${JSON.stringify(obj)}`
return JSON.stringify(result)
}
console.log(nice_sign_v3('{"country":"1","mobile":"888888888","send":"yes","check":"no"}', "",''))