激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java中RSA加密解密的實現方法分析

Java中RSA加密解密的實現方法分析

2020-11-29 11:38Central-Perk Java教程

這篇文章主要介紹了Java中RSA加密解密的實現方法,結合具體實例形式分析了java實現RSA加密解密算法的具體步驟與相關操作技巧,并附帶了關于RSA算法密鑰長度/密文長度/明文長度的參考說明,需要的朋友可以參考下

本文實例講述了JavaRSA加密解密的實現方法。分享給大家供大家參考,具體如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) throws Exception {
    // TODO Auto-generated method stub
    HashMap<String, Object> map = RSAUtils.getKeys();
    //生成公鑰和私鑰
    RSAPublicKey publicKey = (RSAPublicKey) map.get("public");
    RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");
    //模
    String modulus = publicKey.getModulus().toString();
    //公鑰指數
    String public_exponent = publicKey.getPublicExponent().toString();
    //私鑰指數
    String private_exponent = privateKey.getPrivateExponent().toString();
    //明文
    String ming = "123456789";
    //使用模和指數生成公鑰和私鑰
    RSAPublicKey pubKey = RSAUtils.getPublicKey(modulus, public_exponent);
    RSAPrivateKey priKey = RSAUtils.getPrivateKey(modulus, private_exponent);
    //加密后的密文
    String mi = RSAUtils.encryptByPublicKey(ming, pubKey);
    System.err.println(mi);
    //解密后的明文
    ming = RSAUtils.decryptByPrivateKey(mi, priKey);
    System.err.println(ming);
}

