吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1083|回复: 6
收起左侧

[讨论] java加密解密

[复制链接]
wuqingvika 发表于 2023-4-7 17:11
本帖最后由 wuqingvika 于 2023-4-13 17:09 编辑

想知道 企业里分发密钥形式一般是怎么样的
  • 数据发送方1)制作签名 把明文+时间戳,用发送方私钥生成签名字符串,把字符串拼接在明文数据和时间戳之后。平台要求接口传递的参数必须做签名,以防止接口参数被任意篡改。签名摘要是根据所传输参数动态生成,具体算法为:签名=32md5(密文 +厂商id + API密钥)后的大写字母。接口 POST 数据即通过公钥加密的密文数据,同时将 idc_id 和 req_sign 放入请求头中。2)加密 把拼接后的数据,用接收方公钥对Json数据进行RSA2048加密,再 base64 编码得到密文字符串。 3)调用 https 接口发送数据
  • 数据接收方 1)收到数据,先解密 把密文数据用接收方的私钥进行解密,得到明文数据+时间戳+签名字符 串。2)验签 用发送方的公钥对签名进行验签。 3)验签通过,正常处理业务。

自己网上学了个小例子 不过在keySpec那里有点晕。。。
[Java] 纯文本查看 复制代码
package XXX.XXX;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * [url=home.php?mod=space&uid=686208]@AuThor[/url] qwu
 * [url=home.php?mod=space&uid=686237]@date[/url] 2023/4/7
 **/
public class GcgsRSA {
    PublicKey publicKey;
    PrivateKey privateKey;

