Recently accidentally and colleagues to exchange data security transmission problems, think of their own used RSA asymmetric encryption algorithm, idle down to sum up.
What is RSA encryption?
RSA algorithm is the most popular public key cryptography algorithm, using the length can change the key. RSA is the first algorithm that can be used both for data encryption and for digital signatures.
The principle of RSA algorithm is as follows:
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.
How to use it?
The first step: to generate the secret key pair first
/**
* 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 for block encryption public
static final int default_buffersize = ( DEFAULT_KEY_SIZE/8)-11;//The current secret key supports the maximum number of bytes encrypted
about the encryption fill: 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 end, The original RSA implementation of the Android system is "rsa/none/nopadding" and the standard JDK implementation is "rsa/none/pkcs1padding", which causes the inability to decrypt on the server after encrypting on the Android machine . So in the realization of this must pay attention to.
implementation of the segmented encryption: after the filling method and confident that all is well, but the accident or happened, RSA asymmetric encryption content length limit, 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[] Encryptbyprivateke
Yforspilt (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[] Decryptbypublickey
Forspilt (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 D
ATA range 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) thro
WS 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 more than the scope of data for (int j = 1; J < SPL Itlen;
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 public key encryption private key decryption 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
The above is a small series for everyone to bring the Android data encryption RSA encryption of the simple realization of all the content, I hope that we support cloud-Habitat Community ~