Android RSA Data encryption and decryption introduction and use of examples _android

Source: Internet
Author: User
Tags decrypt asymmetric encryption

RSA encryption

RSA is the most influential public-key encryption algorithm, and RSA is the first algorithm that can be used both for data encryption and digital signature. The algorithm is based on a very simple number theory fact: it is easy to multiply two large primes, but it is extremely difficult to factorization the product, so you can expose the product as an encryption key, a public key, and two large primes as private keys. The public key is available for anyone to use, and the private key is owned by itself for decryption.

The principle of RSA algorithm

1. Randomly selects two big prime numbers p and q,p not equal to Q, calculates N=PQ;

2. Select a natural number greater than 1 less than n e,e must be with (p-1) (q-1) the mutual element.

3. Use the formula to calculate D:DXE = 1 (mod (p-1) (q-1)).

4. Destroy P and Q.

The resulting N and E is the "public key", D is the "private key", the sender uses N to encrypt the data, and the receiver only uses D to unlock the data content.

RSA security relies on a large number of decomposition, n less than 1024 bits has proven to be unsafe, and since the RSA algorithm is based on a large number of computations, making RSA as fast as possible more than DES, which is the biggest drawback of RSA, it is usually only used to encrypt small amounts of data or cryptographic keys. But RSA is still a high strength algorithm.

RSA uses

