android 加解密的速度和什么有关系,Android 加解密类Cipher

近日在做一个关于短信及文件加解密的小项目,查看了一些Android加解密方面的知识。关于加解密这部分以前完全没有接触过,所以网上乱翻了一天对于什么DES,AES,RSA,BASE64,MD5之类的还是懵懵懂懂,这里也就不再来说它们的原理了,实在是我自己也没弄懂。写这篇博客时也就大致了解了一下Cipher类,并实现了一个简单的AES编解码工具类,当然是用的都是些最简单的默认模式,更详细的知识还有待进一步的学习。 此博文主要是复习记录一下一天学习所得,加深印象。

Android的Cipher类其实是来自于Java的加密环境JCE,查看官方的文档就可以看到: javax.crypto.Cipher。当然据说这个类也不在官方的正式JDK里面,而且有些解密方法在Android中不可用(这部分不敢下结论,加密的东西我也刚刚开始了解)。下面就来具体看一下实现AES加密的过程吧。

Step1:实现一个简单XML文件做测试界面,实现一个EditText,两个Button,一个TextView显示结果:

android:id="@+id/et_input"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

android:id="@+id/btn_encrypt"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="加密"/>

android:id="@+id/btn_decrypt"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="解密"/>

android:id="@+id/tv_output"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

Step2:Activity代码就不贴出来了,无非就是获得上面4个控件,然后监听加密、解密两个按钮执行加解密工具类的加解密方法。

Step3:实现加解密工具类,这也是此篇博文的关键。下面来一步一步的分析:

先来看看官方给出的加密大致流程:Use a secure random number generator,, to initialize any cryptographic keys,.  这句话大致意思就是使用一个安全的随机数来产生一个密匙。当然这个密匙是我们用来加密使用的。把这段话转换成一段代码如下:

private static byte[] getRawKey(byte[] seed) throws NoSuchAlgorithmException{

SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); // 获得一个随机数,传入的参数为默认方式。

sr.setSeed(seed);  // 设置一个种子,这个种子一般是用户设定的密码。也可以是其它某个固定的字符串

KeyGenerator keyGen = KeyGenerator.getInstance("AES");  // 获得一个key生成器(AES加密模式)

keyGen.init(128, sr);      // 设置密匙长度128位

SecretKey key = keyGen.generateKey();  // 获得密匙

byte[] raw = key.getEncoded();   // 返回密匙的byte数组供加解密使用

return raw;

}

当我们通过上面的方法获得密匙后,就可以使用Cypher提供的方法来进行加解密操作了。注意Cypher无法直接获得实例,只能通过getInstance方法来获得实例:

This class provides access to implementations of cryptographic ciphers for encryption and decryption. Cipher classes can not be instantiated directly, one has to call the Cipher's getInstance method with the name of a requested transformation, optionally with a provider. A transformation specifies an operation (or a set of operations) as a string in the form:

"algorithm/mode/padding"or

"algorithm"

这里指出在获得Cypher实例时需要使用getInstance方法,且必须传入一个参数,这个参数包括加密算法,加密模式和填充方式三部分,当然也可以只指定加密算法,从而使用默认的模式和填充方式。此次我的设计传入"AES"参数,那么系统会默认使用"AES/CFB8/NoPadding"来做为这三部分的设置参数。当获得Cypher实例以后,就可以调用它的一些方法来进行加解密,具体实现如下:

private static byte[] encry(byte[] raw, byte[] input) throws Exception {  // 加密

SecretKeySpec keySpec = new SecretKeySpec(raw, "AES"); // 根据上一步生成的密匙指定一个密匙(密匙二次加密?)

Cipher cipher = Cipher.getInstance("AES");  // 获得Cypher实例对象

cipher.init(Cipher.ENCRYPT_MODE, keySpec);  // 初始化模式为加密模式,并指定密匙

byte[] encode = cipher.doFinal(input);  // 执行加密操作。 input为需要加密的byte数组

return encode;                         // 返回加密后的密文(byte数组)

}

