加密解密(RSA)

来源:互联网 发布:淘宝店铺导航栏全屏 编辑:程序博客网 时间:2024/05/16 11:32

加密解密(RSA)

什么是对称加密,什么是非对称加密?

加密解密使用同样的密钥,则是对称加密,使用不一样的密钥就是非对称加密,RSA属于非对称加密。

RSA中有公钥和私钥的概念,公钥加密私钥解密,私钥加密公钥解密,也可以使用RSA对消息进行签名


1.一些常量,防止觉得代码不清晰

 /**     * 加密算法RSA     */    public static final String KEY_ALGORITHM = "RSA";    /**     * 签名算法     */    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";    /**     * 获取公钥的key     */    public static final String PUBLIC_KEY = "RSAPublicKey";    /**     * 获取私钥的key     */    public static final String PRIVATE_KEY = "RSAPrivateKey";    /**     * RSA最大加密明文大小     */    private static final int MAX_ENCRYPT_BLOCK = 117;    /**     * RSA最大解密密文大小     */    private static final int MAX_DECRYPT_BLOCK = 128;

2.获取密钥对

这里使用了内置的方法获取生成的公钥私钥,返回的密钥已经经过了Base64编码的处理,是可见的字符串。

  /**     * <p>     * 生成密钥对(公钥和私钥)     * </p>     *     * @return     * @throws Exception     */    public static Map<String, Object> getKeyPair(int size) throws Exception {        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);        keyPairGen.initialize(size);        KeyPair keyPair = keyPairGen.generateKeyPair();        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();        Map<String, Object> keyMap = new HashMap<String, Object>(2);        keyMap.put(PUBLIC_KEY, publicKey);        keyMap.put(PRIVATE_KEY, privateKey);        return keyMap;    } /**     * <p>     * 获取私钥     * </p>     *     * @param keyMap 密钥对     * @return 获取的key已经经过base64编码     * @throws Exception     */    public static String getPrivateKey(Map<String, Object> keyMap)            throws Exception {        Key key = (Key) keyMap.get(PRIVATE_KEY);        // return Base64Utils.encode(key.getEncoded());        return Base64.encodeToString(key.getEncoded(), Base64.NO_WRAP);    }    /**     * <p>     * 获取公钥     * </p>     *     * @param keyMap 密钥对     * @return 获取的key已经经过base64编码     * @throws Exception     */    public static String getPublicKey(Map<String, Object> keyMap)            throws Exception {        Key key = (Key) keyMap.get(PUBLIC_KEY);        // return Base64Utils.encode(key.getEncoded());        return Base64.encodeToString(key.getEncoded(), Base64.NO_WRAP);    }

3.私钥加密

/**     * <p>     * 私钥加密     * </p>     *     * @param data       源数据     * @param privateKey 私钥(BASE64编码)     * @return     * @throws Exception     */    public static byte[] encryptByPrivateKey(byte[] data, String privateKey)            throws Exception {//      byte[] keyBytes = Base64Utils.decode(privateKey);        byte[] keyBytes = Base64.decode(privateKey, Base64.NO_WRAP);        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());        cipher.init(Cipher.ENCRYPT_MODE, privateK);        int inputLen = data.length;        ByteArrayOutputStream out = new ByteArrayOutputStream();        int offSet = 0;        byte[] cache;        int i = 0;        // 对数据分段加密        while (inputLen - offSet > 0) {            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);            } else {                cache = cipher.doFinal(data, offSet, inputLen - offSet);            }            out.write(cache, 0, cache.length);            i++;            offSet = i * MAX_ENCRYPT_BLOCK;        }        byte[] encryptedData = out.toByteArray();        out.close();        return encryptedData;    }

4.公钥加密

 /**     * <p>     * 公钥加密     * </p>     *     * @param data      源数据     * @param publicKey 公钥(BASE64编码)     * @return     * @throws Exception     */    public static byte[] encryptByPublicKey(byte[] data, String publicKey)            throws Exception {        byte[] keyBytes = Base64.decode(publicKey, Base64.NO_WRAP);        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);        Key publicK = keyFactory.generatePublic(x509KeySpec);        // 对数据加密        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());        cipher.init(Cipher.ENCRYPT_MODE, publicK);        int inputLen = data.length;        ByteArrayOutputStream out = new ByteArrayOutputStream();        int offSet = 0;        byte[] cache;        int i = 0;        // 对数据分段加密        while (inputLen - offSet > 0) {            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);            } else {                cache = cipher.doFinal(data, offSet, inputLen - offSet);            }            out.write(cache, 0, cache.length);            i++;            offSet = i * MAX_ENCRYPT_BLOCK;        }        byte[] encryptedData = out.toByteArray();        out.close();        return encryptedData;    }

5.公钥解密

    /**     * <p>     * 公钥解密     * </p>     *     * @param encryptedData 已加密数据     * @param publicKey     公钥(BASE64编码)     * @return     * @throws Exception     */    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)            throws Exception {        byte[] keyBytes = Base64.decode(publicKey, Base64.NO_WRAP);        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);        Key publicK = keyFactory.generatePublic(x509KeySpec);        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());        cipher.init(Cipher.DECRYPT_MODE, publicK);        int inputLen = encryptedData.length;        ByteArrayOutputStream out = new ByteArrayOutputStream();        int offSet = 0;        byte[] cache;        int i = 0;        // 对数据分段解密        while (inputLen - offSet > 0) {            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);            } else {                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);            }            out.write(cache, 0, cache.length);            i++;            offSet = i * MAX_DECRYPT_BLOCK;        }        byte[] decryptedData = out.toByteArray();        out.close();        return decryptedData;    }

