Data encryption and decryption using RSA public and private key generated by OpenSSL in Java
What is RSA: The RSA public key encryption algorithm was developed in 1977 by Ron Rivest, Adi Shamirh and Len Adleman at (Massachusetts Institute of Technology). RSA naming comes from the names that develop the three of them. RSA is the most influential public key encryption algorithm at present. It is able to resist all cryptographic attacks known so far and has been recommended by ISO as a public key data encryption standard. At present, this encryption method is widely used in online banking, digital signatures and other occasions. The RSA algorithm is based on a very simple number theory fact: it is very easy to multiply two large prime numbers, but it was extremely difficult to factorize the product at that time, so the product can be disclosed as an encryption key.
What is OpenSSL: numerous cryptographic algorithms, public key infrastructure standards, and SSL protocols, and perhaps these interesting features will give you the idea of implementing all of these algorithms and standards. If so, while expressing your admiration, I still can’t help but remind you: This is a daunting process. This work is no longer as simple as reading a few cryptography monographs and protocol documents, but rather understanding every detail of all these algorithms, standards and protocol documents, and implementing these definitions and processes one by one with C characters you may be familiar with. We don't know how much time you'll need to do this fun and terrible job, but it's certainly not a year or two issue. OpenSSL is an algorithm collection that combines many security algorithms, written by two great men, Eric A. Young and Tim J. Hudson, since 1995. Through commands or development libraries, we can easily implement standard public algorithm applications.
One of my hypothetical application background:
With the popularity of mobile Internet, applications developed for mobile devices are emerging one after another. These applications are often accompanied by user registration and password verification functions. There are hidden dangers in security in "network transmission" and "application log access". Passwords are sensitive data for users, and developers need to take security precautions before the application is launched. Improper handling may cause problems such as malicious attacks by business competitors and litigation by third-party partners.
Although RSA algorithms have so many benefits, there is no complete example on the Internet to illustrate how to operate them. Let me introduce it below:
1. Use OpenSSL to generate private and public keys
I am using a Linux system and have the OpenSSL package installed. Please verify that OpenSSL is installed on your machine. The following information should appear when running the command:
[root@chaijunkun ~]# openssl version -a OpenSSL 1.0.0-fips 29 Mar 2010 built on: Wed Jan 25 02:17:15 GMT 2012 platform: linux-x86_64 options: bn(64,64) md2(int) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx) compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DKRB5_MIT -m64 -DL_ENDIAN -DTERMIO -Wall -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -Wa,-noexecstack -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DWHIRLPOOL_ASM OPENSSLDIR: "/etc/pki/tls" engines: aesni dynamic
First generate the private key:
[root@chaijunkun ~]# openssl genrsa -out rsa_private_key.pem 1024 Generating RSA private key, 1024 bit long modulus ..................++++++ ..++++++++ e is 65537 (0x10001)
This command allows openssl to randomly generate a private key, and the encryption length is 1024 bits. Encrypted length refers to the theoretical limit of the maximum allowed "encrypted information" length, that is, the length limit of plain text. As this parameter increases (for example, 2048), the allowed plaintext length will also increase, but it will also cause a rapid increase in computing complexity. The recommended length is 1024 bits (128 bytes).
Let's take a look at the content of the private key:
[root@chaijunkun ~]# cat rsa_private_key.pem -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQChDzcjw/rWgFwnxunbKp7/4e8w/UmXx2jk6qEEn69t6N2R1i/L mcyDT1xr/T2AHGOiXNQ5V8W4iCaaeNawi7aJaRhtVx1uOH/2U378fscEESEG8XDq ll0GCfB1/TjKI2aitVSzXOtRs8kYgGU78f7VmDNgXIlk3gdhnzh+uoEQywIDAQAB AoGAaeKk76CSsp7k90mwyWP18GhLZru+vEhfT9BpV67cGLg1owFbntFYQSPVsTFm U2lWn5HD/IcV+EGaj4fOLXdM43Kt4wyznoABSZCKKxs6uRciu8nQaFNUy4xVeOfX PHU2TE7vi4LDkw9df1fya+DScSLnaDAUN3OHB5jqGL+Ls5ECQQDUfuxXN3uqGYKk znrKj0j6pY27HRfROMeHgxbjnnApCQ71SzjqAM77R3wIlKfh935OIV0aQC4jQRB4 iHYSLl9lAkEAwgh4jxxXeIAufMsgjOi3qpJqGvumKX0W96McpCwV3Fsew7W1/msi suTkJp5BBvjFvFwfMAHYlJdP7W+nEBWkbwJAYbz/eB5NAzA4pxVR5VmCd8cuKaJ4 EgPLwsjI/mkhrb484xZ2VyuICIwYwNmfXpA3yDgQWsKqdgy3Rrl9lV8/AQJAcjLi IfigUr++nJxA8C4Xy0CZSoBJ76k710wdE1MPGr5WgQF1t+P+bCPjVAdYZm4Mkyv0 /yBXBD16QVixjvnt6QJABli6Zx9GYRWnu6AKpDAHd8QjWOnnNfNLQHue4WepEvkm CysG+IBs2GgsXNtrzLWJLFx7VHmpqNTTC8yNmX1KFw== ------END RSA PRIVATE KEY----
The contents are all standard ASCII characters, with obvious marks on the beginning and the ending lines, and the real private key data is irregular characters in the middle.
Supplementary on March 24, 2015: The key file will eventually store the data through Base64 encoding. You can see that the length of each line of the above key file content is very regular. This is due to the provisions in RFC2045: The encoded output stream must be represented in lines of no more than 76 characters each. That is to say, the data encoded by Base64 will not exceed 76 characters per line, and it needs to be divided by row for ultra-long data.
Next, generate the public key based on the private key:
[root@chaijunkun ~]# openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout writing RSA key
Let’s take a look at the contents of the public key:
[root@chaijunkun ~]# cat rsa_public_ley.pem -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChDzcjw/rWgFwnxunbKp7/4e8w /UmXx2jk6qEEn69t6N2R1i/LmcyDT1xr/T2AHGOiXNQ5V8W4iCaaeNawi7aJaRht Vx1uOH/2U378fscEESEG8XDqll0GCfB1/TjKI2aitVSzXOtRs8kYgGU78f7VmDNg XIlk3gdhnzh+uoEQywIDAQAB ----END PUBLIC KEY----
At this time, the private key cannot be used directly, so PKCS#8 encoding is required:
[root@chaijunkun ~]# openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt
The command indicates that the input private key file is rsa_private_key.pem, and the output private key file is pkcs8_rsa_private_key.pem, and no secondary encryption is used (-nocrypt)
Let’s take a look at whether the encoded private key file is different from the previous private key file:
[root@chaijunkun ~]# cat pkcs8_rsa_private_key.pem
-----BEGIN PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKEPNyPD+taAXCfG 6dsqnv/h7zD9SZfHaOTqoQSfr23o3ZHWL8uZzINPXGv9PYAcY6Jc1DlXxbiIJpp4 1rCLtolpGG1XHW44f/ZTfvx+xwQRIQbxcOqWXQYJ8HX9OMojZqK1VLNc61GzyRiA ZTvx/tWYM2BciWTeB2GfOH66gRDLAgMBAAECgYBp4qTvoJKynuT3SbDJY/XwaEtm u768SF9P0GlXrtwYuDWjAVue0VhBI9WxMWZTaVafkcP8hxX4QZqPh84td0zjcq3j DLOegAFJkIorGzq5FyK7ydBoU1TLjFV459c8dTZMTu+LgsOTD11/V/Jr4NJxIudo MBQ3c4cHmOoYv4uzkQJBANR+7Fc3e6oZgqTOesqPSPqljbsdF9E4x4eDFuOecCkJ DvVLOOoAzvtHfAiUp+H3fk4hXRpALiNBEHiIdhIuX2UCQQDCCHiPHFd4gC58yyCM 6Leqkmoa+6YpfRb3oxykLBXcWx7DtbX+ayKy5OQmnkEG+MW8XB8wAdiUl0/tb6cQ FaRvAkBhvP94Hk0DMDinFVHlWYJ3xy4pongSA8vCyMj+aSGtvjzjFnZXK4gIjBjA 2Z9ekDfIOBBawqp2DLdGuX2VXz8BAkByMuIh+KBSv76cnEDwLhfLQJlKgEnvqTvX TB0TUw8avlaBAXW34/5sI+NUB1hmbgyTK/T/IFcEPXpBWLGO+e3pAkAGWLpnH0Zh Fae7oAqkMAd3xCNY6ec180tAe57hZ6kS+SYLKwb4gGzYaCxc22vMtYksXHtUeamo 1NMLzI2ZfUoX -----END PRIVATE KEY----
At this point, the available key pairs have been generated. The private key uses pkcs8_rsa_private_key.pem, and the public key uses rsa_public_key.pem.
Added on May 20, 2014: Recently, I encountered the need for RSA encryption, and the other party required that they could only use the private key file that was not encoded by PKCS#8 generated in the first step. Later, I checked the relevant documents and learned that the private key file generated in the first step is PKCS#1 format. This format is actually supported by Java, but I just write two more lines of code:
RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(priKeyData)); RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent()); KeyFactory keyFactory= KeyFactory.getInstance("RSA"); PrivateKey priKey= keyFactory.generatePrivate(rsaPrivKeySpec); First read out the private key file of PKCS#1 (note that you remove the comment content at the beginning of the minus sign), and then use Base64 to decode the read string to get priKeyData, which is the parameter in the first line of code. The last line gets the private key. There is no difference in the next usage.
References: https://community.Oracle.com/thread/1529240?start=0&tstart=0
2. Write Java code to test it
Supplementary February 23, 2012: The standard JDK is only specified in the JCE (JCE (JCE (Java Cryptography Extension) is a set of packages that provide frameworks and implementations for encryption, key generation and negotiation, and Message Authentication Code (MAC) algorithms. It provides encryption support for symmetric, asymmetry, block and stream ciphers, and it also supports secure flow and sealed objects.) interfaces, but internal implementations need to be provided by themselves or by a third party. Therefore, we use the open source JCE implementation package of bouncycastle here, the download address is: http://bouncycastle.org/latest_releases.html, I am using bcprov-jdk16-146.jar, which is used in the JDK1.6 environment. If you need implementations under other JDK versions, you can find the corresponding version in the previous download page.
Let's take a look at the code I implemented:
package net.csdn.blog.chaijunkun; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import org.bouncycastle.jce.provider.BouncyCastleProvider; import sun.misc.BASE64Decoder; public class RSAEncrypt { private static final String DEFAULT_PUBLIC_KEY= "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChDzcjw/rWgFwnxunbKp7/4e8w" + "/r" + "/UmXx2jk6qEEn69t6N2R1i/LmcyDT1xr/T2AHGOiXNQ5V8W4iCaaeNawi7aJaRht" + "/r" + "Vx1uOH/2U378fscEESEG8XDqll0GCfB1/TjKI2aitVSzXOtRs8kYgGU78f7VmDNg" + "/r" + "XIlk3gdhnzh+uoEQywIDAQAB" + "/r"; private static final String DEFAULT_PRIVATE_KEY= "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKEPNyPD+taAXCfG" + "/r" + "6dsqnv/h7zD9SZfHaOTqoQSfr23o3ZHWL8uZzINPXGv9PYAcY6Jc1DlXxbiIJpp4" + "/r" + "1rCLtolpGG1XHW44f/ZTfvx+xwQRIQbxcOqWXQYJ8HX9OMojZqK1VLNc61GzyRiA" + "/r" + "ZTvx/tWYM2BciWTeB2GfOH66gRDLAgMBAAECgYBp4qTvoJKynuT3SbDJY/XwaEtm" + "/r" + "u768SF9P0GlXrtwYuDWjAVue0VhBI9WxMWZTaVafkcP8hxX4QZqPh84td0zjcq3j" + "/r" + "DLOegAFJkIorGzq5FyK7ydBoU1TLjFV459c8dTZMTu+LgsOTD11/V/Jr4NJxIudo" + "/r" + "MBQ3c4cHmOoYv4uzkQJBANR+7Fc3e6oZgqTOesqPSPqljbsdF9E4x4eDFuOecCkJ" + "/r" + "DvVLOOoAzvtHfAiUp+H3fk4hXRpALiNBEHiIdhIuX2UCQQDCCHiPHFd4gC58yyCM" + "/r" + "6Leqkmoa+6YpfRb3oxykLBXcWx7DtbX+ayKy5OQmnkEG+MW8XB8wAdiUl0/tb6cQ" + "/r" + "FaRvAkBhvP94Hk0DMDinFVHlWYJ3xy4pongSA8vCyMj+aSGtvjzjFnZXK4gIjBjA" + "/r" + "2Z9ekDfIOBBawqp2DLdGuX2VXz8BAkByMuIh+KBSv76cnEDwLhfLQJlKgEnvqTvX" + "/r" + "TB0TUw8avlaBAXW34/5sI+NUB1hmbgyTK/T/IFcEPXpBWLGO+e3pAkAGWLpnH0Zh" + "/r" + "Fae7oAqkMAd3xCNY6ec180tAe57hZ6kS+SYLKwb4gGzYaCxc22vMtYksXHtUeamo" + "/r" + "1NMLzI2ZfUoX" + "/r"; /** * Private key*/ private RSAPrivateKey privateKey; /** * Public key*/ private RSAPublicKey publicKey; /** * Private set to string*/ private static final char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * Get the private key* @return Current private key object*/ public RSAPrivateKey getPrivateKey() { return privateKey; } /** * Get the public key* @return Current public key object*/ public RSAPublicKey getPublicKey() { return publicKey; } /** * Randomly generated key pair*/ public void genKeyPair(){ KeyPairGenerator keyPairGen= null; try { keyPairGen= KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyPairGen.initialize(1024, new SecureRandom()); KeyPair keyPair= keyPairGen.generateKeyPair(); this.privateKey= (RSAPrivateKey) keyPair.getPrivate(); this.publicKey= (RSAPublicKey) keyPair.getPublic(); } /** * Load the public key from the input stream in the file* @param in public key input stream* @throws Exception Exception generated when loading the public key*/ public void loadPublicKey(InputStream in) throws Exception{ try { BufferedReader br= new BufferedReader(new InputStreamReader(in)); String readLine= null; StringBuilder sb= new StringBuilder(); while((readLine= br.readLine())!=null){ if(readLine.charAt(0)=='-'){ continue; }else{ sb.append(readLine); sb.append('/r'); } } loadPublicKey(sb.toString()); } catch (IOException e) { throw new Exception("Public Key Data Stream Read Error"); } catch (NullPointerException e) { throw new Exception("Public Key Input Stream is empty"); } } /** * Load the public key from a string* @param publicKeyStr Public Key Data String* @throws Exception Exception generated when loading the public key*/ public void loadPublicKey(String publicKeyStr) throws Exception{ try { BASE64Decoder base64Decoder= new BASE64Decoder(); byte[] buffer= base64Decoder.decodeBuffer(publicKeyStr); KeyFactory keyFactory= KeyFactory.getInstance("RSA"); X509EncodedKeySpec keySpec= new X509EncodedKeySpec(buffer); this.publicKey= (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("Nothing algorithm"); } catch (InvalidKeySpecException e) { throw new Exception("Public key illegal"); } catch (IOException e) { throw new Exception("Public key data content read error"); } catch (NullPointerException e) { throw new Exception("Public key data is empty"); } } /** * Load the private key from the file* @param keyFileName Private key file name* @return Whether it is successful* @throws Exception */ public void loadPrivateKey(InputStream in) throws Exception{ try { BufferedReader br= new BufferedReader(new InputStreamReader(in)); String readLine= null; StringBuilder sb= new StringBuilder(); while((readLine= br.readLine())!=null){ if(readLine.charAt(0)=='-'){ continue; }else{ sb.append(readLine); sb.append('/r'); } } loadPrivateKey(sb.toString()); } catch (IOException e) { throw new Exception("Private Key Data Read Error"); } catch (NullPointerException e) { throw new Exception("Private Key Input Stream is empty"); } } public void loadPrivateKey(String privateKeyStr) throws Exception{ try { BASE64Decoder base64Decoder= new BASE64Decoder(); byte[] buffer= base64Decoder.decodeBuffer(privateKeyStr); PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory= KeyFactory.getInstance("RSA"); this.privateKey= (RSAPrivateKey) keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("Nothing this algorithm"); } catch (InvalidKeySpecException e) { throw new Exception("Private key illegal"); } catch (IOException e) { throw new Exception("Private key data content read error"); } catch (NullPointerException e) { throw new Exception("Private key data is empty"); } } /** * Encryption process* @param publicKey public key* @param plainTextData plaintext data* @return * @throws Exception Exception information during encryption process*/ public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception{ if(publicKey== null){ throw new Exception("Encryption public key is empty, Please set "); } Cipher cipher= null; try { cipher= Cipher.getInstance("RSA", new BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] output= cipher.doFinal(plainTextData); return output; } catch (NoSuchAlgorithmException e) { throw new Exception("NoThis encryption algorithm"); } catch (NoSuchPaddingException e) { e.printStackTrace(); return null; }catch (InvalidKeyException e) { throw new Exception("Encryption public key is illegal, please check"); } catch (IllegalBlockSizeException e) { throw new Exception("Placktext length is illegal"); } catch (BadPaddingException e) { throw new Exception("Placktext data is corrupted"); } } /** * Decryption process* @param privateKey private key* @param cipherData ciphertext data* @return plaintext* @throws Exception Exception information during decryption process*/ public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception{ if (privateKey== null){ throw new Exception("Decrypt private key is empty, please set"); } Cipher cipher= null; try { cipher= Cipher.getInstance("RSA", new BouncyCastleProvider()); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] output= cipher.doFinal(cipherData); return output; } catch (NoSuchAlgorithmException e) { throw new Exception("Nothing decryption algorithm"); } catch (NoSuchPaddingException e) { e.printStackTrace(); return null; }catch (InvalidKeyException e) { throw new Exception("Decryption private key is illegal, please check"); } catch (IllegalBlockSizeException e) { throw new Exception("Cryptotext length is illegal"); } catch (BadPaddingException e) { throw new Exception("Cryptotext data is corrupted"); } } /** * Byte data to hexadecimal string* @param data Input data* @return Hexadecimal content*/ public static String byteArrayToString(byte[] data){ StringBuilder stringBuilder= new StringBuilder(); for (int i=0; i<data.length; i++){ //Take out the high four digits of the byte as index to get the corresponding hexadecimal identifier Note that the unsigned right shift stringBuilder.append(HEX_CHAR[(data[i] & 0xf0)>>> 4]); //Take out the lower four bits of the byte as index to get the corresponding hexadecimal identifier stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]); if (i<data.length-1){ stringBuilder.append(' '); } } return stringBuilder.toString(); } public static void main(String[] args){ RSAEncrypt rsaEncrypt= new RSAEncrypt(); //rsaEncrypt.genKeyPair(); //Load the public key try { rsaEncrypt.loadPublicKey(RSAEncrypt.DEFAULT_PUBLIC_KEY); System.out.println("Loading the public key successfully"); } catch (Exception e) { System.err.println(e.getMessage()); System.err.println("Loading the public key failed"); } //Loading the private key try { rsaEncrypt.loadPrivateKey(RSAEncrypt.DEFAULT_PRIVATE_KEY); System.out.println("Loading the private key successfully"); } catch (Exception e) { System.err.println(e.getMessage()); System.err.println("Loading private key failed"); } //Test string String encryptStr= "Test String chaijunkun"; try { //Encrypt byte[] cipher = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), encryptStr.getBytes()); //Decrypt byte[] plainText = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher); System.out.println("ciphertext length:"+ cipher.length); System.out.println(RSAEncrypt.byteArrayToString(cipher)); System.out.println("plaintext length:"+ plainText.length); System.out.println(RSAEncrypt.byteArrayToString(plainText)); System.out.println(new String(plainText)); } catch (Exception e) { System.err.println(e.getMessage()); } } } In the code, I provide two ways to load public and private keys.
Read by stream: suitable for the method of obtaining InputStream by ID indexing resources in Android applications;
Read by string: As shown in the code, store the key contents by line into static constants and import the key by String type.
Run the above code and the following information will be displayed:
1 64 57 c8 e3 46 a7 ce 57 31 ac cd 21 89 89 8f c1 24 c1 22 0c cb 70 6a 0d fa c9 38 80 ba 2e e1 29 02 ed 45 9e 88 e9 23 09 87 af ad ab ac cb 61 03 3c a1 81 56 a5 de c4 79 aa 3e 48 ee 30 3d bc 5b 47 50 75 9f fd 22 87 9e de b1 f4 e8 b2 Plain text length:22 54 65 73 74 20 53 74 72 69 6e 67 20 63 68 61 69 6a 75 6e 6b 75 6e Test String chaijunkun
In the main function I commented out "rsaEncrypt.genKeyPair()", which is used to randomly generate key pairs (only generate, use, not store). When the file key is not used, you can comment the code that loads the key, enable this method, or run the code.
The difference between loading a public key and loading a private key is that when the public key is loaded, X509EncodedKeySpec (X509-encoded Key instruction), and when the private key is loaded, PKCS8EncodedKeySpec (PKCS#8-encoded Key instruction).
Added on February 22, 2012: During the development of Android software, it was found that the above code did not work properly. The main reason is that the sun.misc.BASE64Decoder class does not exist in the Android development package. Therefore, you need to look for the source code of rt.jar on the Internet. As for the source code in JDK's src.zip, this is only part of the source code in JDK, and the codes of the above classes do not exist. After searching and adding, the above code works well in android applications. This contains the corresponding code for this class. In addition, this class also depends on CEFormatException, CEStreamExhausted, CharacterDecoder and CharacterEncoder classes and exception definitions.
Added on February 23, 2012: At first, I wrote this article to implement RSA encryption and decryption without relying on any third-party packages, but I encountered problems later. Since a Cipher object must be created in both the encryption method encrypt and the decrypt method decrypt, this object can only obtain instances through getInstance. There are two types of it: the first is to specify only the algorithm and not the provider; the second is to specify both. At first, the code can still run, but you will find that the result of each encryption is different. Later, it was discovered that the public and private key used by the Cipher object was randomly generated internally, not the public and private key specified in the code. Strangely, this code that does not specify a Provider can run through android applications, and the result of each encryption is the same. I think that in addition to some system development functions in the Android SDK, it also implements the functions of the JDK. It may have provided corresponding providers in its own JDK, which makes the encryption result the same every time. When I added the bouncycastle provider like the sample code on the Internet, the results of each encryption are the same.
Thank you for reading, I hope it can help you. Thank you for your support for this site!