private static byte[] decry(byte[] raw, byte[] encode) throws Exception{ // 解密

SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");

Cipher cipher = Cipher.getInstance("AES");

cipher.init(Cipher.DECRYPT_MODE, keySpec);   // 解密的的方法差不多,只是这里的模式不一样

byte[] decode = cipher.doFinal(encode);  // 加解密都通过doFinal方法来执行最终的实际操作

return decode;

}

最后再对上述两个方法进行一次封装,提供对外的接口即可完成此工具类的简单功能。加解密工具要求实现字符串明文输入,字符串密文输出,下面来看看具体实现代码:

public static String decryptString(String seed,byte[] encode) throws Exception{

byte[] raw = getRawKey(seed.getBytes());

byte[] decode = decry(raw, encode);

return new String(decode);

}

public static byte[] encryptString(String seed, String input) throws Exception{

byte[] raw = getRawKey(seed.getBytes());

byte[] encode = encry(raw, input.getBytes());

// return new String(encode);  // 这里返回加密后的密文字符串是有问题的,后面再解释。

returnencode;

}

上面代码中基本实现了需求,只不过加密时输出的是byte数组,解密时输入也是byte数组。当然这样对称设计在同一个应用里是不会出现问题的,不过传输时大家都习惯将byte数组转成字符串的格式,而在byte转字符串时会因为字符编码的原因出现一些问题,下面就来看看如何来解决加解密使用字符串密文异常问题。

大家都知道,计算机存储字符使用ASCII码形式,当出现中文等字符时将无法使用一个8位的字符来表示,国际通用标准UNICODE使用16位来表示,但不同语种已经实现了大量不同的编码格式,而我们的加密算法是针对byte数组来进行的,加密后的byte数组将无法使用某种字符编码来转成字符串,所以这里将加密后的byte数组转换成字符串时将出现问题。

这里再举一个简单的例子来说明会出现何种问题,大家可以使用下面这段代码来跟踪一下具体实现效果:

byte[] b = -120;

String str = new String(b);

byte[] bytes = str.getBytes();

大家执行一下这段代码,看看bytes得到是什么? 我想不用我说,现在应该都知道为什么转换会出现问题了吧。这对这种情况,我们需要在byte与String转换时进行一个byte转hex,以及hex转byte的中转操作。具体代码如下:

private static String bytesToHexString(byte[] src){

StringBuilder stringBuilder = new StringBuilder("");

if (src == null || src.length <= 0) {

return null;

}

for (int i = 0; i < src.length; i++) {

int v = src[i] & 0xFF;

String hv = Integer.toHexString(v);

if (hv.length() < 2) {

stringBuilder.append(0);

}

stringBuilder.append(hv);

}

return stringBuilder.toString();

}

private static byte[] hexStringToBytes(String hexString) {

if (hexString == null || hexString.equals("")) {

return null;

}

hexString = hexString.toUpperCase();

int length = hexString.length() / 2;

char[] hexChars = hexString.toCharArray();

byte[] d = new byte[length];

for (int i = 0; i < length; i++) {

int pos = i * 2;

d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

}

return d;

}

private static byte charToByte(char c) {

return (byte) "0123456789ABCDEF".indexOf(c);

}

到这里就完美解决了转换问题,把上述前面封装的两个接口中标注红色的部分分别进行转换即可达到进出皆为String的目的。 AES算法的简单实现到这里就完成了,关于加解密方面的知识后续还需要抽时间再好好补一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

redis缓存原理与实现_SpringBoot整合Redis缓存,手把手教你一步一步实现

推荐学习分布式大全&#xff1a;反向代理/Redis/中间件/MySQL/消息&#xff0c;挑战阿里P7必备都是“Redis惹的祸”&#xff0c;害我差点挂在美团三面&#xff0c;真是“虚惊一场”微服务架构之春招总结&#xff1a;SpringCloud、Docker、Dubbo与SpringBoot一、基本概况为什么使…

