背景:因为HDFS小文件太多了 导致HDFS集群压力很大 所以项目由原来的存储文件方式改成了 把文件流以二进制的方式存入一个个大的文件块 通过文件 位置信息和偏移量信息来标记文件
网上很多通过APK路径 来获取APK的签名和权限列表的 但是直接对接流的基本没有 而且封装的方法 也没有好的可以接入流的接口
通过输入流获取APK签名:
思路:
截取HDFS中APK输入流
再截取APK中RSA的文件流 保存到本地
结合cmd命令
keytool -printcert -file rsaFilePath
打印出RSA文件的MD5和SHA1值 截取 保存
/**
* DESC: 获取HDFS中apk文件的签名:MD5、SHA1
* @param filePath : /tmp/a/b/c.apk
* @param position : 位置信息
* @param offset : 偏移量
* */
public static Map<String,String> getAPKSignV2(String filePath,long position, int offset){
getHDFS();
Map<String, String> signMap = new HashMap<>();/**用来存放MD5、SHA1的签名*/
Path path = new Path(filePath);
FSDataInputStream dataStream;
try {
dataStream = hdfs.open(path);
InputStream new_dataStream=getInputStreamByPosAndOffset(dataStream,position,offset);
getApkSignInfo(new_dataStream,signMap);
} catch (Exception e) {
e.printStackTrace();
}
return signMap;
}
public static void getApkSignInfo(InputStream inputStream,Map<String, String> signMap) {
String osName = System.getProperty("os.name");
String rsaFilePath = null;
String rsaFileName=System.currentTimeMillis()+".RSA";
String parentDir="";
String WINDOWS_LOCAL = "D:\\attachfiles\\wsl\\";
String LINUX_LOCAL = "/tmp/attachfiles/";
if (osName.contains("Windows")) {
parentDir = WINDOWS_LOCAL;
}
else {
parentDir = LINUX_LOCAL;
}
File file=new File(parentDir);
if (!file .exists() && !file .isDirectory())
{
file .mkdirs();
}
rsaFilePath = parentDir +rsaFileName;
InputStream in = new BufferedInputStream(inputStream);
ZipInputStream zin = new ZipInputStream(in);
File ff=new File(rsaFilePath);
ZipEntry ze;
try {
while ((ze = zin.getNextEntry()) != null) {
if (ze.isDirectory()) {
} else {
if(ze.getName().endsWith(".RSA")){
InputStreamToFile(zin,ff);//保存RSA输入流到位RSA文件
getApkSignResult(rsaFilePath,signMap);//读取RSA文件获取MD5和SHA1值
}
}
}
} catch (Exception e) {
logger.error("解析RSA流失败...",e);
} finally {
try {
zin.closeEntry();
inputStream.close();
in.close();
zin.close();
}catch (Exception e) {
logger.error("关闭流异常...",e);
} finally {
if(ff.exists()){
ff.delete();
}
}
}
}
public static void InputStreamToFile(InputStream ins,File file){
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void getApkSignResult(String rsaFilePath,Map<String, String> signMap){
Process p;
String cmd = "keytool -printcert -file " + rsaFilePath;
try
{
//执行命令
p = Runtime.getRuntime().exec(cmd);
//取得命令结果的输出流
InputStream fis=p.getInputStream();
//用一个读输出流类去读
//用缓冲器读行
BufferedReader br=new BufferedReader( new InputStreamReader(fis,"GB2312"));
String line=null;
//直到读完为止
while((line=br.readLine())!=null)
{
if(line.contains("MD5")){ //解析符合自己需要的內容,获取之后,直接返回。
String MD5=line.replace(":","").replace("MD5","").toLowerCase().trim();
signMap.put("MD5",MD5);
}
if(line.contains("SHA1")){ //解析符合自己需要的內容,获取之后,直接返回。
String SHA1=line.replace(":","").replace("SHA1","").toLowerCase().trim();
signMap.put("SHA1",SHA1);
}
}
} catch (IOException e)
{
e.printStackTrace();
}
}
由于HDFS小文件问题,项目改为存储文件流。文章介绍了一种通过截取HDFS APK输入流,提取RSA文件流并利用cmd命令计算MD5和SHA1值来获取APK签名的方法,解决了直接对接流获取签名的难题。
9447

被折叠的 条评论
为什么被折叠?



