Android传输数据时Rsa加密解密详解

来源:互联网 发布:金英杰免费网络课2017 编辑:程序博客网 时间:2024/06/07 07:01

Android传输数据时Rsa加密解密详解

一、RSA加密算法

RSA加密算法是一种“非对称加密算法”。使用长度可以变化的密钥。RSA是第一个既能用于数据加密也能用于数字签名的算法。

RSA的安全性依赖于大数分解,小于1024位的N已经被证明是不安全的,而且由于RSA算法进行的都是大数计算,是的RSA最快的情况也比DES慢,因此通常RSA只能用于加密少量数据或者加密密钥。

RSA算法原理:

1. 随机选择两个大质数pq,计算N = p*q;

2. 选择一个大于1小于N的自然数ee必须与(p-1)(q-1)互素

3. 用公式计算出d:      d*e = 1(mod(p-1)(q-1))

4. 销毁pq

最终得到的Ne就是“公钥”,d就是“私钥”;发送方使用N去加密数据,接收方只有使用d才能解开数据内容。

二、加密注意事项

Android加密过的数据,服务端无法解密:

1. 加密填充方式不同

Android系统RSA实现是“RSA/None/NoPadding

Java JDK实现是“RSA/None/PKCS1Padding

注:加密填充方式选择RSA/None/PKCS1Padding

2. 实现分段加密

RSA非对称加密内容长度有限制,1024key最多只能加密127位数据,否则会报错:javax.crypto.IllegalBlockSizeException:input must beunder 256 bytesRSA是常用的非对称加密算法。出现“不正确长度”原因是待加密数据超长所致。

RSA算法规定:待加密的字节数不能超过密钥的长度值除以8再减去11,而加密后得到密文的字数,正好是密钥长度值除以8。

注:小数据可以不使用分段加密,一旦数据超过密钥支持最大字节数,使用分段加密。

3. 私钥加密和解密都很耗时,所以根据不同需求采用不同方案进行加解密。个人觉得因为服务器要求解密效率高,所以客户端私钥加密,服务器公钥解密比较好一点。加密之后数据大小差不多是加密前的1.5倍。

三、RSA加密算法实例

1. 设置变量

/**非对称加密密钥算法*/
public static finalString RSA= "RSA";
/** 加密填充方式*/
public static finalString ECB_PKCS1_PADDING= "RSA/ECB/PKCS1Padding";
/** 秘钥默认长度*/
public static final intDEFAULT_KEY_SIZE = 2048;
/** 当要加密的内容超过bufferSize,则采用partSplit进行分块加密*/
public static final byte[]DEFAULT_SPLIT = "#PART#".getBytes();
/** 当前秘钥支持加密的最大字节数*/
public static final intDEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE/ 8) - 11;

2. 生成密钥对

/**
 * 随机生成RSA密钥对
 *
 *
@param keyLength密钥长度,范围:5122048  一般1024
 *
@return 
 
*/
public static KeyPair generateRSAKeyPair(intkeyLength) {
    try{
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
        kpg.initialize(keyLength);
        returnkpg.genKeyPair();
    } catch(NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}

3. 公钥加密

/**
 * 用公钥对字符串进行加密
 *
 *
@param data原文
 */
public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey)throws Exception {
    //得到公钥
    
X509EncodedKeySpec keySpec =new X509EncodedKeySpec(publicKey);
    KeyFactory kf = KeyFactory.getInstance(RSA);
    PublicKey keyPublic = kf.generatePublic(keySpec);
    //加密数据
    
Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
    cp.init(Cipher.ENCRYPT_MODE, keyPublic);
    returncp.doFinal(data);
}

4. 私钥解密

/**
 * 使用私钥进行解密
 */
public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey)throws Exception {
    //得到私钥
    
PKCS8EncodedKeySpec keySpec =new PKCS8EncodedKeySpec(privateKey);
    KeyFactory kf = KeyFactory.getInstance(RSA);
    PrivateKey keyPrivate = kf.generatePrivate(keySpec);

    //解密数据
    
Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
    cp.init(Cipher.DECRYPT_MODE, keyPrivate);
    byte[] arr = cp.doFinal(encrypted);
    returnarr;
}

 

5. 私钥加密

/**
 * 私钥加密
 *
 *
@param data       待加密数据
 *
@param privateKey密钥
 *
@returnbyte[] 加密数据
 */
public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey)throws Exception {
    //得到私钥
    
PKCS8EncodedKeySpec keySpec =new PKCS8EncodedKeySpec(privateKey);
    KeyFactory kf = KeyFactory.getInstance(RSA);
    PrivateKey keyPrivate = kf.generatePrivate(keySpec);
    //数据加密
    
Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
    cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
    returncipher.doFinal(data);
}

 

6. 公钥解密

/**
 * 公钥解密
 *
 *
@param data      待解密数据
 *
@param publicKey密钥
 *
@returnbyte[] 解密数据
 */