First generate the secret key pair

  /**
   * Randomly generated RSA key pair
   *
   * @param keylength key length, Range: 512~2048
   *         General 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;
    }
  }

Specific encryption implementation:

Public Key Cryptography

  /**
   * Encrypt the string with public key
   * *
   @param data Original * *
  byte[static Encryptbypublickey (byte[) data, byte[] PublicKey) throws Exception {
    //Get public key
    x509encodedkeyspec keyspec = new X509encodedkeyspec (publickey);
    Keyfactory KF = Keyfactory.getinstance (RSA);
    PublicKey keypublic = Kf.generatepublic (keyspec);
    Encrypted data
    Cipher CP = Cipher.getinstance (ecb_pkcs1_padding);
    Cp.init (Cipher.encrypt_mode, keypublic);
    return cp.dofinal (data);
  }

Private key encryption

  /**
   * Private key encryption * @param data to be
   encrypted *
   @param privatekey Key
   * @return byte[] Encrypted data
  /Public Static byte[] Encryptbyprivatekey (byte[] data, byte[] privatekey) throws Exception {
    //Get private key
    Pkcs8encodedkeyspec Keyspec = new Pkcs8encodedkeyspec (privatekey);
    Keyfactory KF = Keyfactory.getinstance (RSA);
    Privatekey keyprivate = kf.generateprivate (keyspec);
    Data encryption
    Cipher Cipher = cipher.getinstance (ecb_pkcs1_padding);
    Cipher.init (Cipher.encrypt_mode, keyprivate);
    return cipher.dofinal (data);
  }

Public Key decryption

 /**
   * Public Key decryption * * @param data to be   decrypted
   * @param publickey key
   * @return byte[] Decrypt data
  Static byte[] Decryptbypublickey (byte[] data, byte[] publickey) throws Exception {
    //Get public key
    X509encodedkeyspec Keyspec = new X509encodedkeyspec (publickey);
    Keyfactory KF = Keyfactory.getinstance (RSA);
    PublicKey keypublic = Kf.generatepublic (keyspec);
    Data decryption
    Cipher Cipher = cipher.getinstance (ecb_pkcs1_padding);
    Cipher.init (Cipher.decrypt_mode, keypublic);
    return cipher.dofinal (data);
  }

Private key decryption

 /**
   * Using the private key for decryption
  /public static byte[] Decryptbyprivatekey (byte[] encrypted, byte[] privatekey) throws Exception {
    //Get private key
    pkcs8encodedkeyspec keyspec = new Pkcs8encodedkeyspec (privatekey);
    Keyfactory KF = Keyfactory.getinstance (RSA);
    Privatekey keyprivate = kf.generateprivate (keyspec);

    Decrypt data
    Cipher CP = Cipher.getinstance (ecb_pkcs1_padding);
    Cp.init (Cipher.decrypt_mode, keyprivate);
    byte[] arr = cp.dofinal (encrypted);
    return arr;
  }

Several global variable explanations:

  public static final String RSA = "RSA";//Asymmetric Encryption key algorithm public
  static final string ecb_pkcs1_padding = "Rsa/ecb/pkcs1paddi Ng "//Encryption fill mode public
  static final int default_key_size = 2048;//secret key default length public
  static final byte[] Default_split =" #PART # ". GetBytes ();  When the content to be encrypted exceeds buffersize, Partsplit is used to block the encryption public
  static final int default_buffersize = (DEFAULT_KEY_SIZE/8)-11;// The current secret key supports the maximum number of bytes encrypted

Encrypt fill mode

Previously thought that these operations will be able to achieve RSA encryption and decryption, think everything is all right, oh, this thing is not finished, tragedy or happened, Android here encrypted data, the server can not decrypt, the original Android system RSA implementation is "rsa/none/nopadding "And the standard JDK implementation is" rsa/none/pkcs1padding ", which causes the inability to decrypt on the server after encryption on the Android computer, so be sure to pay attention to this when it is implemented.

Implementing segmented encryption

I got it. After the filling method and confident that all is well, but the accident or happened, the RSA asymmetric encryption content length is limited, 1024-bit key can only encrypt 127-bit data, otherwise it will be an error ( Javax.crypto.IllegalBlockSizeException:Data must is longer than 117 bytes), RSA is a commonly used asymmetric encryption algorithm. There was an "incorrect length" exception during the recent use, which was found to be caused by an unusually long amount of data to be encrypted. The RSA algorithm stipulates that the number of bytes to be encrypted cannot exceed the length of the key by 8 minus 11 (that is, KEYSIZE/8-11), and the number of bytes encrypted with the cipher is exactly the length of the key divided by 8 (that is, KEYSIZE/8).

Public-Key fragment encryption

/** * Using public key to segment the string (* * * * * * * * * 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; }

Private key fragment encryption

 /** * @param data to encrypt the raw data * @param privatekey secret key/public static byte[] Encryptbyprivatek
    Eyforspilt (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; }

Public key fragmentation decryption

 /** * Public Key Fragment decryption * * @param encrypted data to be decrypted * @param publickey Key * * * * byte[] Decryptbypublicke
    Yforspilt (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) {//to the last byte[of data] 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]) {//This is with split[0] opening if (Splitlen > 1) {if (i + Splitlen < Datalen) {//No more than
                The scope of data for (int j = 1; J < Splitlen J + +) {if (Default_split[j]!= encrypted[i + j]) {
              Break } if (j = = splitLen-1) {//Verify that the last of the split has no break, it indicates that the split segment has been confirmed Ismatchs
              Plit = true;
        else {//split is only one bit, and has already matched 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; }

Private key fragment decryption

 /** * Using private key to decrypt */public static byte[] Decryptbyprivatekeyforspilt (byte[] encrypted, byte[] privatekey) thr
    OWS 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) {//to the last byte[of data] 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]) {//This is split[0] opening if (spliTlen > 1) {if (i + Splitlen < Datalen) {//No Beyond data for (int j = 1; J < sp Litlen;
              J + +) {if (Default_split[j]!= encrypted[i + j]) {break; } if (j = = splitLen-1) {//Verify that the last of the split has no break, it indicates that the split segment has been confirmed Ismatchs
              Plit = true;
        else {//split is only one bit, and has already matched 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; }

This finally solves the problem that meets, the project uses is the client public key encryption, the server private key decrypts, the server developer says is for the efficiency consideration, therefore still wrote a program to test the real efficiency

Step one: Prepare 100 Object data

    List<person> personlist=new arraylist<> ();
    The maximum number of data bars for int testmaxcount=100;//test
    //Add test data for
    (int i=0;i<testmaxcount;i++) {person person
      =new person ();
      Person.setage (i);
      Person.setname (string.valueof (i));
      Personlist.add (person);
    }
    Fastjson generates JSON data

    String Jsondata=jsonutils.objecttojsonforfastjson (personlist);

    LOG.E ("Mainactivity", "pre-encrypted JSON data---->" +jsondata);
    LOG.E ("Mainactivity", "encrypt front json data length---->" +jsondata.length ());

The second step is to generate the secret key pair

    KeyPair Keypair=rsautils.generatersakeypair (rsautils.default_key_size);
    Public key Rsapublickey PublicKey = (rsapublickey) keypair.getpublic ();
Private key Rsaprivatekey Privatekey = (rsaprivatekey) keypair.getprivate ();
    Next, use the public key encryption private key to decrypt the private key encryption public key decryption//Public key encryption Long Start=system.currenttimemillis ();
    Byte[] encryptbytes= rsautils.encryptbypublickeyforspilt (Jsondata.getbytes (), publickey.getencoded ());
    Long End=system.currenttimemillis ();
    LOG.E ("Mainactivity", "public key encryption time-consuming cost time---->" + (End-start));
    String Encrystr=base64encoder.encode (encryptbytes);
    LOG.E ("Mainactivity", "encrypted JSON data--1-->" +ENCRYSTR);
    LOG.E ("Mainactivity", "encrypted JSON data length--1-->" +encrystr.length ());
    Private key decryption Start=system.currenttimemillis (); Byte[] decryptbytes= rsautils.decryptbyprivatekeyforspilt (base64decoder.decodetobytes (ENCRYSTR),
    Privatekey.getencoded ());
    String Decrystr=new string (decryptbytes);
    End=system.currenttimemillis (); LOG.E ("Mainactivity", "private key decryption time consuming Cost time----> "+ (End-start));

    LOG.E ("Mainactivity", "decrypted JSON data--1-->" +DECRYSTR);
    Private key encryption Start=system.currenttimemillis ();
    Encryptbytes= rsautils.encryptbyprivatekeyforspilt (Jsondata.getbytes (), privatekey.getencoded ());
    End=system.currenttimemillis ();
    LOG.E ("Mainactivity", "private key encryption time-consuming cost time---->" + (End-start));
    Encrystr=base64encoder.encode (encryptbytes);
    LOG.E ("Mainactivity", "encrypted JSON data--2-->" +ENCRYSTR);
    LOG.E ("Mainactivity", "encrypted JSON data length--2-->" +encrystr.length ());
    Public key decryption Start=system.currenttimemillis (); Decryptbytes= rsautils.decryptbypublickeyforspilt (Base64decoder.decodetobytes (ENCRYSTR), publicKey.getEncoded ())
    ;
    Decrystr=new String (decryptbytes);
    End=system.currenttimemillis ();
    LOG.E ("Mainactivity", "public key decryption time-consuming cost time---->" + (End-start)); LOG.E ("Mainactivity", "decrypted JSON data--2-->" +DECRYSTR);

Run Result:

Comparison found that the encryption of the private key is time-consuming, so can be based on different requirements of the solution to add and decrypt. Personally feel that the server requires high decryption efficiency, the client key encryption, the server public key decryption is better

Data size changes after encryption: The amount of data is almost 1.5 times times before the encryption

Summarize

The above is about the Android RSA Data encryption and decryption of all content, I hope this article content for everyone's study or work can bring some help, if there is doubt you can message exchange.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.