RSAUtils.Java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
package yyy.test.rsa;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.HashMap;
import javax.crypto.Cipher;
public class RSAUtils {
  /**
   * 生成公鑰和私鑰
   * @throws NoSuchAlgorithmException
   *
   */
  public static HashMap<String, Object> getKeys() throws NoSuchAlgorithmException{
    HashMap<String, Object> map = new HashMap<String, Object>();
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    keyPairGen.initialize(1024);
    KeyPair keyPair = keyPairGen.generateKeyPair();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    map.put("public", publicKey);
    map.put("private", privateKey);
    return map;
  }
  /**
   * 使用模和指數生成RSA公鑰
   * 注意:【此代碼用了默認補位方式,為RSA/None/PKCS1Padding,不同JDK默認的補位方式可能不同,如Android默認是RSA
   * /None/NoPadding】
   *
   * @param modulus
   *      模
   * @param exponent
   *      指數
   * @return
   */
  public static RSAPublicKey getPublicKey(String modulus, String exponent) {
    try {
      BigInteger b1 = new BigInteger(modulus);
      BigInteger b2 = new BigInteger(exponent);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
      return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
  /**
   * 使用模和指數生成RSA私鑰
   * 注意:【此代碼用了默認補位方式,為RSA/None/PKCS1Padding,不同JDK默認的補位方式可能不同,如Android默認是RSA
   * /None/NoPadding】
   *
   * @param modulus
   *      模
   * @param exponent
   *      指數
   * @return
   */
  public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
    try {
      BigInteger b1 = new BigInteger(modulus);
      BigInteger b2 = new BigInteger(exponent);
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
      return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
  /**
   * 公鑰加密
   *
   * @param data
   * @param publicKey
   * @return
   * @throws Exception
   */
  public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
      throws Exception {
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    // 模長
    int key_len = publicKey.getModulus().bitLength() / 8;
    // 加密數據長度 <= 模長-11
    String[] datas = splitString(data, key_len - 11);
    String mi = "";
    //如果明文長度大于模長-11則要分組加密
    for (String s : datas) {
      mi += bcd2Str(cipher.doFinal(s.getBytes()));
    }
    return mi;
  }
  /**
   * 私鑰解密
   *
   * @param data
   * @param privateKey
   * @return
   * @throws Exception
   */
  public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey)
      throws Exception {
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    //模長
    int key_len = privateKey.getModulus().bitLength() / 8;
    byte[] bytes = data.getBytes();
    byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
    System.err.println(bcd.length);
    //如果密文長度大于模長則要分組解密
    String ming = "";
    byte[][] arrays = splitArray(bcd, key_len);
    for(byte[] arr : arrays){
      ming += new String(cipher.doFinal(arr));
    }
    return ming;
  }
  /**
   * ASCII碼轉BCD碼
   *
   */
  public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
    byte[] bcd = new byte[asc_len / 2];
    int j = 0;
    for (int i = 0; i < (asc_len + 1) / 2; i++) {
      bcd[i] = asc_to_bcd(ascii[j++]);
      bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
    }
    return bcd;
  }
  public static byte asc_to_bcd(byte asc) {
    byte bcd;
    if ((asc >= '0') && (asc <= '9'))
      bcd = (byte) (asc - '0');
    else if ((asc >= 'A') && (asc <= 'F'))
      bcd = (byte) (asc - 'A' + 10);
    else if ((asc >= 'a') && (asc <= 'f'))
      bcd = (byte) (asc - 'a' + 10);
    else
      bcd = (byte) (asc - 48);
    return bcd;
  }
  /**
   * BCD轉字符串
   */
  public static String bcd2Str(byte[] bytes) {
    char temp[] = new char[bytes.length * 2], val;
    for (int i = 0; i < bytes.length; i++) {
      val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
      temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
      val = (char) (bytes[i] & 0x0f);
      temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
    }
    return new String(temp);
  }
  /**
   * 拆分字符串
   */
  public static String[] splitString(String string, int len) {
    int x = string.length() / len;
    int y = string.length() % len;
    int z = 0;
    if (y != 0) {
      z = 1;
    }
    String[] strings = new String[x + z];
    String str = "";
    for (int i=0; i<x+z; i++) {
      if (i==x+z-1 && y!=0) {
        str = string.substring(i*len, i*len+y);
      }else{
        str = string.substring(i*len, i*len+len);
      }
      strings[i] = str;
    }
    return strings;
  }
  /**
   *拆分數組
   */
  public static byte[][] splitArray(byte[] data,int len){
    int x = data.length / len;
    int y = data.length % len;
    int z = 0;
    if(y!=0){
      z = 1;
    }
    byte[][] arrays = new byte[x+z][];
    byte[] arr;
    for(int i=0; i<x+z; i++){
      arr = new byte[len];
      if(i==x+z-1 && y!=0){
        System.arraycopy(data, i*len, arr, 0, y);
      }else{
        System.arraycopy(data, i*len, arr, 0, len);
      }
      arrays[i] = arr;
    }
    return arrays;
  }
}

java

?
1
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

android

?
1
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");

參考:

http://stackoverflow.com/questions/6069369/rsa-encryption-difference-between-java-and-android
http://stackoverflow.com/questions/2956647/rsa-encrypt-with-base64-encoded-public-key-in-android

補充:關于RSA算法密鑰長度/密文長度/明文長度

1.密鑰長度

rsa算法初始化的時候一般要填入密鑰長度,在96-1024bits間

(1)為啥下限是96bits(12bytes)?因為加密1byte的明文,需要至少1+11=12bytes的密鑰(不懂?看下面的明文長度),低于下限96bits時,一個byte都加密不了,當然沒意義啦
(2)為啥上限是1024(128bytes)?這是算法本身決定的...當然如果某天網上出現了支持2048bits長的密鑰的rsa算法時,你當我廢話吧

2.明文長度

明文長度(bytes) <= 密鑰長度(bytes)-11.這樣的話,對于上限密鑰長度1024bits能加密的明文上限就是117bytes了.
這個規定很狗血,所以就出現了分片加密,網上很流行這個版本.很簡單,如果明文長度大于那個最大明文長度了,我就分片吧,保證每片都別超過那個值就是了.
片數=(明文長度(bytes)/(密鑰長度(bytes)-11))的整數部分+1,就是不滿一片的按一片算

3.密文長度

對,就是這個充滿了謠言,都說密文長度為密鑰長度的一半,經俺驗證,密文長度等于密鑰長度.當然這是不分片情況下的.
分片后,密文長度=密鑰長度*片數

例如96bits的密鑰,明文4bytes
每片明文長度=96/8-11=1byte,片數=4,密文長度=96/8*4=48bytes

又例如128bits的密鑰,明文8bytes
每片明文長度=128/8-11=5bytes,片數=8/5取整+1=2,密文長度=128/8*2=32

注意,對于指定長度的明文,其密文長度與密鑰長度非正比關系.如4bytes的明文,在最短密鑰96bites是,密文長度48bytes,128bits米密鑰時,密文長度為16bytes,1024bits密鑰時,密文長度128bytes.
因 為分片越多,密文長度顯然會變大,所以有人說,那就一直用1024bits的密鑰吧...拜托,現在的機器算1024bits的密鑰還是要點時間滴,別以 為你的cpu很牛逼...那么選個什么值比較合適呢?個人認為是600bits,因為我們對于一個字符串的加密,一般不是直接加密,而是將字符串hash 后,對hash值加密.現在的hash值一般都是4bytes,很少有8bytes,幾十年內應該也不會超過64bytes.那就用64bytes算吧, 密鑰長度就是(64+11)*8=600bits了.

用開源rsa算法的時候,還要注意,那個年代的人把long當4bytes用,如今 放在64位的機器上,就會死循環啊多悲催....因為有個循環里讓一個4bytes做遞減....64位機上long是8bytes,這個循環進去后個把 小時都出不來....所以要注意下哦....同理對于所有年代久遠的開源庫都得注意下...

希望本文所述對大家java程序設計有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 永久免费av片在线观看全网站 | 欧美精品一区二区视频 | 日本不卡二区 | 中文字幕网在线 | 九九精品在线播放 | 一级做人爱c黑人影片 | 国产1区2区3区在线观看 | free性欧美hd另类 | 看黄在线| 亚洲一区二区在线免费 | 人人看人人艹 | 成人免费毛片在线观看 | 欧美顶级毛片在线播放小说 | 欧美a∨亚洲欧美亚洲 | 欧美日韩亚洲精品一区二区三区 | 亚洲精品久久久久久 | av在线免费网 | 亚洲一区免费电影 | 国产免费大片视频 | 九色中文 | 91社| 97伦理| 国产又白又嫩又紧又爽18p | 国产超碰人人爽人人做人人爱 | 美女视频大全网站免费 | 49vv看片免费 | 日本a大片| 国产精品免费观在线 | 国产成人高清在线观看 | 亚洲一区在线视频观看 | 国内精品久久久久久2021浪潮 | 久久精品中文字幕一区二区三区 | 免费一级毛片网站 | 欧美一极视频 | 成人福利视频导航 | 欧美日韩爱爱视频 | 99国产精品国产免费观看 | 久久精品国产久精国产 | 黄色毛片免费视频 | 一二区电影 | 中国国语毛片免费观看视频 |