精华内容
下载资源
问答
  • 2017-11-02 16:53:14
    最近有一个外部合作项目要求在数据传输过程中使用RSA加密算法对数据进行加密,所以需要编写一个加解密的工具类,因为对方不是java语言,所以是各自实现的这个工具,本文主要讨论实现以及双方调试过程中的一些插曲,希望给大家不要再次踩坑。
    关于加解密的核心部分,网上有很多博主都有实现过,我也是参考了一些博主的方法自己实现了一个加解密的工具。
    
    package com.chen.test;
    
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.io.IOUtils;
    
    import javax.crypto.Cipher;
    import java.io.ByteArrayOutputStream;
    import java.security.*;
    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 java.util.HashMap;
    import java.util.Map;
    
    public class RSAUtils {
    
        public static final String CHARSET = "UTF-8";
        public static final String RSA_ALGORITHM = "RSA";
    
    
        public static Map<String, String> createKeys(int keySize){
            //为RSA算法创建一个KeyPairGenerator对象
            KeyPairGenerator kpg;
            try{
                kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
            }catch(NoSuchAlgorithmException e){
                throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
            }
    
            //初始化KeyPairGenerator对象,密钥长度
            kpg.initialize(keySize);
            //生成密匙对
            KeyPair keyPair = kpg.generateKeyPair();
            //得到公钥
            Key publicKey = keyPair.getPublic();
            String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
            //得到私钥
            Key privateKey = keyPair.getPrivate();
            String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
            Map<String, String> keyPairMap = new HashMap<String, String>();
            keyPairMap.put("publicKey", publicKeyStr);
            keyPairMap.put("privateKey", privateKeyStr);
    
            return keyPairMap;
        }
    
        /**
         * 得到公钥
         * @param publicKey 密钥字符串(经过base64编码)
         * @throws Exception
         */
        public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
            //通过X509编码的Key指令获得公钥对象
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
            RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
            return key;
        }
    
        /**
         * 得到私钥
         * @param privateKey 密钥字符串(经过base64编码)
         * @throws Exception
         */
        public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
            //通过PKCS#8编码的Key指令获得私钥对象
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
            RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
            return key;
        }
    
        /**
         * 公钥加密
         * @param data
         * @param publicKey
         * @return
         */
        public static String publicEncrypt(String data, RSAPublicKey publicKey){
            try{
                Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
            }catch(Exception e){
                throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
            }
        }
    
        /**
         * 私钥解密
         * @param data
         * @param privateKey
         * @return
         */
    
        public static String privateDecrypt(String data, RSAPrivateKey privateKey){
            try{
                Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
                return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
            }catch(Exception e){
                throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
            }
        }
    
        /**
         * 私钥加密
         * @param data
         * @param privateKey
         * @return
         */
    
        public static String privateEncrypt(String data, RSAPrivateKey privateKey){
            try{
                Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
                cipher.init(Cipher.ENCRYPT_MODE, privateKey);
                return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
            }catch(Exception e){
                throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
            }
        }
    
        /**
         * 公钥解密
         * @param data
         * @param publicKey
         * @return
         */
    
        public static String publicDecrypt(String data, RSAPublicKey publicKey){
            try{
                Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
                cipher.init(Cipher.DECRYPT_MODE, publicKey);
                return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
            }catch(Exception e){
                throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
            }
        }
    
        private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
            int maxBlock = 0;
            if(opmode == Cipher.DECRYPT_MODE){
                maxBlock = keySize / 8;
            }else{
                maxBlock = keySize / 8 - 11;
            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] buff;
            int i = 0;
            try{
                while(datas.length > offSet){
                    if(datas.length-offSet > maxBlock){
                        buff = cipher.doFinal(datas, offSet, maxBlock);
                    }else{
                        buff = cipher.doFinal(datas, offSet, datas.length-offSet);
                    }
                    out.write(buff, 0, buff.length);
                    i++;
                    offSet = i * maxBlock;
                }
            }catch(Exception e){
                throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);
            }
            byte[] resultDatas = out.toByteArray();
            IOUtils.closeQuietly(out);
            return resultDatas;
        }
    
    }

    简单测试一下。

    public static void main (String[] args) throws Exception {
            Map<String, String> keyMap = RSAUtils.createKeys(1024);
            String  publicKey = keyMap.get("publicKey");
            String  privateKey = keyMap.get("privateKey");
            System.out.println("公钥: \n\r" + publicKey);
            System.out.println("私钥: \n\r" + privateKey);
    
            System.out.println("公钥加密——私钥解密");
            String str = "站在大明门前守卫的禁卫军,事先没有接到\n" +
                    "有关的命令,但看到大批盛装的官员来临,也就\n" +
                    "以为确系举行大典,因而未加询问。进大明门即\n" +
                    "为皇城。文武百官看到端门午门之前气氛平静,\n" +
                    "城楼上下也无朝会的迹象,既无几案,站队点名\n" +
                    "的御史和御前侍卫“大汉将军”也不见踪影,不免\n" +
                    "心中揣测,互相询问:所谓午朝是否讹传?";
            System.out.println("\r明文:\r\n" + str);
            System.out.println("\r明文大小:\r\n" + str.getBytes().length);
            String encodedData = RSAUtils.publicEncrypt(str, RSAUtils.getPublicKey(publicKey));
            System.out.println("密文:\r\n" + encodedData);
            String decodedData = RSAUtils.privateDecrypt(encodedData, RSAUtils.getPrivateKey(privateKey));
            System.out.println("解密后文字: \r\n" + decodedData);
    
    
        }

    实现基本上就是这样,都是大同小异。不过,问题来了,结下来才是重点。
    **1. RSA加密算法对于加密数据的长度是有要求的。一般来说,明文长度小于等于密钥长度(Bytes)-11。解决这个问题需要对较长的明文进行分段加解密,这个上面的代码已经实现了。
    2. 一旦涉及到双方开发,语言又不相同,不能够采用同一个工具的时候,切记要约定以下内容。
    a)约定双方的BASE64编码
    b)约定双方分段加解密的方式。我踩的坑也主要是这里,不仅仅是约定大家分段的大小,更重要的是分段加密后的拼装方式。doFinal方法加密完成后得到的仍然是byte[],因为最终呈现的是编码后的字符串,所以你可以分段加密,分段编码和分段加密,一次编码两种方式(上面的代码采用的是后一种,也推荐采用这一种)。相信我不是所有人的脑回路都一样的,尤其是当他采用的开发语言和你不通时。**

    更多相关内容
  • 主要介绍了java实现RSA加密算法,结合实例形式详细分析了RSA加密解密的原理、java实现方法及相关注意事项,需要的朋友可以参考下
  • 提供了rsa算法java类及测试代码.其中已经用过,有需要的可以拿去
  • JAVA RSA 加密算法 RSA.java RSA公钥加解密,RSA私钥加解密,MD5withRSA 签名 MD5withRSA签名较验
  • 下面小编就为大家带来一篇RSA加密算法java简单实现方法(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。 这时一个简单的Java实现,在RSA网络安全工具类是比较完整的实现。
  • RSA加密算法实现以及C#与java互通加解密,解决RSA算法在java与C#相互通用
  • java编程实现RSA加密算法

    千次阅读 2021-03-07 11:02:25
    那么我今天就给大家介绍一下如何利用Java编程来实现RSA加密算法。一、RSA加密算法描述RSA加密算法是1978年提出的。经过多年的分析和研究,在众多的公开密钥加密算法中,RSA加密算法最受推崇,它也被推荐为公开密钥...

    RSA加密算法是目前应用最广泛的公钥加密算法,特别适用于通过Internet传送的数据,常用于数字签名和密钥交换。那么我今天就给大家介绍一下如何利用Java编程来实现RSA加密算法。

    一、RSA加密算法描述

    RSA加密算法是1978年提出的。经过多年的分析和研究,在众多的公开密钥加密算法中,RSA加密算法最受推崇,它也被推荐为公开密钥数据加密标准。

    由数论知识可知,若将一个具有大素数因子的合数进行分解是很困难的,或者说这个问题的计算量是令人望而生畏的,而RSA加密算法正是建立在这个基础上的。

    在RSA加密算法中,—个用户A可根据以下步骤来选择密钥和进行密码转换:

    (1)随机的选取两个不同的大素数p和q(一般为100位以上的十进制数),予以保密;

    (2)计算n=p*q,作为用户A的模数,予以公开;

    (3)计算欧拉(Euler)函数z=(p-1)*(q-1),予以保密;

    (4)随机的选取d与z互质,作为A的公开密钥;

    (5)利用Euclid算法计算满足同余方程e*d≡1modz的解d,作为用户A的保密密钥;

    (6)任何向用户A发送信息M的用户,可以用A的公开模数D和公开密钥e根据C=Me mod n得到密文C;

    RSA加密算法的安全性是基于大素数分解的困难性。攻击者可以分解已知的n,得到p和q,然后可得到z;最后用Euclid算法,由e和z得到d。然而要分解200位的数,需要大约40亿年。

    二、用Java语言描述RSA加密算法的原理

    假设我们需要将信息从机器A传到机器B,首先由机器B随机确定一个private_kcy(我们称之为密钥),可将这个private_key始终保存在机器B中而不发出来。然后,由这个private_key计算出public_key(我们称之为公钥)。这个public_key的特性是:几乎不可能通过该public_key计算生成它的priyate_key。接下来通过网络把这个public_key传给机器A,机器A收到public_key后,利用public_key将信息加密,并把加密后的信息通过网络发送到机器B,最后机器B利用已知的pri.rate_key,就可以解开加密信息。

    步骤:

    (1)首先选择两个大素数p和q,计算n=p*q;m=(p-1)(q一1);

    (2)而后随机选择加密密钥public_key,要求和m互质(比如public_key=m-1);

    (3)利用Euclid算法计算解密密钥priyate_key,使private_key满足public_key*private_key—1(mod m),其中public_key,n是作为公钥已知,priVate_key是密钥;

    (4)加密信息text时,利用公式secretWord=texI^Public_key (mod n)得到密文8ecretword;

    (5)解密时利用公式word=text^priVate_key(mod n)得到原文word=text。

    三、用java编程实现RSA加密算法过程

    1、产生大素数

    实现RSA加密算法的第一个步骤是产生大素数p和q,采用的方法是产生随机数而后对其进行素性判断,故实现RSA加密算法的一个重要技术是随机数的产生。RSA加密算法中的大素数的随机性直接影响算法的安全性,如果素数产生时随机性差,就很容易被重复,因而也就是不安全的。然而,要人工产生真正的随机数是不可能的,一般情况下计算机产生的随机数都足伪随机数,但是,用一些算法产生的伪随机数的随机性非常接近真正的随机数,可以满足密码学的要求。

    JAVA的标准包java .security中的SecureRandom类提供了一个基于SHA-1散列算法的强伪随机数生成器,该生成算法生成的随机序列具有比较理想的随机性。使用该方法生成随机序列后,利用Biglnteger类中的intcertainty方法对产生的随机序列进行多次素性测试,则通过该测试的随机序列为素数的概率为1-(1/2)m(设素性判断的次数是m次)。不难看出,当m取一个比较大的整数时,该序列为素数的概率近似为1。

    生成N位的大素数p和q的主要代码如下:

    SecureRandom rnd=new SecureRandom();//生成随机序列

    Biglnteger p=new Biglnteger(m.200, md);//生成p

    Biglnteger q=new Biglnteger(m, 200, md);//生成q

    2、计算乘积n和模数Φ(n)

    Biglnteger类中已经预先定义了基本的数学运算方法,如multiply、subtract等,利用这些方法可以非常快捷地计算n=p*q和Φ(n)=(p—1)(q—1)。具体实现代码如下:

    Biglnteger u=(p.subtract(new Biglnteger(“1”)

    multiply(q.subtract(new Biglnteger(“1”)));//计算模数Φ(n)

    n=p.multiply(q);//计算乘积n

    3、生成密钥对e和d

    适当选择RSA加密算法的公钥e,可以大大加快算法的实现速度。例如,可以选e为3、17或65537,它们的二进制表示式中都只有两个1,可以大大减少运算量。但是e太小时可能会导致低加密指数攻击,本程序选取e为65537,这样可以在提高算法速度的同时保证安全性。

    得到e后,需要根据:d=e-1modΦ(n)计算私钥d,即d是e的乘法逆元,Biglnteger类中的modlnverse方法可以直接用来计算乘法逆元d,选取e以及根据e计算d的部分代码为:

    e=new Biglnteger(”65537i”);//选择公钥e为65537

    d=PK.modlnverse(u);//根据e求私钥d

    4、加密和解密

    RSA加密算法的加密和解密过程中均需要计算大整数的幂之后模n,在程序实现上可以利用Biglnteger类中的modPow方法,该方法是计算一个大整数的幂与另外一个大整数的模。分别在程序中的RSA类中定义加密方法encrypt和解密方法decrypt:

    Biglnteger encrypt(Biglnteger message)

    {

    return message.modPow(e,n),)//加密

    Biglnteger decrypt(Biglnteger encrypted)

    {

    retum encrypted. modPow(d,n);

    }

    //解密

    在加密和解密中分别调用RSA类中对应的加密方法enaypt和解密方法decrypt,即可获得对应的密文和明文。

    四、程序执行结果

    此RSA加密程序的开发环境为eclipse-SDK-3.0.1,在Pentium(R) Dual T2310 (1.4G),1G内存, 在Windows XP系统计算机上调试成功。在操作系统的命令提示符下进入程序所在路径,键入“java rsa”,根据提示输入加密密钥位数以及明文,程序执行结果如图所示。

    123af27906ac7f833a1120c85db0456c.png

    程序根据设定的公钥65537计算出私钥,并对明文进行了加密和解密操作,执行结果验证了程序的正确性。

    RSA加密体制既可用于关键数据文件加密,也可用于数字签名,目前已被广泛应用于各种安全和认证领域,如Web服务器和浏览器信息安全,Email的安全和认证。对远程登录的安全保证和网上银行的身份验证等。运用JAVA语言实现的RSA密码算法,结合了JAVA语言良好的跨平台性和安全性,具有广阔的应用前景。

    小知识之公开密钥

    公开密钥也称为非对称密钥,每个人都有一对唯一对应的密钥:公开密钥(简称公钥)和私人密钥(简称私钥),公钥对外公开,私钥由个人秘密保存;用其中一把密钥加密,就只能用另一把密钥解密。非对称密钥加密算法的典型代表是RSA。

    展开全文
  • RSA加密算法是一种非对称加密算法,其玩法打破了以往所有加密算法的规则.在RSA出现之前,所有的加密方法都是同一种模式:加密解密的规则使用同一种方式.这种长达几个世纪的加密方案有一个致命的缺陷.在传递加密信息时,...

    什么是RSA加密算法?

    RSA加密算法是一种非对称加密算法,其玩法打破了以往所有加密算法的规则.在RSA出现之前,所有的加密方法都是同一种模式:加密解密的规则使用同一种方式.这种长达几个世纪的加密方案有一个致命的缺陷.在传递加密信息时,必须让对方拿到解密的规则才能正常解密.由于加密解密的规则一致,所以保存和传递"密钥",就成了最头疼的问题。

    • 使用公钥加密的数据,利用私钥进行解密
    • 使用私钥加密的数据,利用公钥进行解密

    RSA加密使用了"一对"密钥.分别是公钥和私钥,这个公钥和私钥其实就是一组数字!其二进制位长度可以是1024位或者2048位.长度越长其加密强度越大,目前为止公之于众的能破解的最大长度为768位密钥,只要高于768位,相对就比较安全.所以目前为止,这种加密算法一直被广泛使用.

    如何使用?

    公钥PK
    私钥SK
    明文P
    RSA加密算法
    密文T
    网络传输
    RSA解密算法
    明文P

    生成RSA非对称密钥对 SK&PK

    /**
         /**
         * 生成RSA密钥对
         *
         * @return Keys.Rsa
         * @throws NoSuchAlgorithmException
         */
        public static Keys.Rsa genKey() throws NoSuchAlgorithmException {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
            keyPairGen.initialize(1024, new SecureRandom());
            KeyPair keyPair = keyPairGen.generateKeyPair();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            String publicKeyString = Tools.encodeToString(publicKey.getEncoded());
            String privateKeyString = Tools.encodeToString((privateKey.getEncoded()));
            Keys.Rsa rsa = new Keys().new Rsa(publicKeyString, privateKeyString);
            return rsa;
        }
    

    RSA 公钥加密

    /**
         /**
         * RSA 公钥加密
         *
         * @param str
         * @param publicKey
         * @return
         * @throws Exception
         */
        public static String encrypt(String str, String publicKey) throws Exception {
            //base64编码的公钥
            byte[] keyBytes = Tools.decode(publicKey);
            KeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(keySpec);
            //RSA加密
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            String outStr = Tools.encodeToString(cipher.doFinal(str.getBytes(Charsets.UTF_8)));
            return outStr;
        }
    

    RSA 私钥解密

    /**
         /**
         * RSA 私钥解密
         *
         * @param str
         * @param privateKey
         * @return
         * @throws Exception
         */
        public static String decrypt(String str, String privateKey) throws Exception {
            //base64编码的私钥
            byte[] keyBytes = Tools.decode(privateKey);
            KeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(keySpec);
            //RSA解密
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            //64位解码加密后的字符串
            byte[] inputByte = Tools.decode(str.getBytes(Charsets.UTF_8));
            return new String(cipher.doFinal(inputByte));
        }
    

    Test测试

    import com.alibaba.fastjson.JSON;
    import com.pnoker.common.bean.encryp.Keys;
    import com.pnoker.common.utils.encryp.AesTools;
    import com.pnoker.common.utils.encryp.RsaTools;
    import lombok.extern.slf4j.Slf4j;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    /**
     * <p>Copyright(c) 2018. Pnoker All Rights Reserved.
     * <p>Author     : Pnoker
     * <p>Email      : pnokers@gmail.com
     * <p>Description: AES\RSA 加密算法测试
     */
    @Slf4j
    public class TestEncrypt {
    	@Test
        public void aesTest() throws Exception {
            Keys.Aes aes = AesTools.genKey();
            log.info(" aes key : {}", JSON.toJSONString(aes));
            String str = "nihao@ks.pnoker.cn,nihao@ks.pnoker.cn";
            log.info("str : {}", str);
            String ens = AesTools.encrypt(str, aes.getPrivateKey());
            log.info("ens : {}", ens);
            String des = AesTools.decrypt(ens, aes.getPrivateKey());
            log.info("des : {}", des);
        }
        
        @Test
        public void rsaTest() throws Exception {
            Keys.Rsa rsa = RsaTools.genKey();
            log.info(" rsa key : {}", JSON.toJSONString(rsa));
            String str = "nihao@ks.pnoker.cn,nihao@ks.pnoker.cn";
            log.info("str : {}", str);
            String ens = RsaTools.encrypt(str, rsa.getPublicKey());
            log.info("ens : {}", ens);
            String des = RsaTools.decrypt(ens, rsa.getPrivateKey());
            log.info("des : {}", des);
        }
    }
    

    Base64工具类

    import com.google.common.base.Charsets;
    
    import java.util.Base64;
    
    /**
     * <p>Copyright(c) 2018. Pnoker All Rights Reserved.
     * <p>Author     : Pnoker
     * <p>Email      : pnokers@gmail.com
     * <p>Description: 工具类
     */
    public class Tools {
        /**
         * 将字符串进行Base64编码
         *
         * @param str
         * @return 返回字节流
         */
        public static byte[] encode(String str) {
            byte[] bytes = Base64.getEncoder().encode(str.getBytes(Charsets.UTF_8));
            return bytes;
        }
    
        /**
         * 将字节流进行Base64编码
         *
         * @param bytes
         * @return 返回字符串
         */
        public static String encodeToString(byte[] bytes) {
            String str = Base64.getEncoder().encodeToString(bytes);
            return str;
        }
    
        /**
         * 必须配合encode使用,用于encode编码之后解码
         *
         * @param str 字符串
         * @return 返回字节流
         */
        public static byte[] decode(String str) {
            byte[] bytes = Base64.getDecoder().decode(str);
            return bytes;
        }
    
        /**
         * 必须配合encode使用,用于encode编码之后解码
         *
         * @param input 字节流
         * @return 返回字节流
         */
        public static byte[] decode(byte[] input) {
            byte[] bytes = Base64.getDecoder().decode(input);
            return bytes;
        }
    }
    

    实体封装类

    import lombok.AllArgsConstructor;
    import lombok.Data;
    
    /**
     * <p>Copyright(c) 2018. Pnoker All Rights Reserved.
     * <p>Author     : Pnoker
     * <p>Email      : pnokers@gmail.com
     * <p>Description: AES & RSA 算法密钥实体类
     */
    public class Keys {
    
        /**
         * RSA 密钥对
         */
        @Data
        @AllArgsConstructor
        public class Rsa {
            private String publicKey;
            private String privateKey;
        }
    
        /**
         * Aes 密钥
         */
        @Data
        @AllArgsConstructor
        public class Aes {
            private String privateKey;
        }
    }
    

    完整例子推荐

    IOT应用实例下载 AES/RSA算法


    项目推荐



    DC3是基于Spring Cloud的开源可分布式物联网(IOT)平台,用于快速开发、部署物联设备接入项目,是一整套物联系统解决方案。

    展开全文
  • 主要介绍了Java实现RSA加密解密算法,结合实例形式分析了java RAS加密解密算法的相关实现技巧,需要的朋友可以参考下
  • RSA加密算法原理及其Java实现

    千次阅读 2019-10-23 19:31:32
    简单介绍了RSA加密算法的原理及其Java实现:原文过长时,进行了分段加密。 RSA加密算法的基本原理 主要步骤 本文所有的字母都为正整数。 其主要步骤如下: 1、取两个不相等的质数p、q,一般都比较大。例如:p=67,q...


    简单介绍了RSA加密算法的原理及其Java实现:原文过长时,进行了分段加密。

    RSA加密算法的基本原理

    主要步骤

    本文所有的字母都为正整数。
    其主要步骤如下:
    1、取两个不相等的质数p、q,一般都比较大。例如:p=67,q=79。
    2、n=p×q,其中n所对应的二进制长度即为密钥的长度,一般为1024位或2048位。n=67×79=5293,转化为二进制数为1 0100 1010 1101,共13位。
    3、计算n的欧拉函数f(n):
    欧拉函数f(n)定义为:小于n的正整数中和n组成互斥关系的正整数的个数。由欧拉函数的性质:(1)如果正整数可以分解为两个互斥整数之积,则有该正整数的欧拉函数等于两个互斥整数的欧拉函数之积;(2)如果整数为质数,其欧拉函数为该整数减一。则有:
    f ( n ) = f ( p ) ∗ f ( q ) = ( p − 1 ) ∗ ( q − 1 ) (1) f(n)=f(p)*f(q)=(p-1)*(q-1)\tag{1} f(n)=f(p)f(q)=(p1)(q1)(1)
    f(n)=66×78=5148
    4、任选一整数x满足1<x<f(n),且x与f(n)互斥。选x=19
    5、计算x关于f(n)的模反元素y,即满足:
    ( x ∗ y ) % f ( n ) = 1 x y = h f ( n ) + 1 (2) (x*y)\%f(n)=1\tag{2}\\ xy=hf(n)+1 (xy)%f(n)=1xy=hf(n)+1(2)
    %为取余。
    通过扩展欧几里得算法求解19y=5148h+1:
    在这里插入图片描述
    求得y=271,h=-1。
    则(n,x)为公钥,(n,y)为私钥,假设原文为a(这里的原文是要转换为ascii码或者其他编码方式,用数字表示),且a小于n,则获取密文b的加密过程为:
    b = a x % n (3) b=a^{x}\%n\tag{3} b=ax%n(3)
    解密过程为:
    a = b y % n (4) a=b^{y}\%n\tag{4} a=by%n(4)
    假设传递字符A,其ascii码值为65,则通过(3)式计算得到b=1863,通过(4)式解密得到a=65。注意这里数字足够大,以至于使用普通整数计算得到的结果是错误的。

    BigInteger num1 = new BigInteger("65");
    BigInteger num2 = new BigInteger("5293");
    BigInteger b = num1.pow(19).mod(num2);
    System.out.println(b); 
    System.out.println("普通的整数运算是错误的:"+Math.pow(65, 19)%5293);  
    BigInteger a = b.pow(271).mod(num2);
    System.out.println(a);
    // 输出为:
    1863
    普通的整数运算是错误的:4055.0
    65
    

    可靠性说明:因为公钥是公开的,所以破解的方法就是获取y,那么在已知n和x的情况下能否求解出y呢?
    (1)通过步骤5可知,只有知道x和f(n)才能求解y;
    (2)要计算f(n)需要得到p和q;
    (3)n=pq,只有将n进行因式分解才能算出p和q。
    大整数的因式分解是很难的,所以RSA加密算法可靠。

    解密过程证明

    下面给出解密公式正确性的证明,即证明(4)式成立:
    通过(3)式得:
    b = a x − k n (5) b=a^{x}-kn\tag{5} b=axkn(5)
    将(5)式代入到(4)式等号右边得:
    b y % n = ( a x − k n ) y % n = ( a x y + n K ( n ) ) % n = a x y % n (6) b^{y}\%n=(a^{x}-kn)^{y}\%n=(a^{xy}+nK(n))\%n=a^{xy}\%n\tag{6} by%n=(axkn)y%n=(axy+nK(n))%n=axy%n(6)
    这里用到了多项式的因式分解:
    ( x + y ) n = x n + ( n 1 ) x y n − 1 + . . . + ( n n − 1 ) x n − 1 y + y n (7) (x+y)^n=x^n+\binom{n}{1}xy^{n-1}+...+\binom{n}{n-1}x^{n-1}y+y^{n}\tag{7} (x+y)n=xn+(1n)xyn1+...+(n1n)xn1y+yn(7)
    其中只有第一项不包含y。
    将(2)式代入到(6)式,则只需要证明:
    a h f ( n ) + 1 % n = a (8) a^{hf(n)+1}\%n=a\tag{8} ahf(n)+1%n=a(8)
    下面分情况进行讨论:
    情况1、a和n互斥。
    这里引入欧拉定理:如果a和n互斥,n的欧拉函数为f(n),则
    a f ( n ) % n = 1 (9) a^{f(n)}\%n=1\tag{9} af(n)%n=1(9)
    根据欧拉定理:
    a f ( n ) = 1 + g n → a h f ( n ) = ( 1 + g n ) h a h f ( n ) + 1 = a f ( n ) ∗ a = ( 1 + g n ) h ∗ a = ( 1 + h g n + . . . + h g h − 1 n h − 1 + g h n h ) a (10) a^{f(n)}=1+gn→a^{hf(n)}=(1+gn)^{h}\\ a^{hf(n)+1}=a^{f(n)}*a=(1+gn)^{h}*a=(1+hgn+...+hg^{h-1}n^{h-1}+g^{h}n^{h})a\tag{10} af(n)=1+gnahf(n)=(1+gn)hahf(n)+1=af(n)a=(1+gn)ha=(1+hgn+...+hgh1nh1+ghnh)a(10)
    将(10)式代入到(8)式,则可证明(8)式成立。
    情况2、a和n不互斥。
    由于n为两个质数的乘积,a<n,所以必有a=kp或a=kq,不妨假设a=kp,此时a与q互斥。根据欧拉定理:
    a f ( q ) % q = 1 → a f ( q ) = 1 + g q (11) a^{f(q)}\%q=1→a^{f(q)}=1+gq\tag{11} af(q)%q=1af(q)=1+gq(11)
    a h f ( n ) + 1 % q = ( a f ( q ) ) f ( p ) ∗ a % q = ( 1 + g q ) f ( p ) ∗ a % q = a a h f ( n ) + 1 = a + t q (12) a^{hf(n)+1}\%q=(a^{f(q)})^{f(p)}*a\%q=(1+gq)^{f(p)}*a\%q=a\tag{12}\\ a^{hf(n)+1}=a+tq ahf(n)+1%q=(af(q))f(p)a%q=(1+gq)f(p)a%q=aahf(n)+1=a+tq(12)
    因为a=kp,所以必然有:
    a h f ( n ) + 1 % p = 0 (13) a^{hf(n)+1}\%p=0\tag{13} ahf(n)+1%p=0(13)

    ( a + t q ) % p = t q % p = 0 (14) (a+tq)\%p=tq\%p=0\tag{14} (a+tq)%p=tq%p=0(14)
    又因为pq互斥,则由t=rp,代入到式(12)得:
    a h f ( n ) + 1 = a + r p q = a + r n ( a + r n ) % n = a → a h f ( n ) + 1 % n = a a^{hf(n)+1}=a+rpq=a+rn\\ (a+rn)\%n=a→a^{hf(n)+1}\%n=a ahf(n)+1=a+rpq=a+rn(a+rn)%n=aahf(n)+1%n=a
    得证(8)式。
    结合情况1、2,则可证明解密公式得正确性。

    java实现

    package mytest;
    
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.interfaces.RSAPrivateCrtKey;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.Arrays;
    import java.util.Base64;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    
    import javax.crypto.Cipher;
    
    
    public class RSAUtil {
    	// 密钥长度,可调
    	public static int keyLength = 1025;
    	// 注意这里1024对应128byte,其中11byte用来存储相关信息,所以1024最多加密117Byte数据
    	// 若超过117Byte需要分段,计算公式为keyLength/8并向上取整再减去11
    	// 解密时候长度为keyLength/8向上取整
    
    	// 存储密钥
    	public static Map<String, String> keyMap = new HashMap<String, String>();
    	
    	public static void main(String[] args) throws Exception {
    		//生成公钥和私钥
    		geneKeyPair();
    		// 输入原文
    		System.out.print("输入原文:");
    		Scanner in = new Scanner(System.in);
    		String message = in.nextLine();
    		//String message = "1aa";
    		System.out.println("随机生成的公钥为:" + keyMap.get("publicKey"));
    		System.out.println("随机生成的私钥为:" + keyMap.get("privateKey"));
    		//加密字符串
    		String messageEnctypt = encrypt(message, keyMap.get("publicKey"));
    		System.out.println("原文:"+message + "\n加密后的字符串为:" + messageEnctypt);
    		
    		String messageDecrypt = decrypt(messageEnctypt, keyMap.get("privateKey"));
    		System.out.println("还原后的字符串为:" + messageDecrypt);
    		
    		in.close();
    	}
    	
    	/**
    	 * function:随机生成密钥对并存放在keyMap中
    	 * 也可以直接保存RSAPublicKey对象和RSAPrivateCrtKey对象
    	 * 一般情况下密钥可能会保存在本地或者其他地方,然后直接读取密钥,这时候存储的一般是密钥字符串
    	 * @throws NoSuchAlgorithmException 
    	 */
    	public static void geneKeyPair() throws NoSuchAlgorithmException {
    		// RSA密钥生成器
    		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    		// 初始化密钥生成器
    		keyPairGenerator.initialize(keyLength, new SecureRandom());
    		// 生成密钥对并保存
    		KeyPair keyPair = keyPairGenerator.generateKeyPair();
    		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 公钥
    		RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) keyPair.getPrivate();  // 私钥
    
    		String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());  // 公钥字符串
    		String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());  // 私钥字符串
    		// 存放
    		keyMap.put("publicKey", publicKeyString);
    		keyMap.put("privateKey", privateKeyString);
    	}
    	
    	/*
    	 * function:加密
    	 * @param 明文
    	 * @param 公钥字符串,十六进制字符串
    	 * @return 密文
    	 * @throws Exception
    	 */
    	public static String encrypt(String input, String publicKeyString) throws Exception {
    		// 从字符串获取公钥
    		byte[] decoded = Base64.getDecoder().decode(publicKeyString.getBytes());
    		RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); 
    		// 加密
    		Cipher cipher = Cipher.getInstance("RSA");
    		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    		byte[] inputArr = input.getBytes();
    		StringBuilder output = new StringBuilder();
    		int splitLength = (int) Math.ceil((float)keyLength/8) - 11;  // 分段长度
    		for(int i = 0; i < inputArr.length; i += splitLength) {  // 分段加密
    			int len = inputArr.length-i >= splitLength ? splitLength :  inputArr.length-i;
    			output.append(byteArray2HexString(cipher.doFinal(Arrays.copyOfRange(inputArr, i, i+len))));
    		}
    		return output.toString();
    	}
    	
    	
    	/*
    	 * function:私钥解密
    	 * @param 密文
    	 * @param 私钥字符串
    	 * @return 明文
    	 * @throws Exception
    	 */
    	public static String decrypt(String input, String privateKeyString) throws Exception {
    		// 从字符串获取私钥
    		byte[] decoded = Base64.getDecoder().decode(privateKeyString.getBytes());
    		RSAPrivateKey privateKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); 
    		// 解密
    		Cipher cipher = Cipher.getInstance("RSA");
    		cipher.init(Cipher.DECRYPT_MODE, privateKey);
    		
    		int splitLength = (int) Math.ceil((float)privateKey.getModulus().bitLength()/8);  // 分段长度
    		byte[] inputArr = hexString2byteArray(input);
    		StringBuilder output = new StringBuilder();
    		for(int i = 0; i < inputArr.length; i += splitLength) {  // 分段解密
    			int len = inputArr.length-i >= splitLength ? splitLength :  inputArr.length-i;
    			output.append(new String(cipher.doFinal(Arrays.copyOfRange(inputArr, i, i+len))));
    		}
    		return output.toString();
    	}
    	
    	public static int getKeyLength() {
    		return keyLength;
    	}
    	/*
    	 * function:设置密钥长度
    	 */
    	public static void setKeyLength(int keyLength) {
    		// RSA keys must be at least 512 bits long
    		if(keyLength < 512) {
    			keyLength = 512;
    		}
    		RSAUtil.keyLength = keyLength;
    	}
    	
    	/*
    	 * function:byte[]转换为十六进制字符串
    	 * byte占8位,可以用两位16进制数表示
    	 * @param byte[]
    	 * @return String
    	 */
    	public static String byteArray2HexString(byte[] bytes) {
    		StringBuilder output = new StringBuilder();
    		String temp;
    		for(byte b : bytes) {
    			temp = Integer.toHexString(0xff & b);
    			if(temp.length() == 1) {
    				output.append(0);
    			}
    			output.append(temp);
    		}
    		return output.toString();
    	}
    	
    	/*
    	 * function:十六进制字符串转换位byte[]
    	 * @param String
    	 * @return byte[]
    	 */
    	public static byte[] hexString2byteArray(String hexString) {
    		int len = hexString.length() / 2;
    		byte[] output = new byte[len];
    		for(int i = 0; i < len; i++) {
    			int pos = i * 2;
    			output[i] = (byte) (char2Byte(hexString.charAt(pos)) << 4 | char2Byte(hexString.charAt(pos+1)));
    		}
    		return output;
    	}
    	
    	/*
    	 * function: char转换位byte,这里的char只包含0123456789abcdef
    	 * @param char
    	 * @return byte
    	 */
    	private static byte char2Byte(char c) {
    		byte b = (byte)"0123456789abcdef".indexOf(c);
    		return b;
    	}
    }
    
    

    测试结果:

    输入原文:sadjhfkkjasdghjkhadkjsdhgksdhgjkshgdweuosyhjkhfsdg5sd4g5s4dg1564h56d4as1gd521f56a1sa3f54a654g5s6d41fg56ha456sd41f23g1h5a6s4dg1gf2asd5g45
    随机生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo+UfWVK/CQVayLR5DRy9ydyahLUjr0Eq4xD6pXmMouNWgSjWkiEiQ2eWE3RfAVI89qGYwvD76VvBd+uO9lMLZmh3aVk+Iu0ajTwEt4UxI3T3oGpirYYHWIBHNmcKrRyuGPpQZd+klNzzJeiS+/4Ee5mOPEKun5kJs33D61o4kKwIDAQAB
    随机生成的私钥为:MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKj5R9ZUr8JBVrItHkNHL3J3JqEtSOvQSrjEPqleYyi41aBKNaSISJDZ5YTdF8BUjz2oZjC8PvpW8F36472UwtmaHdpWT4i7RqNPAS3hTEjdPegamKthgdYgEc2ZwqtHK4Y+lBl36SU3PMl6JL7/gR7mY48Qq6fmQmzfcPrWjiQrAgMBAAECgYBZKkodMM0abc4o8aQRjoPcHEH3NWVQgrabb3s9dsBOodKg5egOrZfVUBZMmTrKVBTOTYm3V+7HvY7TmOwKg3CZ9UzxYrhhIbh7p42gAIlpnyiq7YCz3X0hz+FrRKEOJJ5eLINKxl6w3jOG1ZeY9FIHUrGIb0KJe/a5m1gkG8zFoQJBAN0zS/DPpDNJKCrnxRs1TijtLdL9JgOle7ecPKp2kbJQB6RLmJ5/675JrlR1SD5N9E4KUdgEsyF4uUr3cew6XlsCQQDDjpcTHn3wgjZOGU8WAuNHV132TSfT1YiCttFjRuXNtGVrmYdbyZh77g6qbk+DxjJ1Zw0dNh1WhsGyLOTCI9pxAkAJxW1SWunG9jFXC9vyIr2sIyYGDvax7Ip1hupLIWe4N77OrCQ2xDHWuwx/YJrrXagwFladMz/yd5G/1QRsSfvHAkB50wuEapt0R/oCnzuob7YczG2Jsbkc+0pme/NnUFR62GXSKTusz6LBmaTjQYMhiUgH4WHHD94o+BwUnmkIFIPRAkAr5ToL9zeevlwYvIxqd4++Vdcfm+1uDbxa0Rjm00ay5S3fS/3jXHs0j+CB2faxakVUYueMKmdUoYpWKfgOOk7A
    原文:sadjhfkkjasdghjkhadkjsdhgksdhgjkshgdweuosyhjkhfsdg5sd4g5s4dg1564h56d4as1gd521f56a1sa3f54a654g5s6d41fg56ha456sd41f23g1h5a6s4dg1gf2asd5g45
    加密后的字符串为:9186b953a69941d47b35e0abff66356c03b29e3b0be1b1187f845fd212f2bf14e9fe56484fd5b15b23782d960545bb6cb1a992142315857a6f2854e81f89c20216b5e15cf9b5496350c17224f1820fe4445044ce0adf10eba16d130dd63885b6ede13a3670009e2493f1eeaaee35e67fdcd8373692449dab4382196d85ee84861680fc1613ce132c731d6be0d34e00c7ed04a6a0c8b695a0f91983931de47ec2221575d60023cf223ac5b70c047c9c6b155e20723770cbdb13f45014656244f1894205cb8a2a4d029b3cdd2de9b1cbf1729e5ddcdf3314145c6db93a593b8e1f38c70dc064147a3d6ffaf9a21d338fa5d9a676a9449e37c8d9446abea15f1dfc
    还原后的字符串为:sadjhfkkjasdghjkhadkjsdhgksdhgjkshgdweuosyhjkhfsdg5sd4g5s4dg1564h56d4as1gd521f56a1sa3f54a654g5s6d41fg56ha456sd41f23g1h5a6s4dg1gf2asd5g45
    
    展开全文
  • RSA 加密算法实现Java

    千次阅读 2019-05-17 22:52:29
    (这里不是用 jdk 自带的RSA加密实现,具体是什么可以自行百度了解) 本文的数据类型采用 BigInteger 类。 一、RSA算法实现过程 ① 选择两个大素数 p 和 q ② 计算乘积 n = p * q 和 Fn = (p - 1) * (q...
  • MD5和RSA加密算法Java完成实现

    千次下载 热门讨论 2014-05-21 22:29:18
    MD5和RSA加密算法Java完成实现,及实现RSA需要用的jar包。参见博文 http://blog.csdn.net/yanzi1225627/article/details/26508035
  • RSA算法Java实现

    2019-03-23 16:27:06
    RSAPrivateKey prk = (RSAPrivateKey) b.readObject(); BigInteger d = prk.getPrivateExponent(); // 获取私钥参数及解密 BigInteger n = prk.getModulus(); System.out.println("d= " + d); System.out...
  • 简单的RSA加密算法,用JAVA语言实现的,RSA算法
  • Java——RSA加密算法

    千次阅读 2021-12-26 21:14:55
    Java实现RSA加密算法 package RSAtest; import javax.crypto.Cipher; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; /** * @author ...
  • 主要介绍了Java加密算法RSA代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • RSA算法JAVA实现完整版

    千次阅读 2021-04-27 11:53:23
    1、RSAUtils package rsa; import javax.crypto.Cipher;...import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeyS.
  • RSA密码加密Java实现

    千次阅读 2021-08-06 22:01:34
    RSA加解密
  • RSA加密算法java编程实现宣贯.pdf
  • 基于JavaRSA加密算法实现

    千次阅读 2018-05-08 17:13:27
    一、RSA算法描述(1)选取长度相等的两个大素数p、q,计算其乘积n=p.q(2)计算n的欧拉数Φ(n)=(p-1).(q-1)(3)随机选择...(5)加密明文:Ci=mi^e(modn)(6)解密密文:mi=Ci^d(modn)二、RSA实现Java代码1...
  • RSA算法,有界面操作,能随机产生素数,进而随机产生公钥和私钥,功能完善
  • 关键:(1)Java支持NoPadding填充方式,并且已经封装好相应的接口,可通过Cipher.getInstance来指定RSA/ECB/NoPadding该对齐和填充方式; (2)Golang中不支持NoPadding的填充方式,需要自己处理;
  • 包括RSA算法的两种语言实现,原理正确,可以正常运行,对应博客为:https://blog.csdn.net/qq_41112170/article/details/104904340
  • RSA加密算法实现

    千次阅读 2021-10-21 20:16:08
    由于在银行方面工作对数据安全性要求比较高,需要对前后端通信的数据进行加密,因此编写一个简易的RSA加密算法工具类,可以提高前后端传送数据时的安全性。再次罗列下来,希望自己能有一个更好的理解以及帮助到有...
  • RSA加密算法JAVA实现

    2019-12-27 18:37:02
    运行环境:Windows + eclipse + JAVA RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。
  • 主要介绍了Java中RSA加密解密的实现方法,结合具体实例形式分析了java实现RSA加密解密算法的具体步骤与相关操作技巧,并附带了关于RSA算法密钥长度/密文长度/明文长度的参考说明,需要的朋友可以参考下

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 28,669
精华内容 11,467
关键字:

rsa加密算法java实现

java 订阅