C 实现高性能内存池

版权一、概述在 C/C 中&#xff0c;内存管理是一个非常棘手的问题&#xff0c;我们在编写一个程序的时候几乎不可避免的要遇到内存的分配逻辑&#xff0c;这时候随之而来的有这样一些问题&#xff1a;是否有足够的内存可供分配? 分配失败了怎么办? 如何管理自身的内存使用情况…

【计算理论】06 可归约性

文章目录 本章要点可归约性映射可归约图灵可判定归约证明 H A L T T M HALT_{TM} HALTTM​不可判定 E T M E_{TM} ETM​不可判定 R E G U L A R T M REGULAR_{TM} REGULARTM​不可判定 E Q T M EQ_{TM} EQTM​不可判定 图灵可识别的归约性参考 本章要点 可归约性定义&#xff…

组件注入 # 注入的属性_注入域对象而不是基础结构组件

组件注入 # 注入的属性依赖注入是Java&#xff08;以及许多其他编程语言&#xff09;中广泛使用的软件设计模式&#xff0c;用于实现控制反转 。 它提高了可重用性&#xff0c;可测试性&#xff0c;可维护性&#xff0c;并有助于构建松耦合的组件。 如今&#xff0c;依赖注入是…

docker $PWD路径_Docker安装Jenkins+Shell脚本自动化部署项目

本文同名博客老炮说Java&#xff1a;https://www.laopaojava.com/&#xff0c;每天更新Spring/SpringMvc/SpringBoot/实战项目等文章资料SentinelNacos 是微服务环境搭建必不可少的两个组件&#xff0c;这里给大家推荐一套微服务教程&#xff1a;SpringCloud微服务电商项目教程…

flyme Android7.0 root,手把手教你如何免ROOT卸载Flyme7系统自带APP

本教程需要使用adb&#xff0c;adb的全称为Android Debug bridge&#xff0c;就是起到调试桥的作用。借助adb工具&#xff0c;我们可以管理设备或手机模拟器的状态。本教程需要使用adb&#xff0c;adb的全称为Android Debug bridge&#xff0c;就是起到调试桥的作用。借助adb工…

C语言 -- 字符串中根据特定字符(串)分割

版权C语言字符串操作函数有很多&#xff0c;这里举出需要用到的&#xff0c;其他请自行查找。1、len strlen(p) &#xff1b;//取字符串长度 原型&#xff1a;size_t strlen(const char *s); 功能&#xff1a;统计字符串string中字符的个数&#xff0c;字符串的长度在 size_t…

javaone_JavaOne 2014:会议与合同利益冲突

javaone杜克街咖啡馆&#xff0c;工程师可以在街上进行走廊交谈 。 与签约不兼容 我的第11届JavaOne会议&#xff08;2004年至2014年为11 10 1&#xff09;非常出色。 值得参加此活动并结识社区中所有的人。 现在&#xff0c;这里是绅士的&#xff0c;但 。 除了经济上的明显…

什么流读取MultipartFile_深入理解并运用Node中的IO模型流

在 NodeJs 中&#xff0c;流随处可见&#xff0c;读/写文件流&#xff0c;HTTP请求/返回流&#xff0c;stdin/stdout流。理解并运用好流会让你的Node更具力量。Streamlib/_stream_readable.jslib/_stream_writable.jslib/_stream_tranform.jslib/_stream_duplex.js流主要有可读…

android状态机是线程么,Java中的线程状态机 - java

有没有一种方法可以将线程保留在状态中等待更改&#xff1f;我的意思是&#xff0c;等一下事情发生了(更改var&#xff0c;调用方法等)。也许它需要使用事件监听器或同步的对象/方法。这样的状态机通常的方法statemachine example它使用一个do {..} while(true)循环&#xff0c…

C 线程的创建

