Java OpenSSL generates RSA public and private keys for data encryption and decryption

  • 2020-05-19 04:54:53
  • OfStack

In Java, RSA public and private keys generated by OpenSSL are used for data encryption and decryption

What is RSA? The RSA public key encryption algorithm was developed by Ron Rivest, Adi Shamirh, and LenAdleman (MIT) in 1977. RSA is named after the person who developed them. RSA is currently the most influential public key encryption algorithm, which can resist all known password attacks so far. It has been recommended as the public key data encryption standard by ISO. At present, the encryption method is widely used in online banking, digital signatures and other occasions. The RSA algorithm is based on a simple 10-point number theory fact: it is easy to multiply two large prime Numbers by 10 points, but at the time it was extremely difficult to factor the product, so the product could be exposed as an encryption key.

What OpenSSL is: a number of cryptographic algorithms, public key infrastructure standards, and the SSL protocol, and perhaps some of these interesting features will give you the idea of implementing all of these algorithms and standards. If so, while I admire you, I can't help but remind you that this is a daunting process. The job is no longer to simply read a few cryptographic books and protocol documents, but to understand every single detail of all these algorithms, standards, and protocol documents, and to implement these definitions and procedures one by one using the C language characters that you may be familiar with. We don't know how much time you'll need to do this interesting and scary job, but it's certainly not a question of one or two years. OpenSSL is a collection of security algorithms that has been compiled by Eric A.Young and Tim J.Hudson since 1995. Standard open algorithm applications can be easily implemented using commands or development libraries.

One of my hypothesis application background:

With the popularity of mobile Internet, the applications developed for mobile devices are also emerging in an endless stream. These apps are often accompanied by user registration and password verification." There are security risks in both network transport and application log access. Password as user's sensitive data, developers need to make security precautions before the application goes online. Improper handling may cause problems such as malicious attacks from commercial competitors and lawsuits from third party partners.

Despite all the benefits of the RSA algorithm, there is no complete example on the web that shows how to do this. Let me introduce 1:

1. Use OpenSSL to generate private and public keys

I am using Linux system and have installed OpenSSL software package. Please verify that OpenSSL has been installed on your machine. The following information should appear in the running 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  

To 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 causes openssl to randomly generate a copy of the private key with a length of 1024 bits. Encryption length refers to the theoretical maximum allowed "encrypted information" length limit, that is, the length of the plaintext limit. As this parameter increases (say 2048), the length of the allowed plaintext increases, but the computational complexity increases dramatically. The recommended length of 1 is 1024 bits (128 bytes).

Let's look at the contents 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 content is all standard ASCII characters, the first and last lines are clearly marked, and the real private key data is irregular characters in the middle.

March 24, 2015 update: the key file finally stores the data through Base64 encoding. You can see that the contents of the key file above have a regular length of each line. This is due to RFC2045: The encoded output stream be represented in of no more than 76 characters each. That is to say, the data encoded by Base64 does not exceed 76 characters per line at most, and for super-long data, it needs to be split by line.

Next, generate the public key according to the private key:


[root@chaijunkun ~]# openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout 
 writing RSA key  

Let's look at the contents of the public key again:


[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 without any two-pass encryption (-nocrypt)

Let's look at 1 again. Is the encoded private key file 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 pair is generated, the private key is pkcs8_rsa_private_key.pem, and the public key is rsa_public_key.pem.

Added May 20, 2014: recently I encountered another request for RSA encryption, which requires that only the private key file generated in step 1 not encoded with PKCS#8 be used. Later, I checked relevant literature and learned that the code of the private key file generated in step 1 is in PKCS#1 format, which is actually supported by Java with two more lines of code written:


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, the private key file of PKCS#1 is read out (note removing the comment at the beginning of the minus sign), and then the read string is decoded using Base64 to get priKeyData, which is the parameter in line 1. The last line gets the private key. The following usage makes no difference.
Reference: https: / / community Oracle. com/thread / 1529240 & # 63; start = 0 & tstart = 0

2. Wrote the actual test of Java code

Note: JCE(JCE (Java Cryptography Extension) is a package that provides the framework and implementation for encryption, key generation and negotiation, and Message Authentication Code(MAC) algorithms. It provides encryption support for symmetric, asymmetric, block and stream passwords, and it also supports secure streams and sealed objects. Interface, but the internal implementation needs to be provided by itself or a third party. So we use bouncycastle here open source JCE implementation package, download address: http: / / bouncycastle org/latest_releases html, I use a bcprov - jdk16-146. jar, this is the JDK1. 6 environment use. If you need another JDK version of the implementation, you can find the corresponding version in the previous download page.

Let's take a look at 1 of 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"; 
 
  /** 
   *  The private key  
   */ 
  private RSAPrivateKey privateKey; 
 
  /** 
   *  The public key  
   */ 
  private RSAPublicKey publicKey; 
   
  /** 
   *  A dedicated collection of bytes of data to strings  
   */ 
  private static final char[] HEX_CHAR= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 
   
 
  /** 
   *  Access to the private key  
   * @return  The current private key object  
   */ 
  public RSAPrivateKey getPrivateKey() { 
    return privateKey; 
  } 
 
  /** 
   *  To obtain the public key  
   * @return  The current public key object  
   */ 
  public RSAPublicKey getPublicKey() { 
    return publicKey; 
  } 
 
  /** 
   *  Generate the key pair randomly  
   */ 
  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  An exception that occurs when the public key is loaded  
   */ 
  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(" Error reading public key data stream "); 
    } catch (NullPointerException e) { 
      throw new Exception(" The public key input stream is empty "); 
    } 
  } 
 
 
  /** 
   *  Load the public key from the string  
   * @param publicKeyStr  Public key data string  
   * @throws Exception  An exception that occurs when the public key is loaded  
   */ 
  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(" Without this algorithm "); 
    } catch (InvalidKeySpecException e) { 
      throw new Exception(" The public key of illegal "); 
    } catch (IOException e) { 
      throw new Exception(" Error reading public key data content "); 
    } catch (NullPointerException e) { 
      throw new Exception(" The public key data is empty "); 
    } 
  } 
 
  /** 
   *  Load the private key from the file  
   * @param keyFileName  Private key file name  
   * @return  The success of  
   * @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(" Error reading private key data "); 
    } catch (NullPointerException e) { 
      throw new Exception(" The 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(" Without this algorithm "); 
    } catch (InvalidKeySpecException e) { 
      throw new Exception(" The private key is illegal "); 
    } catch (IOException e) { 
      throw new Exception(" Error reading private key data content "); 
    } catch (NullPointerException e) { 
      throw new Exception(" The private key data is empty "); 
    } 
  } 
 
  /** 
   *  The encryption process  
   * @param publicKey  The public key  
   * @param plainTextData  Clear data  
   * @return 
   * @throws Exception  Exception information during encryption  
   */ 
  public byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception{ 
    if(publicKey== null){ 
      throw new Exception(" The encrypted public key is empty ,  Please set up "); 
    } 
    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(" There is no encryption algorithm "); 
    } catch (NoSuchPaddingException e) { 
      e.printStackTrace(); 
      return null; 
    }catch (InvalidKeyException e) { 
      throw new Exception(" Illegal encryption of public key , Please check the "); 
    } catch (IllegalBlockSizeException e) { 
      throw new Exception(" Illegal plaintext length "); 
    } catch (BadPaddingException e) { 
      throw new Exception(" The plaintext data is corrupted "); 
    } 
  } 
 
  /** 
   *  The decryption process  
   * @param privateKey  The private key  
   * @param cipherData  Cipher data  
   * @return  clear  
   * @throws Exception  Abnormal information during decryption  
   */ 
  public byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception{ 
    if (privateKey== null){ 
      throw new Exception(" The decryption private key is empty ,  Please set up "); 
    } 
    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(" There is no decryption algorithm "); 
    } catch (NoSuchPaddingException e) { 
      e.printStackTrace(); 
      return null; 
    }catch (InvalidKeyException e) { 
      throw new Exception(" Illegal decryption of private key , Please check the "); 
    } catch (IllegalBlockSizeException e) { 
      throw new Exception(" Illegal ciphertext length "); 
    } catch (BadPaddingException e) { 
      throw new Exception(" Ciphertext data has been corrupted "); 
    }     
  } 
 
   
  /** 
   *  Byte data transfer 106 Base string  
   * @param data  The input data  
   * @return 106 Hexadecimal content  
   */ 
  public static String byteArrayToString(byte[] data){ 
    StringBuilder stringBuilder= new StringBuilder(); 
    for (int i=0; i<data.length; i++){ 
      // Extract the height of the byte 4 position   Get the corresponding as the index 106 Base identifier   Notice the unsigned shift to the right  
      stringBuilder.append(HEX_CHAR[(data[i] & 0xf0)>>> 4]); 
      // Take the low of the byte 4 position   Get the corresponding as the index 106 Base 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(" Public key loaded successfully "); 
    } catch (Exception e) { 
      System.err.println(e.getMessage()); 
      System.err.println(" Failed to load public key "); 
    } 
 
    // Load the private key  
    try { 
      rsaEncrypt.loadPrivateKey(RSAEncrypt.DEFAULT_PRIVATE_KEY); 
      System.out.println(" The private key was loaded successfully "); 
    } catch (Exception e) { 
      System.err.println(e.getMessage()); 
      System.err.println(" Failed to load the private key "); 
    } 
 
    // Test string  
    String encryptStr= "Test String chaijunkun"; 
 
    try { 
      // encryption  
      byte[] cipher = rsaEncrypt.encrypt(rsaEncrypt.getPublicKey(), encryptStr.getBytes()); 
      // decryption  
      byte[] plainText = rsaEncrypt.decrypt(rsaEncrypt.getPrivateKey(), cipher); 
      System.out.println(" The length of the cipher :"+ cipher.length); 
      System.out.println(RSAEncrypt.byteArrayToString(cipher)); 
      System.out.println(" Clear the 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 the public key and the private key.
Read by stream: it is suitable to get InputStream by ID index resource in Android application;
Read by string: as shown in the code, store the key content by line into a static constant, and import the key by type String.

Running the above code will display the following information:


[root@chaijunkun ~]# openssl genrsa -out rsa_private_key.pem 1024 
Generating RSA private key, 1024 bit long modulus 
.......................++++++ 
..++++++ 
e is 65537 (0x10001) 
0

I commented out "rsaEncrypt.genKeyPair ()" in the main function, which is used to randomly generate key pairs (generate, use, not store). When the file key is not used, you can comment the code for the key, enable this method, or run through the code.
The difference between loading the public key and loading the private key is that the public key is loaded using X509EncodedKeySpec (X509 en207en instruction), while the private key is loaded using PKCS8EncodedKeySpec (PKCS#8 en211en instruction).

On February 22, 2012, added in the process of android software development, the code above is found to be unable to work properly, the main reason is that sun. misc. BASE64Decoder class in android does not exist in the development kit. Therefore, we need to look for the source code of rt.jar on the Internet. As for the source code of JDK's src.zip, this is only part of the source code of JDK. After searching and adding, the above code works well in the android application. It contains the corresponding code for this class. This class also depends on the CEFormatException, CEStreamExhausted, CharacterDecoder, and CharacterEncoder classes and exception definitions.

At first, I wrote this article not to rely on any third party package to achieve the encryption and decryption of RSA, but later I encountered problems. Since an Cipher object is created in both the encryption method encrypt and decryption method decrypt, this object can only get an instance through getInstance. It comes in two varieties: the first specifies only the algorithm, not the provider Provider; The second one is going to be both. The code will still work if you don't specify it at first, but you'll notice that the result is different every time you encrypt it. Later analysis revealed that the public-private key used by the Cipher object was generated internally and randomly, not the public-private key specified in the code. Strangely, this code that does not specify Provider works in android applications, and the result is the same every time. I think that in addition to some development functions of the system, android's SDK has also realized JDK's functions. It may have provided the corresponding Provider in its own JDK, so that the encryption result is the same every time. When I added bouncycastle's Provider like the sample code on the web, sure enough, the result was the same every time.

Thank you for reading, I hope to help you, thank you for your support of this site!


Related articles: