Base64

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。

阅读全文 »

AES

分组加密算法,对称加密算法
AES的区块长度固定为128 比特,密钥长度则可以是128,192或256比特

  • AES算法中不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现
  • jdk自带的aes加密只支持到128位,更高的256位的加密,需要到oracle官网下载jce包,替换java自带的加密包。
1
2
// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16
compile group: 'org.bouncycastle', name: 'bcprov-jdk16', version: '1.46'

微信小程序数据解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static {
Security.addProvider(new BouncyCastleProvider());
}
public static String decryptData(String data, String session_key, String iv) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
byte[] content = base64DecodeData(data);
byte[] keyBytes = base64DecodeData(session_key);
byte[] ivBytes = base64DecodeData(iv);
return new String(AESDecodeData(content, keyBytes, ivBytes), "utf-8");
}

private static byte[] AESDecodeData(byte[] content, byte[] keyBytes, byte[] iv) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
Key key = new SecretKeySpec(keyBytes, "AES");

Cipher cipher = getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(content);
}

private static byte[] base64DecodeData(String s) {
Base64.Decoder decoder = Base64.getDecoder();
return decoder.decode(s);
}

JavaScript实现

cryptojs
在微信小程序中npm构建出错,解决:将代码复制到本地即可使用
npm install cryptojs 可以在本地使用(node test.js)
crypto-js
npm install crypto-js

cryptojs测试demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var Crypto = require('./cryptojs/cryptojs.js').Crypto;//ok
//解析运动数据
var decryptData = function(data, session, iv,that) {
var dataBytes = Crypto.util.base64ToBytes(data);
var sessionBytes = Crypto.util.base64ToBytes(session);
var ivBytes = Crypto.util.base64ToBytes(iv);


var mode = new Crypto.mode.CBC(Crypto.pad.pkcs7);
var decryptData = Crypto.AES.decrypt(data, sessionBytes, {
mode: mode,
iv: ivBytes,
asBytes: true //false: bytesToBase64
});
console.log("decrypt: " + Crypto.charenc.UTF8.bytesToString(decryptData));
}

demo(NodeJs)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var crypto = require('crypto')
function WXBizDataCrypt(sessionKey) {
this.sessionKey = sessionKey
}

WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
// base64 decode
var sessionKey = Buffer.from(this.sessionKey, 'base64')//base64解码
encryptedData = Buffer.from(encryptedData, 'base64')
iv = Buffer.from(iv, 'base64')
try {
// 解密
var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
// 设置自动 padding 为 true,删除填充补位
decipher.setAutoPadding(true)
//cipher.update(data, [input_encoding], [output_encoding])
var decoded = decipher.update(encryptedData, 'binary', 'utf8')//解密
decoded += decipher.final('utf8')
decoded = JSON.parse(decoded)
} catch (err) {
throw new Error('Illegal Buffer')
}
return decoded
}
module.exports = WXBizDataCrypt

Java实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package test;

import org.bouncycastle.crypto.Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.Base64;

import static javax.crypto.Cipher.getInstance;

/**
* 介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别
* 要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现
*/
public class Util {

static {
Security.addProvider(new BouncyCastleProvider());
}

public static String decryptData(String data, String session_key, String iv) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
byte[] content = base64DecodeData(data);
byte[] keyBytes = base64DecodeData(session_key);
byte[] ivBytes = base64DecodeData(iv);
return new String(AESDecodeData(content, keyBytes, ivBytes), "utf-8");
}

private static byte[] AESDecodeData(byte[] content, byte[] keyBytes, byte[] iv) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
Key key = new SecretKeySpec(keyBytes, "AES");

Cipher cipher = getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return cipher.doFinal(content);
}

private static byte[] base64DecodeData(String s) {
Base64.Decoder decoder = Base64.getDecoder();
return decoder.decode(s);
}


