Java
23 Aug 2018portable java
我喜欢portable的工具,所以jre也是,可以从openjdk下载zip包,展开jre,添加path即可。如果要注册jar的双击运行,用管理员权限运行下面的脚本即可:
assoc .jar=jarfile
ftype jarfile="%~dp0bin\javaw.exe" -jar "%%1" %%*
注意这个脚本是放在jre根目录下的,因为是脚本所以%需要转义。
Base64
base64算法在标准jdk8以后版本才有,之前jdk可以用commons-codec,安卓则很早版本就有了。按RFC标准,base64的encoder是可以每隔多少个字符输出一个回车,所以一定注意这个选项,可能导致不同平台的base64不兼容,比如安卓版本缺省就有这个回车选项,所以要加参数。
Base64.encodeToString(str, Base64.NO_WRAP)
MD5
public static String md5(String s, boolean lowercase, String def) {
try {
MessageDigest m = MessageDigest.getInstance("MD5");
String hash = new BigInteger(1, m.digest(lowercase ? s.toLowerCase().getBytes("UTF-8") : s.getBytes("UTF-8"))).toString(16);
//前面要补0
while(hash.length() < 32 ){
hash = "0" + hash;
}
return hash;
} catch (Exception e) {
return def;
}
}
需要注意如果命令行使用linux工具来和上面算法校验,要用-ne参数,表示去除回车echo -ne test | md5sum
RSA加密
使用这个算法,在跨平台使用时,在Cipher.getInstance初始化时一定要指定所有选项,而不能仅仅是”RSA”,因为android和desktop可能细节的选项是不一样的,导致一端加密,另一端解不了。
public static String rsaEncrypt(String key, String src) throws Exception {
byte[] keyBytes = Base64.decodeBase64(key.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return new String(Base64.encodeBase64(cipher.doFinal(src.getBytes("utf-8"))));
}
public static String rsaDecrypt(String key, String src) throws Exception {
byte[] keyBytes = Base64.decodeBase64(key.getBytes());
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(spec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(cipher.doFinal(Base64.decodeBase64(src)),"utf-8");
}
因为RSA的特性,输入的长度要小于等于key的长度,输出的长度等于key的长度,所以如果需要强度,需要选择key比较长,如果需要较短的输出,选择短的key,但最短只能是512bit,生成公钥和私钥对可以用下面的算法。
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
//rsa的key至少512长度,为了加密输出最短,就用最小的512,但是能加密的最长字符也就只有53了
keyGen.initialize(512);
KeyPair pair = keyGen.genKeyPair();
byte[] publicKey = pair.getPublic().getEncoded();
byte[] privateKey = pair.getPrivate().getEncoded();
System.out.println(Base64.encodeBase64String(publicKey));
System.out.println(Base64.encodeBase64String(privateKey));
设置工具使用英文
通过环境变量来更改,Windows下可以这样设置:
set JAVA_TOOL_OPTIONS="-Duser.language=en"
maven 镜像
国内使用阿里云的maven镜像要快很多,设置方法时修改conf/settings.xml,添加
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
对于有些使用maven wrapper的工具,可能有多个maven版本,可以把这个settings.xml拷贝到
### http库 java自带的http api过于底层,一般可以使用apache HttpClient,但这个轻量的http-request非常不错值得一用。比如从anki上下载,需要先通过post取到302的下载地址,再下载文件,可以这样
String addr = HttpRequest.post("https://ankiweb.net/shared/downloadDeck/627603312")
.form("k", "xxxkey")
.followRedirects(false)
.location();
HttpRequest.get(addr).header("User-Agent","curl/7.55.1").receive(new File("output"));
json
org.json.JSONObject在导出json时,会把”/”字符转义,原因时考虑json有可能嵌入在html里,所以输出的json可能会出现”\/aaa\/bbb”这样的字符串。
反编译
java反编译有很多工具,jadx值得推荐,它可以直接打开apk进行反编译,gui也做的很好,除此之外的工具有:
- 很多人推荐jd-gui,这个工具不能直接打开dex,只支持jar,反编译的效果和jadx互有胜负,。
- dex-tools,用于将dex转换为jar,对于不支持直接反编译dex的工具,需要用这个先转换一下。
- apk-tool 如果要看apk中的string资源,需要这个命令行工具。
java -jar apktool.jar d xxx.apk
就可以了 - bytecodeviewer,这是个GUI工具,内置了三四种java反编译器,可以多个反编译器的效果对比,但是GUI做的很不好用。
bytecodeviewer支持的几种反编译器里proycon和fenflower都不错,比jadx/jd-gui效果要好。
重新打包
使用apktool可以重新打开一个apk,比如可以调整debug属性,backup属性,甚至改包名, 不过一般需要先通过apktool if安装厂商的资源包
apktool_2.5.0.jar if framework-res.apk
apktool_2.5.0.jar d xxx.apk
REM 修改xxx\AndroidManifest.xml和apktool.yml,可以在apktool.yml里修改renameManifestPackage
apktool_2.5.0.jar b xxx -o xxx2.apk
jarsigner.exe -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore yyy.keystore xxx2.apk yyy
break语言
java的break语句并不常用,但是在反编译的结果中却比较常见,break的意思是跳出当前scope,因此和goto是不一样的。
first:
for( int i = 0; i < 10; i++) {
second:
for(int j = 0; j < 5; j ++ )
{
break xxx; //xxx可以是first,也可以是second,但不能是third
}
}
third:
for( int a = 0; a < 10; a++) {
}