修复在Android 5.1下报错的问题

This commit is contained in:
lyswhut 2023-04-16 01:35:32 +08:00
parent e349044078
commit 14e4d3d624
19 changed files with 750 additions and 922 deletions

View File

@ -11,6 +11,7 @@ import com.facebook.soloader.SoLoader;
import java.util.List; import java.util.List;
import cn.toside.music.mobile.cache.CachePackage; import cn.toside.music.mobile.cache.CachePackage;
import cn.toside.music.mobile.crypto.CryptoPackage;
import cn.toside.music.mobile.gzip.GzipPackage; import cn.toside.music.mobile.gzip.GzipPackage;
import cn.toside.music.mobile.lyric.LyricPackage; import cn.toside.music.mobile.lyric.LyricPackage;
import cn.toside.music.mobile.utils.UtilsPackage; import cn.toside.music.mobile.utils.UtilsPackage;
@ -34,6 +35,7 @@ public class MainApplication extends NavigationApplication {
packages.add(new GzipPackage()); packages.add(new GzipPackage());
packages.add(new LyricPackage()); packages.add(new LyricPackage());
packages.add(new UtilsPackage()); packages.add(new UtilsPackage());
packages.add(new CryptoPackage());
return packages; return packages;
} }

View File

@ -0,0 +1,98 @@
package cn.toside.music.mobile.crypto;
import android.util.Base64;
import java.nio.charset.StandardCharsets;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES {
private static final String AES_MODE_CBC_PKCS7Padding = "AES/CBC/PKCS7Padding";
private static final String AES_MODE_ECB_NoPadding = "AES/ECB/NoPadding";
private static byte[] decodeBase64(String data) {
return Base64.decode(data, Base64.DEFAULT);
}
private static String encodeBase64(byte[] data) {
return new String(Base64.encode(data, Base64.NO_WRAP), StandardCharsets.UTF_8);
}
public static String encrypt(byte[] data, byte[] key, byte[] iv, String mode) {
String encryptedBase64 = "";
try {
Cipher cipher = Cipher.getInstance(mode);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
byte[] finalIvs = new byte[16];
int len = Math.min(iv.length, 16);
System.arraycopy(iv, 0, finalIvs, 0, len);
IvParameterSpec ivps = new IvParameterSpec(finalIvs);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivps);
encryptedBase64 = encodeBase64(cipher.doFinal(data));
} catch (Exception e) {
e.printStackTrace();
}
return encryptedBase64;
}
public static String encrypt(byte[] data, byte[] key, String mode) {
String encryptedBase64 = "";
try {
Cipher cipher = Cipher.getInstance(mode);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
encryptedBase64 = encodeBase64(cipher.doFinal(data));
} catch (Exception e) {
e.printStackTrace();
}
return encryptedBase64;
}
public static String encrypt(String data, String key, String iv, String mode) {
return "".equals(iv) ? encrypt(decodeBase64(data), decodeBase64(key), mode)
: encrypt(decodeBase64(data), decodeBase64(key), decodeBase64(iv), mode);
}
public static String decrypt(byte[] data, byte[] key, byte[] iv, String mode) {
String decryptedString = "";
try {
Cipher cipher = Cipher.getInstance(mode);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
byte[] finalIvs = new byte[16];
int len = Math.min(iv.length, 16);
System.arraycopy(iv, 0, finalIvs, 0, len);
IvParameterSpec ivps = new IvParameterSpec(finalIvs);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivps);
decryptedString = new String(cipher.doFinal(data), StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedString;
}
public static String decrypt(byte[] data, byte[] key, String mode) {
String decryptedString = "";
try {
Cipher cipher = Cipher.getInstance(mode);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
decryptedString = new String(cipher.doFinal(data), StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedString;
}
public static String decrypt(String data, String key, String iv, String mode) {
return "".equals(iv) ? decrypt(decodeBase64(data), decodeBase64(key), mode)
: decrypt(decodeBase64(data), decodeBase64(key), decodeBase64(iv), mode);
}
}

View File

@ -0,0 +1,141 @@
package cn.toside.music.mobile.crypto;
import android.util.Base64;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
public class CryptoModule extends ReactContextBaseJavaModule {
private final ReactApplicationContext reactContext;
CryptoModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public String getName() {
return "CryptoModule";
}
@ReactMethod
public void generateRsaKey(Promise promise) {
KeyPair kp = RSA.getKeyPair();
String publicKeyBytesBase64 = new String(Base64.encode(kp.getPublic().getEncoded(), Base64.DEFAULT));
KeyFactory keyFac;
try {
keyFac = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
promise.reject("-1", e.toString());
return;
}
KeySpec keySpec = new PKCS8EncodedKeySpec(kp.getPrivate().getEncoded());
Key key;
try {
key = keyFac.generatePrivate(keySpec);
} catch (InvalidKeySpecException e) {
promise.reject("-1", e.toString());
return;
}
String privateKeyBytesBase64 = new String(Base64.encode(key.getEncoded(), Base64.DEFAULT));
WritableMap params = Arguments.createMap();
params.putString("publicKey", publicKeyBytesBase64);
params.putString("privateKey", privateKeyBytesBase64);
promise.resolve(params);
}
@ReactMethod
public void rsaEncrypt(String text, String key, String padding, Promise promise) {
promise.resolve(RSA.encryptRSAToString(text, key, padding));
// TaskRunner taskRunner = new TaskRunner();
// try {
// taskRunner.executeAsync(new GzipModule.UnGzip(source, target, force), (String errMessage) -> {
// if ("".equals(errMessage)) {
// promise.resolve(null);
// } else promise.reject("-2", errMessage);
// });
// } catch (RuntimeException err) {
// promise.reject("-2", err.getMessage());
// }
}
@ReactMethod
public void rsaDecrypt(String text, String key, String padding, Promise promise) {
promise.resolve(RSA.decryptRSAToString(text, key, padding));
// TaskRunner taskRunner = new TaskRunner();
// try {
// taskRunner.executeAsync(new GzipModule.UnGzip(source, target, force), (String errMessage) -> {
// if ("".equals(errMessage)) {
// promise.resolve(null);
// } else promise.reject("-2", errMessage);
// });
// } catch (RuntimeException err) {
// promise.reject("-2", err.getMessage());
// }
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String rsaEncryptSync(String text, String key, String padding) {
return RSA.encryptRSAToString(text, key, padding);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String rsaDecryptSync(String text, String key, String padding) {
return RSA.decryptRSAToString(text, key, padding);
}
@ReactMethod
public void aesEncrypt(String text, String key, String iv, String mode, Promise promise) {
promise.resolve(AES.encrypt(text, key, iv, mode));
// TaskRunner taskRunner = new TaskRunner();
// try {
// taskRunner.executeAsync(new GzipModule.UnGzip(source, target, force), (String errMessage) -> {
// if ("".equals(errMessage)) {
// promise.resolve(null);
// } else promise.reject("-2", errMessage);
// });
// } catch (RuntimeException err) {
// promise.reject("-2", err.getMessage());
// }
}
@ReactMethod
public void aesDecrypt(String text, String key, String iv, String mode, Promise promise) {
promise.resolve(AES.decrypt(text, key, iv, mode));
// TaskRunner taskRunner = new TaskRunner();
// try {
// taskRunner.executeAsync(new GzipModule.UnGzip(source, target, force), (String errMessage) -> {
// if ("".equals(errMessage)) {
// promise.resolve(null);
// } else promise.reject("-2", errMessage);
// });
// } catch (RuntimeException err) {
// promise.reject("-2", err.getMessage());
// }
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String aesEncryptSync(String text, String key, String iv, String mode) {
return AES.encrypt(text, key, iv, mode);
}
@ReactMethod(isBlockingSynchronousMethod = true)
public String aesDecryptSync(String text, String key, String iv, String mode) {
return AES.decrypt(text, key, iv, mode);
}
}

View File

@ -0,0 +1,23 @@
package cn.toside.music.mobile.crypto;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class CryptoPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(new CryptoModule(reactContext));
}
}

View File

@ -0,0 +1,113 @@
package cn.toside.music.mobile.crypto;
import android.util.Base64;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
public class RSA {
static final String PADDING_OAEPWithSHA1AndMGF1Padding = "RSA/ECB/OAEPWithSHA1AndMGF1Padding";
static final String PADDING_NoPadding = "RSA/ECB/NoPadding";
// https://stackoverflow.com/a/40978042
// public void testEncryptData(String dataToEncrypt) throws NoSuchAlgorithmException, InvalidKeySpecException {
// // generate a new public/private key pair to test with (note. you should only do this once and keep them!)
// KeyPair kp = getKeyPair();
//
// PublicKey publicKey = kp.getPublic();
// byte[] publicKeyBytes = publicKey.getEncoded();
// String publicKeyBytesBase64 = new String(Base64.encode(publicKeyBytes, Base64.DEFAULT));
// Log.d("RSATest", "publicKeyBytesBase64: " + publicKeyBytesBase64);
//
// PrivateKey privateKey = kp.getPrivate();
// KeyFactory keyFac = KeyFactory.getInstance("RSA");
// KeySpec keySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
// Key key = keyFac.generatePrivate(keySpec);
//
// StringBuilder sb = new StringBuilder();
// sb.append("-----BEGIN PRIVATE KEY-----");
// sb.append(new String(Base64.encode(key.getEncoded(), Base64.DEFAULT)));
// sb.append("-----END PRIVATE KEY-----");
// Log.d("RSATest", "privateKeyBytesBase64: " + sb);
//
// // return new String(Base64.encode(sb.toString().getBytes()));
//
// byte[] privateKeyBytes = privateKey.getEncoded();
// String privateKeyBytesBase64 = new String(Base64.encode(privateKeyBytes, Base64.DEFAULT));
// Log.d("RSATest", "privateKeyBytesBase64: " + privateKeyBytesBase64);
//
// // test encryption
// String encrypted = encryptRSAToString(dataToEncrypt, publicKeyBytesBase64);
//
// Log.d("RSATest", "encrypted: " + encrypted);
//
// // test decryption
// String decrypted = decryptRSAToString(encrypted, privateKeyBytesBase64);
//
// Log.d("RSATest", "decrypted: " + decrypted);
// }
public static KeyPair getKeyPair() {
KeyPair kp = null;
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
kp = kpg.generateKeyPair();
} catch (Exception e) {
e.printStackTrace();
}
return kp;
}
public static String encryptRSAToString(String decryptedBase64, String publicKey, String padding) {
String encryptedBase64 = "";
try {
KeyFactory keyFac = KeyFactory.getInstance("RSA");
KeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKey.trim().getBytes(), Base64.DEFAULT));
Key key = keyFac.generatePublic(keySpec);
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(padding);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(Base64.decode(decryptedBase64, Base64.DEFAULT));
encryptedBase64 = new String(Base64.encode(encryptedBytes, Base64.NO_WRAP));
} catch (Exception e) {
e.printStackTrace();
}
return encryptedBase64;
}
public static String decryptRSAToString(String encryptedBase64, String privateKey, String padding) {
String decryptedString = "";
try {
KeyFactory keyFac = KeyFactory.getInstance("RSA");
KeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey.trim().getBytes(), Base64.DEFAULT));
Key key = keyFac.generatePrivate(keySpec);
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(padding);
// encrypt the plain text using the public key
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptedBytes = Base64.decode(encryptedBase64, Base64.DEFAULT);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
decryptedString = new String(decryptedBytes);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedString;
}
}