public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey)throws Exception {
    //得到公钥
    
X509EncodedKeySpec keySpec =new X509EncodedKeySpec(publicKey);
    KeyFactory kf = KeyFactory.getInstance(RSA);
    PublicKey keyPublic = kf.generatePublic(keySpec);
    //数据解密
    
Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
    cipher.init(Cipher.DECRYPT_MODE, keyPublic);
    returncipher.doFinal(data);
}

 

7. 加密解密实现

KeyPair keyPair =generateRSAKeyPair(DEFAULT_KEY_SIZE);
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

try {
    //公钥加密
    
byte[] encryByte =  
            encryptByPublicKey("Lking".getBytes(),publicKey.getEncoded());
    String encryBase64 = Base64.encodeToString(encryByte,Base64.DEFAULT);
    Log.e("Lking","RSA公钥加密---->"+encryBase64);

    //私钥解密
    
byte[] encryBytepri =
            decryptByPrivateKey(Base64.decode(encryBase64,Base64.DEFAULT),
                    privateKey.getEncoded());
    String pri = newString(encryBytepri);
    Log.e("Lking","RSA私钥解密---->"+pri);
} catch(Exception e) {
    e.printStackTrace();
}

四、分段RSA加密算法实例

1. 设置变量

/**非对称加密密钥算法*/
public static finalString RSA= "RSA";
/** 加密填充方式*/
public static finalString ECB_PKCS1_PADDING= "RSA/ECB/PKCS1Padding";
/** 秘钥默认长度*/
public static final intDEFAULT_KEY_SIZE = 2048;
/** 当要加密的内容超过bufferSize,则采用partSplit进行分块加密*/
public static final byte[]DEFAULT_SPLIT = "#PART#".getBytes();
/** 当前秘钥支持加密的最大字节数*/
public static final intDEFAULT_BUFFERSIZE = (DEFAULT_KEY_SIZE/ 8) - 11;

2. 生成密钥对