6.私钥解密

   /**     * <P>     * 私钥解密     * </p>     *     * @param encryptedData 已加密数据     * @param privateKey    私钥(BASE64编码)     * @return     * @throws Exception     */    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)            throws Exception {        byte[] keyBytes = Base64.decode(privateKey, Base64.NO_WRAP);        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());        cipher.init(Cipher.DECRYPT_MODE, privateK);        int inputLen = encryptedData.length;        ByteArrayOutputStream out = new ByteArrayOutputStream();        int offSet = 0;        byte[] cache;        int i = 0;        // 对数据分段解密        while (inputLen - offSet > 0) {            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);            } else {                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);            }            out.write(cache, 0, cache.length);            i++;            offSet = i * MAX_DECRYPT_BLOCK;        }        byte[] decryptedData = out.toByteArray();        out.close();        return decryptedData;    }

7.消息签名

    /**     * <p>     * 用私钥对信息生成数字签名     * </p>     *     * @param data       已加密数据     * @param privateKey 私钥(BASE64编码)     * @return     * @throws Exception     */    public static String sign(byte[] data, String privateKey) throws Exception {        byte[] keyBytes = Base64.decode(privateKey, Base64.NO_WRAP);        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);        signature.initSign(privateK);        signature.update(data);        return Base64.encodeToString(signature.sign(), Base64.NO_WRAP);    }

8.验证签名

/**     * <p>     * 使用公钥校验数字签名     * </p>     *     * @param data      已加密数据     * @param publicKey 公钥(BASE64编码)     * @param sign      数字签名     * @return     * @throws Exception     */    public static boolean verifySign(byte[] data, String publicKey, String sign)            throws Exception {        byte[] keyBytes = Base64.decode(publicKey, Base64.NO_WRAP);        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);        PublicKey publicK = keyFactory.generatePublic(keySpec);        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);        signature.initVerify(publicK);        signature.update(data);        return signature.verify(Base64.decode(sign, Base64.NO_WRAP));    }

9.可以发现有很多重复代码,这样写是为了更加清晰,代码抽取一下