public static void checkSignature(String session, String rawData, String signature) throws NoSuchAlgorithmException, UnsupportedEncodingException {
String data = rawData + session;
System.out.println(data);
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
byte[] bs = messageDigest.digest(data.getBytes("utf-8"));
byte2Hex(bs);
System.out.println(signature);
}

private static void byte2Hex(byte[] bs) {
byte2Hex(bs, 0, bs.length);
}

public static void byte2Hex(byte[] bs, int start, int offset) {
StringBuilder stringBuilder = new StringBuilder(2 * offset);
for (int i = start; i < start + offset; i++) {
byte high = (byte) ((byte) (bs[i] >> 4) & 0x0f);
stringBuilder.append("0123456789abcdef".charAt(high));
byte low = (byte) ((bs[i] & 0x0f));
stringBuilder.append("0123456789abcdef".charAt(low));
}
System.out.println(stringBuilder.toString());
}

}

输入

param desp
key 128,192或256比特
data 16个字节共128位的需要被加密或被解密的数据
mode DES工作方式,加密或者解密

初始向量(16个字节):IV
填充方式or自行填充

阅读全文 »

DES

分组加密算法,对称加密算法

输入

param desp
key 8个字节共64位的工作密钥(56位密钥+8位奇偶校验位)
data 8个字节共64位的需要被加密或被解密的数据
mode DES工作方式,加密或者解密

初始向量(8个字节):IV
填充方式or自行填充

阅读全文 »

相对路径

1
2
{% asset_img bd_logo.png just for fun ! %}  
![just for fun](bd_logo.png "just for fun !")
阅读全文 »

byte&String

byte2HexString

1
2
3
4
5
6
7
8
9
10
11
12
public void byte2HexString(byte[] bytes){
if (bytes == null) return null;
StringBuilder ret = new StringBuilder(2*bytes.length);
for (int i = 0 ; i < bytes.length ; i++) {
int b;
b = 0x0f & (bytes[i] >> 4);
ret.append("0123456789abcdef".charAt(b));
b = 0x0f & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}

hexString2Byte

1
2
3
4
5
6
7
8
9
10
11
public void hexString2Byte(String str){
if (str==null||str.length()&0x1==1) return null;
str=str.toLowerCase();
byte[] ret=new byte[str.length()/2];
for(int i=0;i<str.length;i++){
byte high = (byte) "0123456789abcdef".indexOf(str.charAt(i));
byte low = (byte) "0123456789abcdef".indexOf(str.charAt(++i));
ret[i/2] = (byte) ((byte)(high<<4) | low );
}
return ret;
}

base64&Img

just base64 encode/decode

Base64toImg

1
2
3
4
5
6
7
8
9
public static void parseImg(String path, String imgStr) {
Base64.Decoder decoder = Base64.getDecoder();
byte[] retbytes = decoder.decode(imgStr);
try {
Files.write(Paths.get(path), retbytes);
} catch (IOException e) {
e.printStackTrace();
}
}

Android ANR分析

前言

ANR即Application Not Responding,顾名思义就是应用程序无响应。在Android中,一般情况下,四大组件均是工作在主线程中的,Android中的Activity Manager和Window Manager会随时监控应用程序的响应情况,如果因为一些耗时操作(网络请求或者IO操作)造成主线程阻塞一定时间(例如造成5s内不能响应用户事件或者BroadcastReceiver的onReceive方法执行时间超过10s),那么系统就会显示ANR对话框提示用户对应的应用处于无响应状态。

虽然每个程序员都不想ANR发生在自己的头上,因此,你需要严格遵守Google提供的一系列建议(看这里),简单总结就是以下两点:

1. 不要让主线程干耗时的工作
2. 不要让其他线程阻塞主线程的执行

因此,要尽量保证主线程执行工作干净利落,一个消息循环执行时间最好不超过100ms到200ms,对于一些脏活累活可以交给AsyncTask、HandlerThread、IntentService或者另外起的新线程来完成,这样应用程序就能够及时响应用户的操作而不会给用户带来卡顿的感觉。

阅读全文 »
0%