View File

@ -16,8 +16,8 @@ module.exports = {
}, },
resolver: { resolver: {
extraNodeModules: { extraNodeModules: {
crypto: require.resolve('react-native-quick-crypto'), // crypto: require.resolve('react-native-quick-crypto'),
stream: require.resolve('stream-browserify'), // stream: require.resolve('stream-browserify'),
buffer: require.resolve('@craftzdog/react-native-buffer'), buffer: require.resolve('@craftzdog/react-native-buffer'),
}, },
}, },

852
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,6 @@
"react-native-navigation": "^7.32.1", "react-native-navigation": "^7.32.1",
"react-native-pager-view": "^6.2.0", "react-native-pager-view": "^6.2.0",
"react-native-quick-base64": "^2.0.5", "react-native-quick-base64": "^2.0.5",
"react-native-quick-crypto": "github:lyswhut/react-native-quick-crypto#b4ea59238ded4fe9cd4d252a838ddfcb7bcd19d8",
"react-native-quick-md5": "^3.0.4", "react-native-quick-md5": "^3.0.4",
"react-native-track-player": "github:lyswhut/react-native-track-player#879d3dc6b7ad41f736943d7495be0ba87b4cf050", "react-native-track-player": "github:lyswhut/react-native-track-player#879d3dc6b7ad41f736943d7495be0ba87b4cf050",
"react-native-vector-icons": "^9.2.0" "react-native-vector-icons": "^9.2.0"

