一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

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程序設計有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 古代双性美人被老糟蹋 | 亚洲阿v天堂2018在线观看 | 国产小视频在线播放 | 99精品视频免费 | 国产在线观看91 | videos变态极端 | gogort99人体专业网站 | 精品久久香蕉国产线看观看麻豆 | 国内小情侣一二三区在线视频 | 日产精品卡一卡2卡三卡乱码工厂 | 久久毛片网站 | 日本xxx在线观看免费播放 | 男女做污事 | 40岁女人三级全黄 | 日本视频一区在线观看免费 | 好大好深视频 | 四虎影视永久在线 | 亚洲四虎影院 | 国产美女亚洲精品久久久综合91 | 亚洲男人天堂a | 亚洲精品国产一区二区第一页 | 9丨精品国产高清自在线看 9久热这里只有精品免费 | 亚洲色图欧美视频 | 久久久96| 四虎免费影院ww4164h | 欧美一二区视频 | 国产精品视频一区二区三区不卡 | 滑进了柔佳火热紧夹的 | 二区三区视频 | 欧美整片完整片视频在线 | 春宵福利网站在线观看 | 九九九九九热 | 高清在线免费 | 91最新入口 | 黑人好大 | 国产欧美国产精品第一区 | 超级碰在线视频 | 99在线观看视频免费 | 俄罗斯毛片免费大全 | 掀开奶罩边躁狠狠躁软学生 | 成年性生交大片免费看 |