本帖最后由 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那里有点晕。。。
[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();
----输出
然后发现这个对长的报文加密会报错【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;
}
}
}
|