非对称RSA加密解密
来源:互联网 发布:淘宝苏宁易购有假货吗 编辑:程序博客网 时间:2024/06/06 01:54
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi
Shamir)和伦纳德·阿德曼(Leonard
Adleman)一起提出的。1987年7月首次在美国公布,当时他们三人都在麻省理工学院工作实习。RSA就是他们三人姓氏开头字母拼在一起组成的。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战和质疑。
MD5加密算法:http://blog.csdn.net/huangxiaoguo1/article/details/78042596
Base64加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78042715
异或加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78042802
DES加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78042908
AES自动生成base64密钥加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78043000
AES加密解密(ECB模式):http://blog.csdn.net/huangxiaoguo1/article/details/78043098
AES加密解密(CBC模式):http://blog.csdn.net/huangxiaoguo1/article/details/78043169
非对称RSA加密解密:http://blog.csdn.net/huangxiaoguo1/article/details/78043354
app与后台的token、sessionId、RSA加密登录认证与安全解决方案:http://blog.csdn.net/huangxiaoguo1/article/details/78031798
什么是Rsa加密
RSA算法是最流行的公钥密码算法,使用长度可以变化的密钥。RSA是第一个既能用于数据加密也能用于数字签名的算法。
RSA算法原理如下:
1.随机选择两个大质数p和q,p不等于q,计算N=pq;
2.选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素。
3.用公式计算出d:d×e = 1 (mod (p-1)(q-1)) 。
4.销毁p和q。 最终得到的N和e就是“公钥”,d就是“私钥”,发送方使用N去加密数据,接收方只有使用d才能解开数据内容。
RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算,
使得RSA最快的情况也比DES慢上倍,这是RSA最大的缺陷,因此通常只能用于加密少量数据或者加密密钥, 但RSA仍然不失为一种高强度的算法。
app与后台的tokenRSA加密登录认证与安全方式
客户端向服务器第一次发起登录请求(不传输用户名和密码)。 服务器利用RSA算法产生一对公钥和私钥。并保留私钥, 将公钥发送给客户端。 客户端收到公钥后, 加密用户密码,向服务器发送用户名和加密后的用户密码;同时另外产生一对公钥和私钥,自己保留私钥, 向服务器发送公钥;于是第二次登录请求传输了用户名和加密后的密码以及客户端生成的公钥。 服务器利用保留的私钥对密文进行解密,得到真正的密码。 经过判断,确定用户可以登录后,生成sessionId和token, 同时利用客户端发送的公钥,对token进行加密。最后将sessionId和加密后的token返还给客户端。 客户端利用自己生成的私钥对token密文解密, 得到真正的token。
效果
代码
RSAAsymmetricActivity
package tsou.com.encryption.activity.RSA;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.text.TextUtils;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.security.KeyPair;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import tsou.com.encryption.R;import tsou.com.encryption.aescbc.Base64Decoder;import tsou.com.encryption.aescbc.Base64Encoder;import tsou.com.encryption.rsa.RSAUtils;/** * 非对称RSA加密解密 * <p> * <p> * 一、什么是Rsa加密? * <p> * RSA算法是最流行的公钥密码算法,使用长度可以变化的密钥。 * RSA是第一个既能用于数据加密也能用于数字签名的算法。 * RSA算法原理如下: * 1.随机选择两个大质数p和q,p不等于q,计算N=pq; * 2.选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素。 * 3.用公式计算出d:d×e = 1 (mod (p-1)(q-1)) 。 * 4.销毁p和q。 * 最终得到的N和e就是“公钥”,d就是“私钥”,发送方使用N去加密数据,接收方只有使用d才能解开数据内容。 * RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算, * 使得RSA最快的情况也比DES慢上倍,这是RSA最大的缺陷,因此通常只能用于加密少量数据或者加密密钥, * 但RSA仍然不失为一种高强度的算法。 * <p> * <p> * 二、app与后台的tokenRSA加密登录认证与安全方式 * <p> * 客户端向服务器第一次发起登录请求(不传输用户名和密码)。 * <p> * 服务器利用RSA算法产生一对公钥和私钥。并保留私钥, 将公钥发送给客户端。 * <p> * 客户端收到公钥后, 加密用户密码,向服务器发送用户名和加密后的用户密码; * 同时另外产生一对公钥和私钥,自己保留私钥, 向服务器发送公钥; * 于是第二次登录请求传输了用户名和加密后的密码以及客户端生成的公钥。 * <p> * 服务器利用保留的私钥对密文进行解密,得到真正的密码。 经过判断, * 确定用户可以登录后,生成sessionId和token,同时利用客户端发送的公钥,对token进行加密。 * 最后将sessionId和加密后的token返还给客户端。 * <p> * 客户端利用自己生成的私钥对token密文解密, 得到真正的token。 * * 三、博客地址 http://blog.csdn.net/huangxiaoguo1/article/details/78031798 * * */public class RSAAsymmetricActivity extends AppCompatActivity implements View.OnClickListener { private EditText encryptionContext; private Button encryption; private TextView tvEncryption; private Button decode; private TextView tvDecode; private Activity mActivity; private Context mContext; private RSAPublicKey publicKey; private RSAPrivateKey privateKey; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_aes); mActivity = this; mContext = this; encryptionContext = (EditText) findViewById(R.id.et_encryption_context); encryption = (Button) findViewById(R.id.btn_encryption); tvEncryption = (TextView) findViewById(R.id.tv_encryption); decode = (Button) findViewById(R.id.btn_decode); tvDecode = (TextView) findViewById(R.id.tv_decode); encryption.setText("公钥加密"); decode.setText("私钥解密"); initListener(); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); KeyPair keyPair = RSAUtils.generateRSAKeyPair(RSAUtils.DEFAULT_KEY_SIZE); // 公钥 publicKey = (RSAPublicKey) keyPair.getPublic(); // 私钥 privateKey = (RSAPrivateKey) keyPair.getPrivate(); } private void initListener() { encryption.setOnClickListener(this); decode.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btn_encryption://公钥加密 //获取客服端公钥的base64编码的String,登录时将公钥传递给后台 // String localPublicKey = EncodeUtils.base64Encode2String(publicKey.getEncoded()); //保存客户端私钥,传递给服务器时保存到本地备用,可以使用AES加密保存 //String localprivateKey = EncodeUtils.base64Encode2String(privateKey.getEncoded()); String encryptionString = encryptionContext.getText().toString().trim(); if (TextUtils.isEmpty(encryptionString)) { Toast.makeText(mContext, "请输入加密内容", Toast.LENGTH_SHORT).show(); return; } try { byte[] encryptBytes = RSAUtils.encryptByPublicKeyForSpilt(encryptionString.getBytes(), publicKey.getEncoded()); String encryStr = Base64Encoder.encode(encryptBytes); tvEncryption.setText(encryStr); } catch (Exception e) { e.printStackTrace(); } break; case R.id.btn_decode://私钥解密 String decodeString = tvEncryption.getText().toString().trim(); if (TextUtils.isEmpty(decodeString)) { Toast.makeText(mContext, "请先加密", Toast.LENGTH_SHORT).show(); return; } try { byte[] decryptBytes = RSAUtils.decryptByPrivateKeyForSpilt( Base64Decoder.decodeToBytes(decodeString), privateKey.getEncoded()); tvDecode.setText(new String(decryptBytes)); } catch (Exception e) { e.printStackTrace(); } break; } }}
RSAUtils
package tsou.com.encryption.rsa;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.PrivateKey;import java.security.PublicKey;import java.security.spec.InvalidKeySpecException;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.ArrayList;import java.util.List;import javax.crypto.Cipher;import tsou.com.encryption.aescbc.Base64Decoder;public class RSAUtils { public static final String RSA = "RSA";// 非对称加密密钥算法 public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式 public static final int DEFAULT_KEY_SIZE = 2048;//秘钥默认长度 public static final byte[] DEFAULT_SPLIT = "#HUANGXIAOGUO#".getBytes(); // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密 public static final int DEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE / 8) - 11;// 当前秘钥支持加密的最大字节数 /** * 随机生成RSA密钥对 * * @param keyLength 密钥长度,范围:512~2048 * 一般1024 * @return */ public static KeyPair generateRSAKeyPair(int keyLength) { try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA); kpg.initialize(keyLength); return kpg.genKeyPair(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } /** * 用公钥对字符串进行加密 * * @param data 原文 */ public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公钥 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 加密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.ENCRYPT_MODE, keyPublic); return cp.doFinal(data); } /** * 私钥加密 * * @param data 待加密数据 * @param privateKey 密钥 * @return byte[] 加密数据 */ public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception { // 得到私钥 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 数据加密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.ENCRYPT_MODE, keyPrivate); return cipher.doFinal(data); } /** * 公钥解密 * * @param data 待解密数据 * @param publicKey 密钥 * @return byte[] 解密数据 */ public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception { // 得到公钥 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); KeyFactory kf = KeyFactory.getInstance(RSA); PublicKey keyPublic = kf.generatePublic(keySpec); // 数据解密 Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING); cipher.init(Cipher.DECRYPT_MODE, keyPublic); return cipher.doFinal(data); } /** * 使用私钥进行解密 */ public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception { // 得到私钥 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory kf = KeyFactory.getInstance(RSA); PrivateKey keyPrivate = kf.generatePrivate(keySpec); // 解密数据 Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING); cp.init(Cipher.DECRYPT_MODE, keyPrivate); byte[] arr = cp.doFinal(encrypted); return arr; } /** * 用公钥对字符串进行分段加密 */ public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception { int dataLen = data.length; if (dataLen <= DEFAULT_BUFFERSIZE) { return encryptByPublicKey(data, publicKey); } List<Byte> allBytes = new ArrayList<Byte>(2048); int bufIndex = 0; int subDataLoop = 0; byte[] buf = new byte[DEFAULT_BUFFERSIZE]; for (int i = 0; i < dataLen; i++) { buf[bufIndex] = data[i]; if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { subDataLoop++; if (subDataLoop != 1) { for (byte b : DEFAULT_SPLIT) { allBytes.add(b); } } byte[] encryptBytes = encryptByPublicKey(buf, publicKey); for (byte b : encryptBytes) { allBytes.add(b); } bufIndex = 0; if (i == dataLen - 1) { buf = null; } else { buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; } } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 分段加密 * * @param data 要加密的原始数据 * @param privateKey 秘钥 */ public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception { int dataLen = data.length; if (dataLen <= DEFAULT_BUFFERSIZE) { return encryptByPrivateKey(data, privateKey); } List<Byte> allBytes = new ArrayList<Byte>(2048); int bufIndex = 0; int subDataLoop = 0; byte[] buf = new byte[DEFAULT_BUFFERSIZE]; for (int i = 0; i < dataLen; i++) { buf[bufIndex] = data[i]; if (++bufIndex == DEFAULT_BUFFERSIZE || i == dataLen - 1) { subDataLoop++; if (subDataLoop != 1) { for (byte b : DEFAULT_SPLIT) { allBytes.add(b); } } byte[] encryptBytes = encryptByPrivateKey(buf, privateKey); for (byte b : encryptBytes) { allBytes.add(b); } bufIndex = 0; if (i == dataLen - 1) { buf = null; } else { buf = new byte[Math.min(DEFAULT_BUFFERSIZE, dataLen - i - 1)]; } } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 公钥分段解密 * * @param encrypted 待解密数据 * @param publicKey 密钥 */ public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception { int splitLen = DEFAULT_SPLIT.length; if (splitLen <= 0) { return decryptByPublicKey(encrypted, publicKey); } int dataLen = encrypted.length; List<Byte> allBytes = new ArrayList<Byte>(1024); int latestStartIndex = 0; for (int i = 0; i < dataLen; i++) { byte bt = encrypted[i]; boolean isMatchSplit = false; if (i == dataLen - 1) { // 到data的最后了 byte[] part = new byte[dataLen - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPublicKey(part, publicKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } else if (bt == DEFAULT_SPLIT[0]) { // 这个是以split[0]开头 if (splitLen > 1) { if (i + splitLen < dataLen) { // 没有超出data的范围 for (int j = 1; j < splitLen; j++) { if (DEFAULT_SPLIT[j] != encrypted[i + j]) { break; } if (j == splitLen - 1) { // 验证到split的最后一位,都没有break,则表明已经确认是split段 isMatchSplit = true; } } } } else { // split只有一位,则已经匹配了 isMatchSplit = true; } } if (isMatchSplit) { byte[] part = new byte[i - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPublicKey(part, publicKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 使用私钥分段解密 */ public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception { int splitLen = DEFAULT_SPLIT.length; if (splitLen <= 0) { return decryptByPrivateKey(encrypted, privateKey); } int dataLen = encrypted.length; List<Byte> allBytes = new ArrayList<Byte>(1024); int latestStartIndex = 0; for (int i = 0; i < dataLen; i++) { byte bt = encrypted[i]; boolean isMatchSplit = false; if (i == dataLen - 1) { // 到data的最后了 byte[] part = new byte[dataLen - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPrivateKey(part, privateKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } else if (bt == DEFAULT_SPLIT[0]) { // 这个是以split[0]开头 if (splitLen > 1) { if (i + splitLen < dataLen) { // 没有超出data的范围 for (int j = 1; j < splitLen; j++) { if (DEFAULT_SPLIT[j] != encrypted[i + j]) { break; } if (j == splitLen - 1) { // 验证到split的最后一位,都没有break,则表明已经确认是split段 isMatchSplit = true; } } } } else { // split只有一位,则已经匹配了 isMatchSplit = true; } } if (isMatchSplit) { byte[] part = new byte[i - latestStartIndex]; System.arraycopy(encrypted, latestStartIndex, part, 0, part.length); byte[] decryptPart = decryptByPrivateKey(part, privateKey); for (byte b : decryptPart) { allBytes.add(b); } latestStartIndex = i + splitLen; i = latestStartIndex - 1; } } byte[] bytes = new byte[allBytes.size()]; { int i = 0; for (Byte b : allBytes) { bytes[i++] = b.byteValue(); } } return bytes; } /** * 通过字符串生成私钥,转换服务器传递过来的私钥 */ public static PrivateKey getPrivateKey(String privateKeyData) { PrivateKey privateKey = null; try { byte[] decodeKey = Base64Decoder.decodeToBytes(privateKeyData); PKCS8EncodedKeySpec x509 = new PKCS8EncodedKeySpec(decodeKey);//创建x509证书封装类 KeyFactory keyFactory = KeyFactory.getInstance("RSA");//指定RSA privateKey = keyFactory.generatePrivate(x509);//生成私钥 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } return privateKey; } /** * 通过字符串生成公钥,转换服务器传递过来的公钥 */ public static PublicKey getPublicKey(String publicKeyData) { PublicKey publicKey = null; try { byte[] decodeKey = Base64Decoder.decodeToBytes(publicKeyData); X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodeKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); publicKey = keyFactory.generatePublic(x509); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeySpecException e) { e.printStackTrace(); } return publicKey; }}
EncodeUtils
package tsou.com.encryption.rsa;import android.os.Build;import android.text.Html;import android.util.Base64;import java.io.UnsupportedEncodingException;import java.net.URLDecoder;import java.net.URLEncoder;/** * <pre> * author: Blankj * blog : http://blankj.com * time : 2016/8/7 * desc : 编码解码相关工具类 * </pre> */public class EncodeUtils { private EncodeUtils() { throw new UnsupportedOperationException("u can't instantiate me..."); } /** * URL编码 * <p>若想自己指定字符集,可以使用{@link #urlEncode(String input, String charset)}方法</p> * * @param input 要编码的字符 * @return 编码为UTF-8的字符串 */ public static String urlEncode(String input) { return urlEncode(input, "UTF-8"); } /** * URL编码 * <p>若系统不支持指定的编码字符集,则直接将input原样返回</p> * * @param input 要编码的字符 * @param charset 字符集 * @return 编码为字符集的字符串 */ public static String urlEncode(String input, String charset) { try { return URLEncoder.encode(input, charset); } catch (UnsupportedEncodingException e) { return input; } } /** * URL解码 * <p>若想自己指定字符集,可以使用 {@link #urlDecode(String input, String charset)}方法</p> * * @param input 要解码的字符串 * @return URL解码后的字符串 */ public static String urlDecode(String input) { return urlDecode(input, "UTF-8"); } /** * URL解码 * <p>若系统不支持指定的解码字符集,则直接将input原样返回</p> * * @param input 要解码的字符串 * @param charset 字符集 * @return URL解码为指定字符集的字符串 */ public static String urlDecode(String input, String charset) { try { return URLDecoder.decode(input, charset); } catch (UnsupportedEncodingException e) { return input; } } /** * Base64编码 * * @param input 要编码的字符串 * @return Base64编码后的字符串 */ public static byte[] base64Encode(String input) { return base64Encode(input.getBytes()); } /** * Base64编码 * * @param input 要编码的字节数组 * @return Base64编码后的字符串 */ public static byte[] base64Encode(byte[] input) { return Base64.encode(input, Base64.NO_WRAP); } /** * Base64编码 * * @param input 要编码的字节数组 * @return Base64编码后的字符串 */ public static String base64Encode2String(byte[] input) { return Base64.encodeToString(input, Base64.NO_WRAP); } /** * Base64解码 * * @param input 要解码的字符串 * @return Base64解码后的字符串 */ public static byte[] base64Decode(String input) { return Base64.decode(input, Base64.NO_WRAP); } /** * Base64解码 * * @param input 要解码的字符串 * @return Base64解码后的字符串 */ public static byte[] base64Decode(byte[] input) { return Base64.decode(input, Base64.NO_WRAP); } /** * Base64URL安全编码 * <p>将Base64中的URL非法字符�?,/=转为其他字符, 见RFC3548</p> * * @param input 要Base64URL安全编码的字符串 * @return Base64URL安全编码后的字符串 */ public static byte[] base64UrlSafeEncode(String input) { return Base64.encode(input.getBytes(), Base64.URL_SAFE); } /** * Html编码 * * @param input 要Html编码的字符串 * @return Html编码后的字符串 */ public static String htmlEncode(CharSequence input) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { return Html.escapeHtml(input); } else { // 参照Html.escapeHtml()中代码 StringBuilder out = new StringBuilder(); for (int i = 0, len = input.length(); i < len; i++) { char c = input.charAt(i); if (c == '<') { out.append("<"); } else if (c == '>') { out.append(">"); } else if (c == '&') { out.append("&"); } else if (c >= 0xD800 && c <= 0xDFFF) { if (c < 0xDC00 && i + 1 < len) { char d = input.charAt(i + 1); if (d >= 0xDC00 && d <= 0xDFFF) { i++; int codepoint = 0x010000 | (int) c - 0xD800 << 10 | (int) d - 0xDC00; out.append("&#").append(codepoint).append(";"); } } } else if (c > 0x7E || c < ' ') { out.append("&#").append((int) c).append(";"); } else if (c == ' ') { while (i + 1 < len && input.charAt(i + 1) == ' ') { out.append(" "); i++; } out.append(' '); } else { out.append(c); } } return out.toString(); } } /** * Html解码 * * @param input 待解码的字符串 * @return Html解码后的字符串 */// public static CharSequence htmlDecode(String input) {// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {// return Html.fromHtml(input, Html.FROM_HTML_MODE_LEGACY);// } else {// return Html.fromHtml(input);// }// }}
Demo下载地址:java-android:AES加密,RAS加密,DES加密,MD5加密,Base64加密,异或加密
- RSA非对称加密解密
- RSA非对称加密解密
- 非对称RSA加密解密
- RSA加密、解密、签名(非对称加密)
- RSA非对称加密和解密方法
- RSA 非对称加密与解密
- RSA非对称加密解密例子
- Android RSA非对称加密解密算法
- Android: AndroidKeyStore 非对称RSA加密解密
- Java对称与非对称加密解密,AES与RSA
- Java对称与非对称加密解密,AES与RSA
- Java对称与非对称加密解密,AES与RSA
- php rsa加密解密实例(非对称加密)
- android RSA加密 解密 非对称可逆加密
- RSA 非对称加密
- RSA非对称加密
- RSA非对称加密
- RSA非对称加密
- Java中序列化和反序列化的作用
- 设计模式-依赖倒转原则
- Oracle的SQL中出现未明确的列以及执行事务出错
- Hibernate HQL查询的一点小结
- Docker、Containerd、RunC...:你应该知道的所有
- 非对称RSA加密解密
- linux内核虚拟内存之高端物理内存与非连续内存分配
- 关于sessionStorage存储数据例子vue
- Tomcat服务器配置参考
- win10下jdk配置
- Linux命令 --- ps/pstack/pstree
- 配送人司机端操作流程
- 替换空格
- mysql触发器详解