    String pk;
    String sk;
    public void getPublicKey() {
        KeySpec keySpec=new X509EncodedKeySpec(Base64.getDecoder().decode(pk));
        //再通过密钥工厂
        try {
            KeyFactory keyFactory=KeyFactory.getInstance("RSA");
            PublicKey publicKey2 = keyFactory.generatePublic(keySpec);
            System.out.println("根据String类型密钥产生的publicKey=="+Base64.getEncoder().encodeToString(publicKey2.getEncoded()));

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

    }

    public void getPrivateKey() {
        KeySpec keySpec=new PKCS8EncodedKeySpec(Base64.getDecoder().decode(sk));
        //再通过密钥工厂
        try {
            KeyFactory keyFactory=KeyFactory.getInstance("RSA");
            PrivateKey privateKey1 = keyFactory.generatePrivate(keySpec);
            System.out.println("根据String类型密钥产生的privateKey=="+Base64.getEncoder().encodeToString(privateKey1.getEncoded()));

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

    }

    String encode(String clearText){
        //对明文加密
        try {
            Cipher cipher= Cipher.getInstance("RSA");//获取RSA算法
            //指定密钥
            cipher.init(Cipher.ENCRYPT_MODE,publicKey);//指定工作模式为加密 公钥加
            byte[] bytes = cipher.doFinal(clearText.getBytes());//进行加密
            //再将加密结果转成base64
            return Base64.getEncoder().encodeToString(bytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return "error";
    }

    String decode(String encryptText){
        //对加密的密文(base64编码)解密
        try {
            Cipher cipher= Cipher.getInstance("RSA");//获取RSA算法
            //指定密钥
            cipher.init(Cipher.DECRYPT_MODE,privateKey);//指定工作模式为解密 用私钥解
            //再将加密密文进行base64解码
            byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(encryptText));//进行解密
            return new String(bytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return "error";
    }


    public GcgsRSA(int key_size) {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            //指定生成密钥长度
            keyPairGenerator.initialize(key_size);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();//产生密钥对
            publicKey=keyPair.getPublic();//产生公钥
            privateKey=keyPair.getPrivate();//私钥
            //为了可读转成base64编码
            pk=Base64.getEncoder().encodeToString(publicKey.getEncoded());
            sk=Base64.getEncoder().encodeToString(privateKey.getEncoded());
            System.out.println("base64后的公钥=="+ pk);
            System.out.println("base64后的私钥=="+ sk);



        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}




-----main函数

[Java] 纯文本查看 复制代码
  GcgsRSA gcgsRSA=new GcgsRSA(2048);

        String clearText="hello wq,我在练手";
        String encryptText = gcgsRSA.encode(clearText);
        String decryptText=gcgsRSA.decode(encryptText);

        System.out.println(clearText+"----->----加密后的字符串===="+encryptText);
        System.out.println(decryptText);


        gcgsRSA.getPublicKey();
        gcgsRSA.getPrivateKey();



----输出
image.png


然后发现这个对长的报文加密会报错【javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes】
需要分层加密解密,新代码如下但是具体加密解密过程还是很晕
[Java] 纯文本查看 复制代码
import javax.crypto.Cipher;
import java.security.*;
import java.util.Base64;
import java.util.Random;

public class RSAExample {

    private static final int KEY_SIZE = 2048;
    private static final int BLOCK_SIZE = KEY_SIZE / 8 - 11; // 块大小

    public static void main(String[] args) throws Exception {
        // 生成公钥、私钥对
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(KEY_SIZE, new SecureRandom());
        KeyPair keyPair = kpg.generateKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        // 要加密的数据
        String originalText = generateRandomString(5000);//随机生成一个长的字符测试分块加密
       // String originalText = "这里放很长很长的This is a very long message that needs to be encrypted using RSA2048. This message is so long that it cannot be encrypted in one go.";
        // 加密操作
        byte[] inputBytes = originalText.getBytes();
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = null;
        for (int i = 0; i < inputBytes.length; i += BLOCK_SIZE) {
            int remainingBytes = Math.min(BLOCK_SIZE, inputBytes.length - i);
            byte[] inputBlock = new byte[remainingBytes];
            System.arraycopy(inputBytes, i, inputBlock, 0, remainingBytes);
            byte[] outputBlock = cipher.doFinal(inputBlock);
            encryptedBytes = appendArray(encryptedBytes, outputBlock);
        }
        String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);

        // 解密操作
        byte[] decryptedBytes = null;
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        for (int i = 0; i < encryptedBytes.length; i += KEY_SIZE / 8) {
            int remainingBytes = Math.min(KEY_SIZE / 8, encryptedBytes.length - i);
            byte[] inputBlock = new byte[remainingBytes];
            System.arraycopy(encryptedBytes, i, inputBlock, 0, remainingBytes);
            byte[] outputBlock = cipher.doFinal(inputBlock);
            decryptedBytes = appendArray(decryptedBytes, outputBlock);
        }
        String decryptedText = new String(decryptedBytes);

        // 输出加密解密结果
        System.out.println("Original text: " + originalText);
        System.out.println("Encrypted text: " + encryptedText);
        System.out.println("Decrypted text: " + decryptedText);
        System.out.println(originalText.equals(decryptedText));
    }

    private static String generateRandomString(int length) {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            char c = (char) ('A' + random.nextInt(26));
            sb.append(c);
        }
        return sb.toString();
    }

    /**
     * 拼接两个字节数组,返回结果数组
     */
    private static byte[] appendArray(byte[] origArray, byte[] newArray) {
        if (origArray == null) {
            return newArray.clone();
        } else {
            byte[] resultArray = new byte[origArray.length + newArray.length];
            System.arraycopy(origArray, 0, resultArray, 0, origArray.length);
            System.arraycopy(newArray, 0, resultArray, origArray.length, newArray.length);
            return resultArray;
        }
    }

}

免费评分

参与人数 3吾爱币 +2 热心值 +3 收起 理由
JinxBoy + 1 用心讨论,共获提升!
0106yingzi + 1 + 1 我很赞同!
ygiveupc + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

a382662643 发表于 2023-4-7 18:15
有点意思
2485dd 发表于 2023-4-7 18:19
adtic 发表于 2023-4-7 19:25
rainerosion 发表于 2023-4-7 21:13
挺好!!!
johntang386 发表于 2023-4-7 23:18
我来学习Java
wushui 发表于 2023-4-8 07:51
很不错,再搞一个国密算法吧
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 01:04

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表