背景:因为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(); } }