wuqingvika 发表于 2023-4-7 17:11

java加密解密

本帖最后由 wuqingvika 于 2023-4-13 17:09 编辑

想知道 企业里分发密钥形式一般是怎么样的

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

自己网上学了个小例子 不过在keySpec那里有点晕。。。
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;

/**
* @AuThor qwu
* @date 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函数

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();


----输出



然后发现这个对长的报文加密会报错【javax.crypto.IllegalBlockSizeException: Data must not be longer than 245 bytes】
需要分层加密解密,新代码如下但是具体加密解密过程还是很晕

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;
            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;
            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;
            System.arraycopy(origArray, 0, resultArray, 0, origArray.length);
            System.arraycopy(newArray, 0, resultArray, origArray.length, newArray.length);
            return resultArray;
      }
    }

}

a382662643 发表于 2023-4-7 18:15

有点意思

2485dd 发表于 2023-4-7 18:19

正在学习,加油

adtic 发表于 2023-4-7 19:25

可以当个demo

rainerosion 发表于 2023-4-7 21:13

挺好!!!

johntang386 发表于 2023-4-7 23:18

我来学习Java

wushui 发表于 2023-4-8 07:51

很不错,再搞一个国密算法吧
页: [1]
查看完整版本: java加密解密