/** * <p> * RSA公钥/私钥/签名工具包 * </p> * <p> * </p> * <p> * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/> * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/> * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全 * </p> */public class RSAUtils {    /**     * 加密算法RSA     */    public static final String KEY_ALGORITHM = "RSA";    /**     * 签名算法     */    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";    /**     * 获取公钥的key     */    public static final String PUBLIC_KEY = "RSAPublicKey";    /**     * 获取私钥的key     */    public static final String PRIVATE_KEY = "RSAPrivateKey";    /**     * RSA最大加密明文大小     */    private static final int MAX_ENCRYPT_BLOCK = 117;    /**     * RSA最大解密密文大小     */    private static final int MAX_DECRYPT_BLOCK = 128;    /**     * <p>     * 生成密钥对(公钥和私钥)     * </p>     *     * @return     * @throws Exception     */    public static Map<String, Object> getKeyPair(int size) throws Exception {        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);        keyPairGen.initialize(size);        KeyPair keyPair = keyPairGen.generateKeyPair();        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();        Map<String, Object> keyMap = new HashMap<String, Object>(2);        keyMap.put(PUBLIC_KEY, publicKey);        keyMap.put(PRIVATE_KEY, privateKey);        return keyMap;    }    /**     * <p>     * 用私钥对信息生成数字签名     * </p>     *     * @param data       已加密数据     * @param privateKey 私钥(BASE64编码)     * @return     * @throws Exception     */    public static String sign(byte[] data, String privateKey) throws Exception {        byte[] keyBytes = Base64.decode(privateKey, Base64.NO_WRAP);        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);        signature.initSign(privateK);        signature.update(data);        return Base64.encodeToString(signature.sign(), Base64.NO_WRAP);    }    /**     * <p>     * 使用公钥校验数字签名     * </p>     *     * @param data      已加密数据     * @param publicKey 公钥(BASE64编码)     * @param sign      数字签名     * @return     * @throws Exception     */    public static boolean verifySign(byte[] data, String publicKey, String sign)            throws Exception {        byte[] keyBytes = Base64.decode(publicKey, Base64.NO_WRAP);        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);        PublicKey publicK = keyFactory.generatePublic(keySpec);        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);        signature.initVerify(publicK);        signature.update(data);        return signature.verify(Base64.decode(sign, Base64.NO_WRAP));    }    /**     * 使用私钥操作时     *     * @param data     * @param key     * @param mode     * @return     * @throws Exception     */    public static byte[] UsePrivate(byte[] data, String key, int mode)            throws Exception {        byte[] keyBytes = Base64.decode(key, Base64.NO_WRAP);        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);        return common(pkcs8KeySpec, data, mode);    }    /**     * 使用公钥操作     *     * @param data     * @param key     * @param mode     * @return     * @throws Exception     */    public static byte[] UsePublic(byte[] data, String key, int mode) {        byte[] keyBytes = Base64.decode(key, Base64.NO_WRAP);        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);        return common(x509KeySpec, data, mode);    }    /**     * 抽取公共的方法     * @param keySpecs     * @param data     * @param mode     * @return     */    private static byte[] common(KeySpec keySpecs, byte[] data, int mode) {        byte[] decryptedData = null;        try {            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);            Key publicK = keyFactory.generatePublic(keySpecs);            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());            cipher.init(mode, publicK);            int inputLen = data.length;            ByteArrayOutputStream out = new ByteArrayOutputStream();            int offSet = 0;            byte[] cache;            int i = 0;            // 对数据分段解密            while (inputLen - offSet > 0) {                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {                    cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);                } else {                    cache = cipher.doFinal(data, offSet, inputLen - offSet);                }                out.write(cache, 0, cache.length);                i++;                offSet = i * MAX_DECRYPT_BLOCK;            }            decryptedData = out.toByteArray();            out.close();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (InvalidKeySpecException e) {            e.printStackTrace();        }        return decryptedData;    }    /**     * <p>     * 获取私钥     * </p>     *     * @param keyMap 密钥对     * @return 获取的key已经经过base64编码     * @throws Exception     */    public static String getPrivateKey(Map<String, Object> keyMap)            throws Exception {        Key key = (Key) keyMap.get(PRIVATE_KEY);        // return Base64Utils.encode(key.getEncoded());        return Base64.encodeToString(key.getEncoded(), Base64.NO_WRAP);    }    /**     * <p>     * 获取公钥     * </p>     *     * @param keyMap 密钥对     * @return 获取的key已经经过base64编码     * @throws Exception     */    public static String getPublicKey(Map<String, Object> keyMap)            throws Exception {        Key key = (Key) keyMap.get(PUBLIC_KEY);        // return Base64Utils.encode(key.getEncoded());        return Base64.encodeToString(key.getEncoded(), Base64.NO_WRAP);    }}

这里涉及了密钥的导入和导出,导出的私钥使用必须经过

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

导出的公钥需要经过

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key publicK = keyFactory.generatePublic(x509KeySpec);

RSA加密解密就到这里了

0 0
原创粉丝点击