前言线程创建很容易&#xff0c;直接调用std::thread&#xff0c;就创建一个新线程了。该线程拿到任务后立即开始执行。线程的创建者&#xff08;父线程&#xff09;必须管理创建的线程&#xff08;子线程&#xff09;&#xff0c;应该等到子线程完成其任务或者让子线程从自己身…

apache karaf_未来是Apache Karaf上的微服务架构

apache karaf这是Jamie Goodyear的客座博客文章&#xff08; 博客 &#xff0c; icbts &#xff09;。 他是Savoir Technologies的开源倡导者&#xff0c;Apache开发人员和计算机系统分析师&#xff1b; 他为全球大型组织设计&#xff0c;批判和支持了体系结构。 他拥有纽芬兰…

AppScan api登录接口 postman_如何通过Postman调用EDI系统的API?

知行EDI系统主要是用来实现贸易双方的数据交换的过程&#xff0c;这个过程中&#xff0c;贸易双方往往需要根据国际通用的消息格式收发信息&#xff0c;我们称符合国际规范的消息文件为EDI报文&#xff0c;然而不同的公司会结合ERP的接口情况选择不同的集成方式&#xff0c;例如…

指针函数和函数指针

概述指针函数和函数指针是C语言里两个比较绕的概念。但是不仅面试题爱考&#xff0c;实际应用中也比较广泛。很多人因为搞不清这两个概念&#xff0c;干脆就避而远之&#xff0c;我刚接触C语言的时候对这两个概念也比较模糊&#xff0c;特别是当指针函数、函数指针、函数指针变…

android显示绘图动画,Android自定义View绘图实现渐隐动画

实现了一个有趣的小东西&#xff1a;使用自定义view绘图&#xff0c;一边画线&#xff0c;画出的线条渐渐变淡&#xff0c;直到消失。效果如下图所示&#xff1a;用属性动画或者渐变填充(shader)可以做到一笔一笔的变化&#xff0c;但要想一笔渐变(手指不抬起边画边渐隐)&#…

csrf spring_无状态Spring安全性第1部分:无状态CSRF保护

csrf spring如今&#xff0c;随着RESTful架构变得越来越标准&#xff0c;可能值得花一些时间重新考虑当前的安全方法。 在这一小系列博客文章中&#xff0c;我们将探索以无状态方式解决与Web相关的安全性问题的几种相对较新的方法。 这第一篇文章是关于保护您的网站免受跨站请求…

python网络编程项目_python网络编程详解

最近在看《UNIX网络编程 卷1》和《FREEBSD操作系统设计与实现》这两本书&#xff0c;我重点关注了TCP协议相关的内容&#xff0c;结合自己后台开发的经验&#xff0c;写下这篇文章&#xff0c;一方面是为了帮助有需要的人&#xff0c;更重要的是方便自己整理思路&#xff0c;加…

C - 指针总结

指针是什么&#xff1f;指针是一变量或函数的内存地址&#xff0c;是一个无符号整数&#xff0c;它是以系统寻址范围为取值范围&#xff0c;32位&#xff0c;4字节。指针变量&#xff1a;存放地址的变量。在C 中&#xff0c;指针变量只有有了明确的指向才有意义。指针类型int* …

android网络转圈,android基于dialog加载时转圈圈很好的demo

【实例简介】这是一个android基于dialog加载时转圈圈很好的完整demo&#xff0c;很适合新手学习&#xff0c;希望对有需要的朋友能得到帮助【实例截图】【核心代码】dialog_anim└── dialog_anim├── AndroidManifest.xml├── bin│ ├── AndroidManifest.xml│ ├…

spring期刊状态_无状态Spring安全性第2部分:无状态认证

spring期刊状态Spring Stateless Security系列的第二部分是关于以无状态方式探索身份验证的方法。 如果您错过了有关CSRF的第一部分&#xff0c;可以在这里找到。 因此&#xff0c;在谈论身份验证时&#xff0c;其全部内容就是让客户端以可验证的方式向服务器标识自己。 通常&…