View File

@ -8,6 +8,7 @@
- 修复在线列表的多选问题 - 修复在线列表的多选问题
- 修复mg搜索不显示时长的问题@Folltoshe - 修复mg搜索不显示时长的问题@Folltoshe
- 修复mg评论加载失败的问题@Folltoshe - 修复mg评论加载失败的问题@Folltoshe
- 修复在Android 5.1下报错的问题
### 其他 ### 其他

View File

@ -36,6 +36,8 @@ const handleInit = async() => {
initNavigation(async() => { initNavigation(async() => {
await handleInit() await handleInit()
if (!isInited) return if (!isInited) return
// import('@/utils/nativeModules/cryptoTest')
await navigations.pushHomeScreen().then(() => { await navigations.pushHomeScreen().then(() => {
handlePushedHomeScreen() handlePushedHomeScreen()
}).catch((err: any) => { }).catch((err: any) => {

View File

@ -11,8 +11,8 @@ import musicSdk from '@/utils/musicSdk'
*/ */
export const setListDetailInfo = (id: string) => { export const setListDetailInfo = (id: string) => {
clearListDetail() clearListDetail()
const [source, bangId] = id.split('__') as [LX.OnlineSource, string] const [source] = id.split('__') as [LX.OnlineSource, string]
leaderboardActions.setListDetailInfo(source, bangId) leaderboardActions.setListDetailInfo(source, id)
} }
export const setListDetail = (result: ListDetailInfo, id: string, page: number) => { export const setListDetail = (result: ListDetailInfo, id: string, page: number) => {
return leaderboardActions.setListDetail(result, id, page) return leaderboardActions.setListDetail(result, id, page)

View File

@ -1,4 +1,4 @@
import { generateKeyPair } from 'crypto' // import { generateKeyPair } from 'crypto'
import BackgroundTimer from 'react-native-background-timer' import BackgroundTimer from 'react-native-background-timer'
export const request = async(url: string, { timeout = 10000, ...options }: RequestInit & { timeout?: number } = {}) => { export const request = async(url: string, { timeout = 10000, ...options }: RequestInit & { timeout?: number } = {}) => {
@ -37,34 +37,35 @@ export const request = async(url: string, { timeout = 10000, ...options }: Reque
// return Buffer.concat([decipher.update(Buffer.from(text, 'base64')), decipher.final()]).toString() // return Buffer.concat([decipher.update(Buffer.from(text, 'base64')), decipher.final()]).toString()
// } // }
export const generateRsaKey = async() => new Promise<{ publicKey: string, privateKey: string }>((resolve, reject) => { export { generateRsaKey } from '@/utils/nativeModules/crypto'
generateKeyPair( // export const generateRsaKey = async() => new Promise<{ publicKey: string, privateKey: string }>((resolve, reject) => {
'rsa', // generateKeyPair(
{ // 'rsa',
modulusLength: 2048, // It holds a number. It is the key size in bits and is applicable for RSA, and DSA algorithm only. // {
publicKeyEncoding: { // modulusLength: 2048, // It holds a number. It is the key size in bits and is applicable for RSA, and DSA algorithm only.
type: 'spki', // Note the type is pkcs1 not spki // publicKeyEncoding: {
format: 'pem', // type: 'spki', // Note the type is pkcs1 not spki
}, // format: 'pem',
privateKeyEncoding: { // },
type: 'pkcs8', // Note again the type is set to pkcs1 // privateKeyEncoding: {
format: 'pem', // type: 'pkcs8', // Note again the type is set to pkcs1
// cipher: "aes-256-cbc", //Optional // format: 'pem',
// passphrase: "", //Optional // // cipher: "aes-256-cbc", //Optional
}, // // passphrase: "", //Optional
}, // },
(err, publicKey, privateKey) => { // },
if (err) { // (err, publicKey, privateKey) => {
reject(err) // if (err) {
return // reject(err)
} // return
resolve({ // }
publicKey, // resolve({
privateKey, // publicKey,
}) // privateKey,
}, // })
) // },
}) // )
// })
export const encryptMsg = (keyInfo: LX.Sync.KeyInfo, msg: string): string => { export const encryptMsg = (keyInfo: LX.Sync.KeyInfo, msg: string): string => {

View File

@ -1,24 +1,30 @@
import { createCipheriv, createDecipheriv, publicEncrypt, privateDecrypt, constants } from 'crypto' // import { createCipheriv, createDecipheriv, publicEncrypt, privateDecrypt, constants } from 'crypto'
import { aesEncryptSync, aesDecryptSync, rsaEncryptSync, rsaDecryptSync, AES_MODE, RSA_PADDING } from '@/utils/nativeModules/crypto'
import { btoa } from 'react-native-quick-base64'
import { LIST_IDS } from '@/config/constant' import { LIST_IDS } from '@/config/constant'
import { getListMusics } from '@/core/list' import { getListMusics } from '@/core/list'
import { userLists } from '@/utils/listManage' import { userLists } from '@/utils/listManage'
export const aesEncrypt = (text: string, key: string) => { export const aesEncrypt = (text: string, b64Key: string) => {
const cipher = createCipheriv('aes-128-ecb', Buffer.from(key, 'base64'), '') // const cipher = createCipheriv('aes-128-ecb', Buffer.from(key, 'base64'), '')
return Buffer.concat([cipher.update(Buffer.from(text)), cipher.final()]).toString('base64') // return Buffer.concat([cipher.update(Buffer.from(text)), cipher.final()]).toString('base64')
return aesEncryptSync(btoa(text), b64Key, '', AES_MODE.ECB_128_NoPadding)
} }
export const aesDecrypt = (text: string, key: string) => { export const aesDecrypt = (text: string, b64Key: string) => {
const decipher = createDecipheriv('aes-128-ecb', Buffer.from(key, 'base64'), '') // const decipher = createDecipheriv('aes-128-ecb', Buffer.from(key, 'base64'), '')
return Buffer.concat([decipher.update(Buffer.from(text, 'base64')), decipher.final()]).toString() // return Buffer.concat([decipher.update(Buffer.from(text, 'base64')), decipher.final()]).toString()
return aesDecryptSync(btoa(text), b64Key, '', AES_MODE.ECB_128_NoPadding)
} }
export const rsaEncrypt = (buffer: Buffer, key: string): string => { export const rsaEncrypt = (buffer: Buffer, key: string): string => {
return publicEncrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer).toString('base64') // return publicEncrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer).toString('base64')
return rsaEncryptSync(buffer.toString('base64'), key, RSA_PADDING.OAEPWithSHA1AndMGF1Padding)
} }
export const rsaDecrypt = (buffer: Buffer, key: string): Buffer => { export const rsaDecrypt = (buffer: Buffer, key: string): string => {
return privateDecrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer) // return privateDecrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer)
return rsaDecryptSync(buffer.toString('base64'), key, RSA_PADDING.OAEPWithSHA1AndMGF1Padding)
} }
export const getLocalListData = async(): Promise<LX.Sync.ListData> => { export const getLocalListData = async(): Promise<LX.Sync.ListData> => {

View File

@ -1,5 +1,5 @@
declare module 'crypto' { // declare module 'crypto' {
import crypto from 'react-native-quick-crypto' // import crypto from 'react-native-quick-crypto'
export default crypto // export default crypto
} // }

View File

@ -1,4 +1,4 @@
import crypto from 'crypto' import { stringMd5 } from 'react-native-quick-md5'
/** /**
* 获取音乐音质 * 获取音乐音质
@ -18,4 +18,4 @@ export const getMusicType = (info, type) => {
return '128k' return '128k'
} }
export const toMD5 = str => crypto.createHash('md5').update(str).digest('hex') export const toMD5 = str => stringMd5(str)

View File

@ -1,40 +1,46 @@
// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/util/crypto.js // https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/util/crypto.js
import { createCipheriv, createDecipheriv, publicEncrypt, randomBytes, createHash } from 'crypto' import { btoa } from 'react-native-quick-base64'
const iv = Buffer.from('0102030405060708') import { aesEncryptSync, aesDecryptSync, rsaEncryptSync, AES_MODE, RSA_PADDING } from '@/utils/nativeModules/crypto'
const presetKey = Buffer.from('0CoJUm6Qyw8W8jud') import { toMD5 } from '../../utils'
const linuxapiKey = Buffer.from('rFgB&h#%2?^eDg:Q') const iv = btoa('0102030405060708')
const base62 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' const presetKey = btoa('0CoJUm6Qyw8W8jud')
const linuxapiKey = btoa('rFgB&h#%2?^eDg:Q')
// const base62 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const publicKey = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9SdB1Ua44oncaTWz7OBGLbCiK45wIDAQAB\n-----END PUBLIC KEY-----' const publicKey = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9SdB1Ua44oncaTWz7OBGLbCiK45wIDAQAB\n-----END PUBLIC KEY-----'
const eapiKey = 'e82ckenh8dichen8' const eapiKey = btoa('e82ckenh8dichen8')
const aesEncrypt = (buffer, mode, key, iv) => {
const cipher = createCipheriv(mode, key, iv) const aesEncrypt = (b64, mode, key, iv) => {
return Buffer.concat([cipher.update(buffer), cipher.final()]) // console.log(b64, mode, key, iv)
// const cipher = createCipheriv(mode, key, iv)
// return Buffer.concat([cipher.update(buffer), cipher.final()])
return aesEncryptSync(b64, key, iv, mode)
} }
const aesDecrypt = function(cipherBuffer, mode, key, iv) { const aesDecrypt = (b64, mode, key, iv) => {
let decipher = createDecipheriv(mode, key, iv) // let decipher = createDecipheriv(mode, key, iv)
return Buffer.concat([decipher.update(cipherBuffer), decipher.final()]) // return Buffer.concat([decipher.update(b64), decipher.final()])
return aesDecryptSync(b64, key, iv, mode)
} }
const rsaEncrypt = (buffer, key) => { const rsaEncrypt = (buffer, key) => {
buffer = Buffer.concat([Buffer.alloc(128 - buffer.length), buffer]) buffer = Buffer.concat([Buffer.alloc(128 - buffer.length), buffer])
return publicEncrypt({ key, padding: 3 }, buffer) return Buffer.from(rsaEncryptSync(buffer.toString('base64'), key, RSA_PADDING.NoPadding), 'base64')
} }
export const weapi = object => { export const weapi = object => {
const text = JSON.stringify(object) const text = JSON.stringify(object)
const secretKey = randomBytes(16).map(n => (base62.charAt(n % 62).charCodeAt())) const secretKey = String(Math.random()).substring(2, 18)
return { return {
params: aesEncrypt(Buffer.from(aesEncrypt(Buffer.from(text), 'aes-128-cbc', presetKey, iv).toString('base64')), 'aes-128-cbc', secretKey, iv).toString('base64'), params: aesEncrypt(btoa(aesEncrypt(btoa(text), AES_MODE.CBC_128_PKCS7Padding, presetKey, iv)), AES_MODE.CBC_128_PKCS7Padding, btoa(secretKey), iv),
encSecKey: rsaEncrypt(secretKey.reverse(), publicKey).toString('hex'), encSecKey: rsaEncrypt(Buffer.from(secretKey).reverse(), publicKey).toString('hex'),
} }
} }
export const linuxapi = object => { export const linuxapi = object => {
const text = JSON.stringify(object) const text = JSON.stringify(object)
return { return {
eparams: aesEncrypt(Buffer.from(text), 'aes-128-ecb', linuxapiKey, '').toString('hex').toUpperCase(), eparams: Buffer.from(aesEncrypt(btoa(text), AES_MODE.ECB_128_NoPadding, linuxapiKey, ''), 'base64').toString('hex').toUpperCase(),
} }
} }
@ -42,13 +48,13 @@ export const linuxapi = object => {
export const eapi = (url, object) => { export const eapi = (url, object) => {
const text = typeof object === 'object' ? JSON.stringify(object) : object const text = typeof object === 'object' ? JSON.stringify(object) : object
const message = `nobody${url}use${text}md5forencrypt` const message = `nobody${url}use${text}md5forencrypt`
const digest = createHash('md5').update(message).digest('hex') const digest = toMD5(message)
const data = `${url}-36cd479b6b5-${text}-36cd479b6b5-${digest}` const data = `${url}-36cd479b6b5-${text}-36cd479b6b5-${digest}`
return { return {
params: aesEncrypt(Buffer.from(data), 'aes-128-ecb', eapiKey, '').toString('hex').toUpperCase(), params: Buffer.from(aesEncrypt(Buffer.from(data).toString('base64'), AES_MODE.ECB_128_NoPadding, eapiKey, ''), 'base64').toString('hex').toUpperCase(),
} }
} }
export const eapiDecrypt = cipherBuffer => { export const eapiDecrypt = cipherBuffer => {
return aesDecrypt(cipherBuffer, 'aes-128-ecb', eapiKey, '').toString() return aesDecrypt(cipherBuffer, AES_MODE.ECB_128_NoPadding, eapiKey, '').toString()
} }

View File

@ -0,0 +1,87 @@
import { NativeModules } from 'react-native'
const { CryptoModule } = NativeModules
// export const testRsa = (text: string, key: string) => {
// // console.log(sourceFilePath, targetFilePath)
// return CryptoModule.testRsa()
// }
enum KEY_PREFIX {
publicKeyStart = '-----BEGIN PUBLIC KEY-----',
publicKeyEnd = '-----END PUBLIC KEY-----',
privateKeyStart = '-----BEGIN PRIVATE KEY-----',
privateKeyEnd = '-----END PRIVATE KEY-----',
}
export enum RSA_PADDING {
OAEPWithSHA1AndMGF1Padding = 'RSA/ECB/OAEPWithSHA1AndMGF1Padding',
NoPadding = 'RSA/ECB/NoPadding',
}
export enum AES_MODE {
CBC_128_PKCS7Padding = 'AES/CBC/PKCS7Padding',
ECB_128_NoPadding = 'AES',
}
export const generateRsaKey = async() => {
// console.log(sourceFilePath, targetFilePath)
const key = await CryptoModule.generateRsaKey() as { publicKey: string, privateKey: string }
return {
publicKey: `${KEY_PREFIX.publicKeyStart}\n${key.publicKey}${KEY_PREFIX.publicKeyEnd}`,
privateKey: `${KEY_PREFIX.privateKeyStart}\n${key.privateKey}${KEY_PREFIX.privateKeyEnd}`,
}
}
export const rsaEncrypt = async(text: string, key: string, padding: RSA_PADDING): Promise<string> => {
// console.log(sourceFilePath, targetFilePath)
return CryptoModule.rsaEncrypt(text, key
.replace(KEY_PREFIX.publicKeyStart, '')
.replace(KEY_PREFIX.publicKeyEnd, ''),
padding)
}
export const rsaDecrypt = async(text: string, key: string, padding: RSA_PADDING): Promise<string> => {
// console.log(sourceFilePath, targetFilePath)
return CryptoModule.rsaDecrypt(text, key
.replace(KEY_PREFIX.privateKeyStart, '')
.replace(KEY_PREFIX.privateKeyEnd, ''),
padding)
}
export const rsaEncryptSync = (text: string, key: string, padding: RSA_PADDING): string => {
// console.log(sourceFilePath, targetFilePath)
return CryptoModule.rsaEncryptSync(text, key
.replace(KEY_PREFIX.publicKeyStart, '')
.replace(KEY_PREFIX.publicKeyEnd, ''),
padding)
}
export const rsaDecryptSync = (text: string, key: string, padding: RSA_PADDING): string => {
// console.log(sourceFilePath, targetFilePath)
return CryptoModule.rsaDecryptSync(text, key
.replace(KEY_PREFIX.privateKeyStart, '')
.replace(KEY_PREFIX.privateKeyEnd, ''),
padding)
}
export const aesEncrypt = async(text: string, key: string, vi: string, mode: AES_MODE): Promise<string> => {
// console.log(sourceFilePath, targetFilePath)
return CryptoModule.aesEncrypt(text, key, vi, mode)
}
export const aesDecrypt = async(text: string, key: string, vi: string, mode: AES_MODE): Promise<string> => {
// console.log(sourceFilePath, targetFilePath)
return CryptoModule.aesDecrypt(text, key, vi, mode)
}
export const aesEncryptSync = (text: string, key: string, vi: string, mode: AES_MODE): string => {
// console.log(sourceFilePath, targetFilePath)
return CryptoModule.aesEncryptSync(text, key, vi, mode)
}
export const aesDecryptSync = (text: string, key: string, vi: string, mode: AES_MODE): string => {
// console.log(sourceFilePath, targetFilePath)
return CryptoModule.aesDecryptSync(text, key, vi, mode)
}

View File

@ -0,0 +1,75 @@
import {
rsaEncrypt,
rsaDecrypt,
RSA_PADDING,
generateRsaKey,
AES_MODE,
aesEncrypt,
aesDecrypt,
} from '@/utils/nativeModules/crypto'
const publicKey = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4U2m4fBhTkQOOeAlEusFCDa28UI3xZqv
5EGiOZCJ2bH1LfBjwG5dL3Zk2vT6XLaAn7vyXwVYNmdDn4Fa3l8fZndCty1aUAkpxZehZVy/0I+z
Q7QwSvzQpv2yHPQ76Kcuc3E7VEMSPZkx71dQpsDBtE/F04TW6zOxomFcbqUA97QsjNwU8KKSKKJR
2FhjEX0WhJpvDrkAKQBEujwf3pQDa8iUuF4F0v+oCKiSEf6tuWYx5iBpOvXUmZDLPeBnVZuvJM0e
2yXaIYeZorDaosIvCEqVcDPT3gvePZp6eTyffRJmqk7OkyG2epWM1XPXynu85BYK91pZ03YRNBrp
OkdU7wIDAQAB
-----END PUBLIC KEY-----
`
const privateKey = `
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDhTabh8GFORA454CUS6wUINrbx
QjfFmq/kQaI5kInZsfUt8GPAbl0vdmTa9PpctoCfu/JfBVg2Z0OfgVreXx9md0K3LVpQCSnFl6Fl
XL/Qj7NDtDBK/NCm/bIc9Dvopy5zcTtUQxI9mTHvV1CmwMG0T8XThNbrM7GiYVxupQD3tCyM3BTw
opIoolHYWGMRfRaEmm8OuQApAES6PB/elANryJS4XgXS/6gIqJIR/q25ZjHmIGk69dSZkMs94GdV
m68kzR7bJdohh5misNqiwi8ISpVwM9PeC949mnp5PJ99EmaqTs6TIbZ6lYzVc9fKe7zkFgr3WlnT
dhE0Guk6R1TvAgMBAAECggEAOTnF94Fc1cpHar/Z6tIy9wEeumy9Sb2ei3V4RPLHcLnYspBqZcgi
dxm1SEAND1tzlB7i0uvCmh7keDEc6XpzuUz1bx1f4RBSwdNftSU3uzukpr+vvHw2axPpF52ZUeCU
1dGe5iobCfZNTqN44sH28VuJvc3x4M/CgKIGHjxe4IsyxFCIBpitjk829ymWqlUp/xdVxYfY+WFQ
7/SgA48MU2ASyQVzBA4Q3MQ1d8Fn7Ogd+nYdCGaMfRvO0MI9DcB6uj6KoNZ2VxZkT6eXNEkbzCJR
mbsHfWUx39HVGmlKvZefvryYKJoui1jAZw24F2h8WtBkeGIZ3DgyR9QLQaVT4QKBgQD/HkZUcYXw
I8To/YDtO7i0UZ+vj95PHkfYsWizW1pUiFMHc2jxsyXcjYoKebf8gogKAYnwMxs9iZNkQ4V6zAHi
zeE9C3SwMvh4l6MGJo10+/VmD3SaGZpHEs38HPyXqqqIsQEQq/WDiOMeacTY06AzeIAbW1lVHcTA
Xa8N3TOVuQKBgQDiFP9PAy0trTE8lozQHINytluXlsJap3WcRkGxOTR0v8YLHWYVXMQYo+s4s2Qx
t48nwtBeDEI7OVMA2ip7mAC1IwNObYarLztyB1Vz2FJgVpyj63TdTUaxsiOeAbkLzo4r0TCZnuqi
wdkhAWGu4i3hRrnXe6sbb2Dv4zYysNKT5wKBgQCTjN8AV+gvS4DHgFbg3nmlUNAaqgrZl5nWKkVz
9pH38iCTXpyDrilntjTwehV/Zb9oihtNYUGQBdHJW4QH0ZYFpy1uMQH8Jn6uwIT5ObL2xgLYVHgL
6GLiWG3qMpmk3oBjLnx/N/V3beRt4p6HCV7OZhMxv1Obduwklgp46ka7gQKBgQDDGbOpj+gw/sD6
tEEYZ0LYf55TFvrqGJFaJxcRxXgLOGPDu78YuFFRokOfTtAsR2f2vBvszU9qpHGIzrzSo74YkvqL
d+E7YSs/oCySKCAOmy/aFZtoTwOu3Tf3Zy01jy8JiSETsRxzEC48WWDe9rj5K3u9BTAIIPnaio1+
+TEACQKBgQCfdfmP/05Q4Yc2wEtLfiuHatiobIBzdrem0lXS3ZsRsabnddkeGoQ2QvoMo1+D1/CA
BL/KT6V2h9E8eNQVIOpwjxjR9wPBeHVSLhRV0Rh0Lkog4tGwvWVOh+W+ICr+s6Xn9xxvMUiL3Uw6
9qebfBzruW5Gzke5E5/k3K6aCvFm0Q==
-----END PRIVATE KEY-----
`
// void rsaEncrypt(Buffer.from('hello').toString('base64'), publicKey, RSA_PADDING.OAEPWithSHA1AndMGF1Padding).then((text) => {
// console.log(text)
// void rsaDecrypt(text, privateKey, RSA_PADDING.OAEPWithSHA1AndMGF1Padding).then((text) => {
// console.log(text)
// })
// })
// void generateRsaKey().then((key) => {
// console.log(key.publicKey)
// console.log(key.privateKey)
// })
const aesKey = Buffer.from('123456789abcdefg').toString('base64')
const vi = Buffer.from('012345678901234a').toString('base64')
// void aesEncrypt(Buffer.from('hello').toString('base64'), aesKey, vi, AES_MODE.CBC_PKCS7Padding).then((text) => {
// console.log('hello', text)
// void aesDecrypt(text, aesKey, vi, AES_MODE.CBC_PKCS7Padding).then((text) => {
// console.log(text)
// })
// })
// void aesEncrypt(Buffer.from('hello2').toString('base64'), aesKey, '', AES_MODE.ECB_NoPadding).then((text) => {
// console.log('hello2', text)
// void aesDecrypt(text, aesKey, '', AES_MODE.ECB_NoPadding).then((text) => {
// console.log(text)
// })
// })

126
test.js Normal file
View File

@ -0,0 +1,126 @@
const { publicEncrypt, privateDecrypt, generateKeyPair, createCipheriv, createDecipheriv, constants } = require('crypto')
const generateRsaKey = () => new Promise((resolve, reject) => {
generateKeyPair(
'rsa',
{
modulusLength: 2048, // It holds a number. It is the key size in bits and is applicable for RSA, and DSA algorithm only.
publicKeyEncoding: {
type: 'spki', // Note the type is pkcs1 not spki
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8', // Note again the type is set to pkcs1
format: 'pem',
// cipher: "aes-256-cbc", //Optional
// passphrase: "", //Optional
},
},
(err, publicKey, privateKey) => {
if (err) {
reject(err)
return
}
resolve({
publicKey,
privateKey,
})
},
)
})
// generateRsaKey().then(({ publicKey, privateKey }) => {
// console.log(publicKey)
// console.log(privateKey)
// })
const rsaEncrypt = (buffer, key) => {
return publicEncrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer).toString('base64')
}
const rsaDecrypt = (buffer, key) => {
return privateDecrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer)
}
const publicKey = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0rggENU2JbXgYGoQBIyqlBJP76mgMKh8
5gRIUsAwoq/Oj7qEoKYX9jqtnRgAwEPIV7aLMQxGryfm9fGlohDcUPtcF6za5l6L9Szd+0McOCxZ
SY98/pPFdTYnBHRHPrHHYqzqs4y5wPqpFFNrt2z312YS4xy3SYHkooNPxL0OscxejeG9KtmXQmMd
ejm2MxOIuItlqGHpdwInlvY8Wm/gOMvBmPVffsMaNB412xSZA25D3gRNZRO6O28+S2pXRdSbmFX6
DLWQ/xRDJW1QnfbtjbAJ7Xo1X1anS/NEKRpZqHidjjWI43rL/LhcIAt45a1MkxpBEO+1yCivaNCF
E5jyQwIDAQAB
-----END PUBLIC KEY-----
`
const privateKey = `
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDSuCAQ1TYlteBgahAEjKqUEk/v
qaAwqHzmBEhSwDCir86PuoSgphf2Oq2dGADAQ8hXtosxDEavJ+b18aWiENxQ+1wXrNrmXov1LN37
Qxw4LFlJj3z+k8V1NicEdEc+scdirOqzjLnA+qkUU2u3bPfXZhLjHLdJgeSig0/EvQ6xzF6N4b0q
2ZdCYx16ObYzE4i4i2WoYel3AieW9jxab+A4y8GY9V9+wxo0HjXbFJkDbkPeBE1lE7o7bz5LaldF
1JuYVfoMtZD/FEMlbVCd9u2NsAntejVfVqdL80QpGlmoeJ2ONYjjesv8uFwgC3jlrUyTGkEQ77XI
KK9o0IUTmPJDAgMBAAECggEAUCLE0xH6pym9XH1JfSlvv6MdMkQ8jvSslx8+z/WWKXCZqjBhOuUf
jL0xBGK5+mRsvurFkZAdG4SdwZ+2AWXPG58UHU7X6q8/I6z9+I3DoBtBk4eVng1dlR9UhE2iQJYE
gSLImSLmC51oCrpU5ytyL8D6YtOrYrGa3TD595R8j6G8ElDuvgeqIeFdb5CQUm/4/v+kZ8i8QzGY
lZ65N/mIyl6xB+DnZmWtPRk9HXDdtAnNQlj7uUrKdChq4JNIbwOmrjdmfVkpk5f5JBrCLt8YjGDM
Tf0bSfQcX/PGtm5RHb95XsAp4nGMhVnV44Dnw7kHLIElHRYtt3oXu/SHo3/BDQKBgQDrEpmFaYNS
iVJczAcqmOR+rLHCZnx3GUrKq2udIE6Zb/s2FTzmYHqcSQ66xsn4XzueaCrj9tqUuYIjYnnVM4lL
ux7CgGAwB6moBlUVcDbPZEMJEXXvDE6+oWg3eLGp1S5U7Q8ab0/9laC+c1ncMrgYhBNJ9RhvzimC
/+LPNbdmDQKBgQDleoBdsCDPIpbJVGjkgwN1T6aDPfs+A2lKx0z8Grzmv17HlhYqjy5Jvdx8bulR
0xY81YJ+h8dFD9e9fHdlxpfGj+gtHB8oGzjdN6JWfob6im+XAmg2ftWd1pHx9KBXkpL34NpqleJF
EH7LjGcMjbnceVAM6FEAiPI8BE6RrM91jwKBgQCMzIkzxa0oxKOWfYZVV1qVHS8jt2sZkwafOemt
JWqusMoQ7MubWXJXJdMywFq8752wFciK3pKxviNaumMq9kFoIN4dtfLnEc/mmlRgEORjeDRGvDSd
SAvqVpcrkpknlk64A32mYcHRq8uqB0FtiNuHo6RCChHm9d8bXdUmM5B0CQKBgQCM6xYq8j6jlHUO
O2SSdxXHk1sImyZO5Z9iCVNwOScpd/lHDRadmgFtzUa5rw5ebgbo4qBY/R5Ufa8ZMHbNrA+GItcL
5IoJgfYAeuqYvOg8sIhoLlU6qdaaL6q972ALhvnzeEQIUfR6Pu/uJVEet2WcS27qDju33WELlAV/
laRsZwKBgBzjfllho66+JLamWnthlDHqgEKZDiZF+1fZipOITd7jaA3W8teGc8v9YmSABG4b9IGd
M8XtAFeDYN/MHMKRq+nmLF6hvEQYHUgqYGZGkxX2HcKnRHUssbUOTWJynvRVNPL/k9g9q0d6PeSS
DaE3OO3AUN8voDBaHDII1YscbEBg
-----END PRIVATE KEY-----
`
// const encrypted = rsaEncrypt('123', publicKey)
// console.log(encrypted)
// // const encrypted = 'lJVUCFSV2K90ZdCeosUbtek/wZPmqmKR7ShsP2vfheldde6o9e2Qrmj1QojEwsZtjvq61FCmwpX46LkbsLY/jpM17PUZeqQHhqCy4Rz/hIyMCyIQTPwH5907pIwcpQH2XpJ45/hrjkhLhGU9pkZXtr3qkJiRTi0nllu7z6p6Qf0Hx/zYGxe41VVVnq/9t5xkoUyAfknEn1LMAJyJVft4pD43vTn4tz34+cf7GuzlC4xPiUyKC/trDGBW0kEQBPIaRpd7q1ab9x5fg8mffhBSDR3o+PvVuq3UP02MwpoMDs2bnnwzYawuGv87VNsvEHcvTkZDnh8ME9vtbQboLWVD5w=='
// console.log(rsaDecrypt(Buffer.from(encrypted, 'base64'), privateKey).toString())
const aesEncrypt = (buffer, mode, key, iv) => {
const cipher = createCipheriv(mode, key, iv)
return Buffer.concat([cipher.update(buffer), cipher.final()])
}
const aesDecrypt = function(cipherBuffer, mode, key, iv) {
let decipher = createDecipheriv(mode, key, iv)
return Buffer.concat([decipher.update(cipherBuffer), decipher.final()])
}
// const aesKey = Buffer.from('123456789abcdefg')
// const iv = Buffer.from('012345678901234a')
// // const encryptedAes = aesEncrypt(Buffer.from('hello'), 'aes-128-cbc', aesKey, iv)
// // console.log(encryptedAes)
// // // const encryptedAes = '4zbNfntuHPrHtPvhEVC10Q=='
// // console.log(aesDecrypt(Buffer.from(encryptedAes, 'base64'), 'aes-128-cbc', aesKey, iv).toString())
// // const encryptedAes = aesEncrypt(Buffer.from('hello'), 'aes-128-ecb', aesKey, '')
// // console.log(encryptedAes)
// const encryptedAes = 'oEShKajDOUILq3cVoRv0iw=='
// console.log(aesDecrypt(Buffer.from(encryptedAes, 'base64'), 'aes-128-ecb', aesKey, '').toString())
const text = '{"id":"3779629","n":100000,"p":1}'
const iv = Buffer.from('0102030405060708')
const presetKey = Buffer.from('0CoJUm6Qyw8W8jud')
const secretKey = [56, 70, 110, 77, 99, 98, 51, 117, 67, 98, 85, 73, 118, 80, 104, 70]
// Rn061YcbiMv3hQJlOLNklgQqbcUEF2YyiShXN8kevX3z+iU8j1qHhNEVEoNTNTPQ
// 4dbKbQjGbYdp/Q0bEwCTHcoB8vEQZNc5OUxz6VxScq4AuCYNHwWY44GJrfYuMV7GqQlC/88WdKg4w9ILJGAx5w==
const r1 = aesEncrypt(text, 'aes-128-cbc', presetKey, iv)
console.log(r1.toString('base64'))
console.log(aesEncrypt(r1, 'aes-128-cbc', Buffer.from(secretKey), iv).toString('base64'))