/**
 * 随机生成RSA密钥对
 *
 *
@param keyLength密钥长度,范围:5122048
 *                  一般1024
 *
@return
 
*/
public static KeyPair generateRSAKeyPair(intkeyLength) {
    try{
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
        kpg.initialize(keyLength);
        returnkpg.genKeyPair();
    } catch(NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}

3. 公钥分段加密

/**
 * 用公钥对字符串进行分段加密
 *
 */
public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey)throws Exception {
    intdataLen = data.length;
    if(dataLen <=DEFAULT_BUFFERSIZE) {
        returnencryptByPublicKey(data, publicKey);
    }
    List<Byte> allBytes =new ArrayList<Byte>(2048);
    intbufIndex =0;
    intsubDataLoop =0;
    byte[] buf =new byte[DEFAULT_BUFFERSIZE];
    for(inti = 0; i < dataLen; i++) {
        buf[bufIndex] = data[i];
        if(++bufIndex ==DEFAULT_BUFFERSIZE|| i == dataLen -1) {
            subDataLoop++;
            if(subDataLoop !=1) {
                for(byteb : DEFAULT_SPLIT) {
                    allBytes.add(b);
                }
            }
            byte[] encryptBytes =encryptByPublicKey(buf, publicKey);
            for(byteb : 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()];
    {
        inti = 0;
        for(Byte b : allBytes) {
            bytes[i++] = b.byteValue();
        }
    }
    returnbytes;
}

4. 私钥分段解密

/**
 * 使用私钥分段解密
 *
 */
public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey)throws Exception {
    intsplitLen =DEFAULT_SPLIT.length;
    if(splitLen <=0) {
        returndecryptByPrivateKey(encrypted, privateKey);
    }
    intdataLen = encrypted.length;
    List<Byte> allBytes =new ArrayList<Byte>(1024);
    intlatestStartIndex =0;
    for(inti = 0; i < dataLen; i++) {
        bytebt = encrypted[i];
        booleanisMatchSplit =false;
        if(i == dataLen -1) {
            //data的最后了
            
byte[] part =new byte[dataLen - latestStartIndex];
            System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
            byte[] decryptPart =decryptByPrivateKey(part, privateKey);
            for(byteb : decryptPart) {
                allBytes.add(b);
            }
            latestStartIndex = i + splitLen;
            i = latestStartIndex -1;
        } else if (bt ==DEFAULT_SPLIT[0]) {
            //这个是以split[0]开头
            
if(splitLen >1) {
                if(i + splitLen < dataLen) {
                    //没有超出data的范围
                    
for(intj = 1; j < splitLen; j++) {
                        if(DEFAULT_SPLIT[j] != encrypted[i + j]) {
                            break;
                        }
                        if(j == splitLen -1) {
                            //验证到split的最后一位,都没有break,则表明已经确认是split
                            
isMatchSplit =true;
                        }
                    }
                }
            } else {
                // split只有一位,则已经匹配了
                
isMatchSplit =true;
            }
        }
        if(isMatchSplit) {
            byte[] part =new byte[i - latestStartIndex];
            System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
            byte[] decryptPart =decryptByPrivateKey(part, privateKey);
            for(byteb : decryptPart) {
                allBytes.add(b);
            }
            latestStartIndex = i + splitLen;
            i = latestStartIndex -1;
        }
    }
    byte[] bytes =new byte[allBytes.size()];
    {
        inti = 0;
        for(Byte b : allBytes) {
            bytes[i++] = b.byteValue();
        }
    }
    returnbytes;
}

5. 私钥分段加密

/**
 * 私钥分段加密
 *
 *
@paramdata       要加密的原始数据
 *
@paramprivateKey 秘钥
 */
public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey)throws Exception {
    intdataLen = data.length;
    if(dataLen <=DEFAULT_BUFFERSIZE) {
        returnencryptByPrivateKey(data, privateKey);
    }
    List<Byte> allBytes =new ArrayList<Byte>(2048);
    intbufIndex =0;
    intsubDataLoop =0;
    byte[] buf =new byte[DEFAULT_BUFFERSIZE];
    for(inti = 0; i < dataLen; i++) {
        buf[bufIndex] = data[i];
        if(++bufIndex ==DEFAULT_BUFFERSIZE|| i == dataLen -1) {
            subDataLoop++;
            if(subDataLoop !=1) {
                for(byteb : DEFAULT_SPLIT) {
                    allBytes.add(b);
                }
            }
            byte[] encryptBytes =encryptByPrivateKey(buf, privateKey);
            for(byteb : 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()];
    {
        inti = 0;
        for(Byte b : allBytes) {
            bytes[i++] = b.byteValue();
        }
    }
    returnbytes;
}

6. 公钥分段解密

/**
 * 公钥分段解密
 *
 *
@paramencrypted 待解密数据
 *
@parampublicKey 密钥
 */
public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey)throws Exception {
    intsplitLen =DEFAULT_SPLIT.length;
    if(splitLen <=0) {
        returndecryptByPublicKey(encrypted, publicKey);
    }
    intdataLen = encrypted.length;
    List<Byte> allBytes =new ArrayList<Byte>(1024);
    intlatestStartIndex =0;
    for(inti = 0; i < dataLen; i++) {
        bytebt = encrypted[i];
        booleanisMatchSplit =false;
        if(i == dataLen -1) {
            //data的最后了
            
byte[] part =new byte[dataLen - latestStartIndex];
            System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
            byte[] decryptPart =decryptByPublicKey(part, publicKey);
            for(byteb : decryptPart) {
                allBytes.add(b);
            }
            latestStartIndex = i + splitLen;
            i = latestStartIndex -1;
        } else if (bt ==DEFAULT_SPLIT[0]) {
            //这个是以split[0]开头
            
if(splitLen >1) {
                if(i + splitLen < dataLen) {
                    //没有超出data的范围
                    
for(intj = 1; j < splitLen; j++) {
                        if(DEFAULT_SPLIT[j] != encrypted[i + j]) {
                            break;
                        }
                        if(j == splitLen -1) {
                            //验证到split的最后一位,都没有break,则表明已经确认是split
                            
isMatchSplit =true;
                        }
                    }
                }
            } else {
                // split只有一位,则已经匹配了
                
isMatchSplit =true;
            }
        }
        if(isMatchSplit) {
            byte[] part =new byte[i - latestStartIndex];
            System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
            byte[] decryptPart =decryptByPublicKey(part, publicKey);
            for(byteb : decryptPart) {
                allBytes.add(b);
            }
            latestStartIndex = i + splitLen;
            i = latestStartIndex -1;
        }
    }
    byte[] bytes =new byte[allBytes.size()];
    {
        inti = 0;
        for(Byte b : allBytes) {
            bytes[i++] = b.byteValue();
        }
    }
    returnbytes;
}

7. 

KeyPair keyPair =generateRSAKeyPair(DEFAULT_KEY_SIZE);
// 公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

try{
    //公钥分段加密
    
byte[] encryByte =
            encryptByPublicKeyForSpilt("大于秘钥支持加密的最大字节数...".getBytes(),

publicKey.getEncoded());
    String encryBase64 = Base64.encodeToString(encryByte,Base64.DEFAULT);
    Log.e("Lking","RSA公钥加密---->"+encryBase64);

    //私钥分段解密
    
byte[] encryBytepri =
            decryptByPrivateKeyForSpilt(Base64.decode(encryBase64,Base64.DEFAULT),
                    privateKey.getEncoded());
    String pri = new String(encryBytepri);
    Log.e("Lking","RSA私钥解密---->"+pri);
} catch(Exception e) {
    e.printStackTrace();
}

原创粉丝点击