RSA 16进制加解密和签名

       本文 字数:1619 

  1.  密钥位数:1024。

  2. 密钥格式:PKCS#8。

  3. 数字签名签名/验证算法:SHA1withRSA。

  4. RSA最大加密明文大小:117

    RSA最大解密密文大小:128

       存在: 1、原RSA公私密钥对,转16进制公私密钥。2、自动生成16进制密钥对。3、使用16进制私钥签名。4、使用16进制公钥验证。5、使用16进制私钥进行原数据加密。6、使用16进制公钥进行解密。7、对于16进制公钥加密,16私钥解密本文不说说明,稍微改一下就可以使用。8、完整代码

 

需要对包

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.StringUtils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

 

 

1、原RSA公私密钥对,转16进制公私密钥

操作:先进性Base64解码,再把byte数组转成16进制即可。

代码:

//私钥
String privateKeyString = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMjT4WYC7xFo5CRw\n" +
        "dHSseOsAqZKV2Ksrjp54yysba66TbVJ9Ai1WioCsP7WBkCSnMbECfb1jfJl37km2\n" +
        "moMMrhrKXNmrKhO5kEKLKZQZdg+/wVugFyzRhxEOIBbEQ6mIeyWVee4zkg+R9GIy\n" +
        "gt9mGhrAhBqqO1lZaAn5/iF43seLAgMBAAECgYAWRlH4w5iKoMy1MffovPyIbEFi\n" +
        "rdYjXihqcVFvjZILAfUdMhpctv2Tugcy9ZTsS9MaJAGYUQGP8Bpw+Jz4rh5dTebx\n" +
        "c8cqZ9NhI9h0gceGYJPyvtw7KdUnFRkYnlcj3vOwR9x793nJl1Yo0APCYl4jk7he\n" +
        "sm4YcCGY52uF7dQGuQJBAPQpRp5VJYuLXzsNNVkxIb27gpfTJVaYZoto2FqlpYhV\n" +
        "USRKGuTP+/5BZjJOBTRMaJvDqy15Ev/PrIm+8+5mvxUCQQDSkLazWyzVPfFAWO7I\n" +
        "3ICv/REtNdXkFQ6FYtYLzgusxFaNr75RsJsgeXfSQxD9RmPb2ipKeY3ertU25ZIl\n" +
        "gBQfAkBURKat4N9LcTfV7rIZ7X4iuMPS2LoLUCAcP3xklMUz75ZIuxbbH/luAG5g\n" +
        "MFNVgIWeNQMwd5gaGDgJdpFEF8wdAkAYkOWf2z1Jy6Y/2aBSMteYsK+2VJeVupct\n" +
        "HLDYQ7u89lMayKwtn6sZiNJf548t3W59EeDpO3E/z6n0c6gvU9gFAkBRxq0RXi/2\n" +
        "5wpEjeRd+tL30WrC2PoTVN6San5cPkv2k6vVWmZJAAMB6RKHtp+r7yUYLcEcrZOG\n" +
        "7ARIDVY19ou5";

//公钥
String publicKeyString = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI0+FmAu8RaOQkcHR0rHjrAKmS\n" +
        "ldirK46eeMsrG2uuk21SfQItVoqArD+1gZAkpzGxAn29Y3yZd+5JtpqDDK4aylzZ\n" +
        "qyoTuZBCiymUGXYPv8FboBcs0YcRDiAWxEOpiHsllXnuM5IPkfRiMoLfZhoawIQa\n" +
        "qjtZWWgJ+f4heN7HiwIDAQAB";

//私钥16进制
byte[] bytes1 = Base64.decodeBase64(privateKeyString);
String pri = byte2Hex(bytes1);

//私钥16进制
byte[] ddd = Base64.decodeBase64(publicKeyString);
String pub = byte2Hex(ddd);

结果:

16进制私钥:30820275020100300d06092a864886f70d01010105000482025f3082025b02010002818100c8d3e16602ef1168e424707474ac78eb00a99295d8ab2b8e9e78cb2b1b6bae936d527d022d568a80ac3fb5819024a731b1027dbd637c9977ee49b69a830cae1aca5cd9ab2a13b990428b299419760fbfc15ba0172cd187110e2016c443a9887b259579ee33920f91f4623282df661a1ac0841aaa3b59596809f9fe2178dec78b0203010001028180164651f8c3988aa0ccb531f7e8bcfc886c4162add6235e286a71516f8d920b01f51d321a5cb6fd93ba0732f594ec4bd31a24019851018ff01a70f89cf8ae1e5d4de6f173c72a67d36123d87481c7866093f2bedc3b29d5271519189e5723def3b047dc7bf779c9975628d003c2625e2393b85eb26e18702198e76b85edd406b9024100f429469e55258b8b5f3b0d35593121bdbb8297d3255698668b68d85aa5a5885551244a1ae4cffbfe4166324e05344c689bc3ab2d7912ffcfac89bef3ee66bf15024100d290b6b35b2cd53df14058eec8dc80affd112d35d5e4150e8562d60bce0bacc4568dafbe51b09b207977d24310fd4663dbda2a4a798ddeaed536e5922580141f02405444a6ade0df4b7137d5eeb219ed7e22b8c3d2d8ba0b50201c3f7c6494c533ef9648bb16db1ff96e006e6030535580859e35033077981a18380976914417cc1d02401890e59fdb3d49cba63fd9a05232d798b0afb6549795ba972d1cb0d843bbbcf6531ac8ac2d9fab1988d25fe78f2ddd6e7d11e0e93b713fcfa9f473a82f53d805024051c6ad115e2ff6e70a448de45dfad2f7d16ac2d8fa1354de926a7e5c3e4bf693abd55a6649000301e91287b69fabef25182dc11cad9386ec04480d5635f68bb9
16进制公钥:30819f300d06092a864886f70d010101050003818d0030818902818100c8d3e16602ef1168e424707474ac78eb00a99295d8ab2b8e9e78cb2b1b6bae936d527d022d568a80ac3fb5819024a731b1027dbd637c9977ee49b69a830cae1aca5cd9ab2a13b990428b299419760fbfc15ba0172cd187110e2016c443a9887b259579ee33920f91f4623282df661a1ac0841aaa3b59596809f9fe2178dec78b0203010001
 

涉及的方法:

Base64:

org.apache.commons.codec.binary.Base64

byte2Hex:

/**
 * @param bytes,输入byte[]数组
 * @return 16进制字符
 * @Description: 将byte[]数组转换成16进制字符。一个byte生成两个字符,长度对应1:2
 * @Author: mastermind
 * @Date: 2020-04-06 12:16
 */
public static String byte2Hex(byte[] bytes) {
    if (bytes == null) {
        return null;
    }
    StringBuilder builder = new StringBuilder();
    // 遍历byte[]数组,将每个byte数字转换成16进制字符,再拼接起来成字符串
    for (int i = 0; i < bytes.length; i++) {
        // 每个byte转换成16进制字符时,bytes[i] & 0xff如果高位是0,输出将会去掉,所以+0x100(在更高位加1),再截取后两位字符
        builder.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
    }
    return builder.toString();
}

扩展:

得到16进制公私密钥,可以提取出指数和系数。

 

2、自动生成16进制密钥对 

操作:有代码直接生成

代码:

/**
 * 生成1024位RSA公私钥对。
 *
 * @return 私钥、公钥
 */
public static String[] genRSAKeyPair() {
    KeyPairGenerator rsaKeyGen = null;
    KeyPair rsaKeyPair = null;
    try {
        log.error("Generating a pair of RSA key ... ");
        rsaKeyGen = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = new SecureRandom();
        random.setSeed(("" + System.currentTimeMillis() * Math.random() * Math.random()).getBytes(Charset
                .forName("UTF-8")));
        rsaKeyGen.initialize(1024, random);
        rsaKeyPair = rsaKeyGen.genKeyPair();
        PublicKey rsaPublic = rsaKeyPair.getPublic();
        PrivateKey rsaPrivate = rsaKeyPair.getPrivate();

        String privateAndPublic[] = new String[2];
        privateAndPublic[0] = byte2Hex(rsaPrivate.getEncoded());
        privateAndPublic[1] = byte2Hex(rsaPublic.getEncoded());
        System.err.println("16私钥:" + privateAndPublic[0]);
        System.err.println("16公钥:" + privateAndPublic[1]);
        return privateAndPublic;
    } catch (Exception e) {
        log.error("genRSAKeyPair error:" + e.getMessage(), e);
        return null;
    }
}

结果:

16私钥:30820275020100300d06092a864886f70d01010105000482025f3082025b02010002818100b0fbba4081656a1cc681315dbd815ee0b198d293def06f2d8d6fb17b64542999a361ec4f7c04e4353aadbf0397169651643d7923e22f038b9b0cafd58c46cd6822ff0e22146612fd872d0b27aa3f1121cc95e144a940de10065c5b261f242f667fccfc5fd5422d82af71d7c4f900843d12949411d726d82ece8b3c8808b4da1d02030100010281807a5c2f72f583260feaf5db299221657537940ed28929f5d3aa9b743b792beeeef7d475caa655c36941be69f79377dc493d627ae462365adf243d6b3bdb1600603e4791eb1700414f189ae1b02b3b40c0093922a5888d1358aec92779546256f5a903a1bb88beacd44514bbd88b18871699a9a1944806bdb783886fcee1a6f349024100e040d5d61bfd4ae8f7b6b93cb6131a5d17dcd1a617032db1d96ee4d4982792e58697e9b67afdb7399b8d673cfb05f911099cc462c30dd932d63b8dbd2bf9e73b024100ca09c80d007e11a29fa7b5d9352c169d98d6def82c473a06687d8eb6589a371923763679c9da6458dd3d7d36bd81aace3236227aa05e86a65ac7773eed491e87024051063bfccb4a1e49c44ec9e8eca4444f4472ed70c439cac5ca98eda6fe7eb5eda64eb70bceae63083672c5cd5ba951cf5d18be402cd7911574203a5b124b8dc702406a15f0c142fcef6da0bf8330e6469c296c53870870d785944fd17dda2973f07276b85faa5b5f1d49bc01c979b0d0214bdbf9a8e912c40f97d21ae2765c4a048902400a02d95a302b6fa69b4da0f146ffdd7ecc0154d852a01023c9af11e13a03ab223ccd26f7be0bfeea4fc5b7904f19880e47c25d31d8f2c43c320b75a50211c9cd
16公钥:30819f300d06092a864886f70d010101050003818d0030818902818100b0fbba4081656a1cc681315dbd815ee0b198d293def06f2d8d6fb17b64542999a361ec4f7c04e4353aadbf0397169651643d7923e22f038b9b0cafd58c46cd6822ff0e22146612fd872d0b27aa3f1121cc95e144a940de10065c5b261f242f667fccfc5fd5422d82af71d7c4f900843d12949411d726d82ece8b3c8808b4da1d0203010001
 

3、使用16进制私钥签名 

 操作:由16进制私钥转成私钥对象,在进行签名运算

代码:

//16进制私钥
String pri = "30820275020100300d06092a864886f70d01010105000482025f3082025b02010002818100c8d3e16602ef1168e424707474ac78eb00a99295d8ab2b8e9e78cb2b1b6bae936d527d022d568a80ac3fb5819024a731b1027dbd637c9977ee49b69a830cae1aca5cd9ab2a13b990428b299419760fbfc15ba0172cd187110e2016c443a9887b259579ee33920f91f4623282df661a1ac0841aaa3b59596809f9fe2178dec78b0203010001028180164651f8c3988aa0ccb531f7e8bcfc886c4162add6235e286a71516f8d920b01f51d321a5cb6fd93ba0732f594ec4bd31a24019851018ff01a70f89cf8ae1e5d4de6f173c72a67d36123d87481c7866093f2bedc3b29d5271519189e5723def3b047dc7bf779c9975628d003c2625e2393b85eb26e18702198e76b85edd406b9024100f429469e55258b8b5f3b0d35593121bdbb8297d3255698668b68d85aa5a5885551244a1ae4cffbfe4166324e05344c689bc3ab2d7912ffcfac89bef3ee66bf15024100d290b6b35b2cd53df14058eec8dc80affd112d35d5e4150e8562d60bce0bacc4568dafbe51b09b207977d24310fd4663dbda2a4a798ddeaed536e5922580141f02405444a6ade0df4b7137d5eeb219ed7e22b8c3d2d8ba0b50201c3f7c6494c533ef9648bb16db1ff96e006e6030535580859e35033077981a18380976914417cc1d02401890e59fdb3d49cba63fd9a05232d798b0afb6549795ba972d1cb0d843bbbcf6531ac8ac2d9fab1988d25fe78f2ddd6e7d11e0e93b713fcfa9f473a82f53d805024051c6ad115e2ff6e70a448de45dfad2f7d16ac2d8fa1354de926a7e5c3e4bf693abd55a6649000301e91287b69fabef25182dc11cad9386ec04480d5635f68bb9";
//原数据
String data = "123456";
System.err.println("代签名数据:" + data);
//签名
String sign = sign(getPrivateKey(pri), data, "utf-8");
System.err.println("私钥16签名:" + sign);

结果:

代签名数据:123456
私钥16签名:885d59e3ff349d7fb03903e2304556ceadfea1bf38c972575d20489e69e4b178bc7076db216a9150e7beac7b263eb967fe9129c6c1d70e127d379d0fe048531e0083fb3cd7e8415f68c91f7f1756c0e50dc98866bb9004c0db402be7f1d8e8acd5d5365bffae1259d3d347f233bebc348e9a52ac4aebaa165eac0269015fc622

 

涉及的方法:

getPrivateKey:

/**
 * 得到私钥对象
 *
 * @param key 密钥字符串(经过16进制编码)
 * @throws Exception
 */
public static PrivateKey getPrivateKey(String key) {
    try {
        byte[] keyBytes = hex2Byte(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    } catch (Exception e) {
        String info = "getPrivateKey failed: " + key + " | " + e.getMessage();
        return null;
    }
}

hex2Byte:

/**
 * 将16进制字符转换成byte[]数组。与byte2Hex功能相反。
 *
 * @param string 16进制字符串
 * @return byte[]数组
 */
public static byte[] hex2Byte(String string) {
    if (string == null || string.length() < 1) {
        return null;
    }
    // 因为一个byte生成两个字符,长度对应1:2,所以byte[]数组长度是字符串长度一半
    byte[] bytes = new byte[string.length() / 2];
    // 遍历byte[]数组,遍历次数是字符串长度一半
    for (int i = 0; i < string.length() / 2; i++) {
        // 截取没两个字符的前一个,将其转为int数值
        int high = Integer.parseInt(string.substring(i * 2, i * 2 + 1), 16);
        // 截取没两个字符的后一个,将其转为int数值
        int low = Integer.parseInt(string.substring(i * 2 + 1, i * 2 + 2), 16);
        // 高位字符对应的int值*16+低位的int值,强转成byte数值即可
        // 如dd,高位13*16+低位13=221(强转成byte二进制11011101,对应十进制-35)
        bytes[i] = (byte) (high * 16 + low);
    }
    return bytes;
}

sign:

/**
 * 使用SHA1withRSA签名算法产生签名
 *
 * @param privateKey privateKey 签名时使用的私钥(16进制编码)
 * @param src        src 签名的原字符串
 * @return String 签名的返回结果(16进制编码)。当产生签名出错的时候,返回null。
 */
public static String sign(PrivateKey privateKey, String src, String encode) {
    try {
        Signature sigEng = Signature.getInstance(SIGNATURE_ALGORITHM);
        sigEng.initSign(privateKey);
        sigEng.update(src.getBytes(encode));
        byte[] signature = sigEng.sign();
        return byte2Hex(signature);
    } catch (Exception e) {
        return null;
    }
}

4、使用16进制公钥验证

操作:传入的签名,公钥都是 16进制格式

代码:

//16进制公钥
String pub = "30819f300d06092a864886f70d010101050003818d0030818902818100c8d3e16602ef1168e424707474ac78eb00a99295d8ab2b8e9e78cb2b1b6bae936d527d022d568a80ac3fb5819024a731b1027dbd637c9977ee49b69a830cae1aca5cd9ab2a13b990428b299419760fbfc15ba0172cd187110e2016c443a9887b259579ee33920f91f4623282df661a1ac0841aaa3b59596809f9fe2178dec78b0203010001";
//原数据
String data = "123456";
System.err.println("代签名数据:" + data);
//签名16进制
String sign = "885d59e3ff349d7fb03903e2304556ceadfea1bf38c972575d20489e69e4b178bc7076db216a9150e7beac7b263eb967fe9129c6c1d70e127d379d0fe048531e0083fb3cd7e8415f68c91f7f1756c0e50dc98866bb9004c0db402be7f1d8e8acd5d5365bffae1259d3d347f233bebc348e9a52ac4aebaa165eac0269015fc622";
//验证
verify(getPublicKey(pub), sign, data, "utf-8");

结果:
代签名数据:123456
验证结果:=====true=====

涉及的方法:

 1、getPublicKey:
/**
 * 获取公钥
 *
 * @param publicKey 公钥字符串
 * @return
 */
public static PublicKey getPublicKey(String publicKey) throws Exception {
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    byte[] keyBytes = hex2Byte(publicKey);
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    return keyFactory.generatePublic(keySpec);
}
2、verify
/**
 * 使用SHA1withRSA签名算法验证签名
 *
 * @param publicKey pubKey 验证签名时使用的公钥(16进制编码)
 * @param sign      sign 签名结果(16进制编码)
 * @param src       src 签名的原字符串
 */
public static void verify(PublicKey publicKey, String sign, String src, String encode) throws Exception {
    try {
        if (StringUtils.isEmpty(sign) || StringUtils.isEmpty(src)) {
            throw new RuntimeException("sign或内容不容为空");
        }
        Signature sigEng = Signature.getInstance("SHA1withRSA");
        sigEng.initVerify(publicKey);
        sigEng.update(src.getBytes(encode));
        byte[] sign1 = hex2Byte(sign);

        boolean aaa = sigEng.verify(sign1);
        System.out.println("验证结果:=====" + aaa + "=====");
        if (!aaa) {
            throw new Exception("验签失败");
        }
    } catch (Exception e) {
        throw new Exception("验签失败");
    }
}

以下部分全部放在代码中,在main中查找

 

全部代码 

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

@Slf4j
public class RSAUtil {

    /**
     * 数字签名,密钥算法
     */
    private static final String RSA_KEY_ALGORITHM = "RSA";
    /**
     * 数字签名签名/验证算法
     */
    private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
    /**
     * RSA密钥长度,RSA算法的默认密钥长度是1024密钥长度必须是64的倍数,在512到65536位之间
     */
    private static final int KEY_SIZE = 1024;

    /** */
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /** */
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;


    /**
     * @param bytes,输入byte[]数组
     * @return 16进制字符
     * @Description: 将byte[]数组转换成16进制字符。一个byte生成两个字符,长度对应1:2
     * @Author: mastermind
     * @Date: 2020-04-06 12:16
     */
    public static String byte2Hex(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        // 遍历byte[]数组,将每个byte数字转换成16进制字符,再拼接起来成字符串
        for (int i = 0; i < bytes.length; i++) {
            // 每个byte转换成16进制字符时,bytes[i] & 0xff如果高位是0,输出将会去掉,所以+0x100(在更高位加1),再截取后两位字符
            builder.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }
        return builder.toString();
    }

    /**
     * 将16进制字符转换成byte[]数组。与byte2Hex功能相反。
     *
     * @param string 16进制字符串
     * @return byte[]数组
     */
    public static byte[] hex2Byte(String string) {
        if (string == null || string.length() < 1) {
            return null;
        }
        // 因为一个byte生成两个字符,长度对应1:2,所以byte[]数组长度是字符串长度一半
        byte[] bytes = new byte[string.length() / 2];
        // 遍历byte[]数组,遍历次数是字符串长度一半
        for (int i = 0; i < string.length() / 2; i++) {
            // 截取没两个字符的前一个,将其转为int数值
            int high = Integer.parseInt(string.substring(i * 2, i * 2 + 1), 16);
            // 截取没两个字符的后一个,将其转为int数值
            int low = Integer.parseInt(string.substring(i * 2 + 1, i * 2 + 2), 16);
            // 高位字符对应的int值*16+低位的int值,强转成byte数值即可
            // 如dd,高位13*16+低位13=221(强转成byte二进制11011101,对应十进制-35)
            bytes[i] = (byte) (high * 16 + low);
        }
        return bytes;
    }

    /**
     * 使用SHA1withRSA签名算法产生签名
     *
     * @param privateKey privateKey 签名时使用的私钥(16进制编码)
     * @param src        src 签名的原字符串
     * @return String 签名的返回结果(16进制编码)。当产生签名出错的时候,返回null。
     */
    public static String sign(PrivateKey privateKey, String src, String encode) {
        try {
            Signature sigEng = Signature.getInstance(SIGNATURE_ALGORITHM);
            sigEng.initSign(privateKey);
            sigEng.update(src.getBytes(encode));
            byte[] signature = sigEng.sign();
            return byte2Hex(signature);
        } catch (Exception e) {
            String info = "sign failed: " + src + " | " + e.getMessage();
            return null;
        }
    }

    /**
     * 本方法使用SHA1withRSA签名算法验证签名
     *
     * @param publicKey pubKey 验证签名时使用的公钥(16进制编码)
     * @param sign      sign 签名结果(16进制编码)
     * @param src       src 签名的原字符串
     */
    public static void verify(PublicKey publicKey, String sign, String src, String encode) throws Exception {
        try {
            if (StringUtils.isEmpty(sign) || StringUtils.isEmpty(src)) {
                throw new RuntimeException("sign或内容不容为空");
            }
            Signature sigEng = Signature.getInstance("SHA1withRSA");
            sigEng.initVerify(publicKey);
            sigEng.update(src.getBytes(encode));
            byte[] sign1 = hex2Byte(sign);

            boolean aaa = sigEng.verify(sign1);
            System.out.println("验证结果:=====" + aaa + "=====");
            if (!aaa) {
                throw new Exception("验签失败");
            }
        } catch (Exception e) {
            throw new Exception("验签失败");
        }
    }

    /**
     * 1024位RSA公私钥对。
     *
     * @return 私钥、公钥
     */
    public static String[] genRSAKeyPair() {
        KeyPairGenerator rsaKeyGen = null;
        KeyPair rsaKeyPair = null;
        try {
            log.error("Generating a pair of RSA key ... ");
            rsaKeyGen = KeyPairGenerator.getInstance("RSA");
            SecureRandom random = new SecureRandom();
            random.setSeed(("" + System.currentTimeMillis() * Math.random() * Math.random()).getBytes(Charset
                    .forName("UTF-8")));
            rsaKeyGen.initialize(1024, random);
            rsaKeyPair = rsaKeyGen.genKeyPair();
            PublicKey rsaPublic = rsaKeyPair.getPublic();
            PrivateKey rsaPrivate = rsaKeyPair.getPrivate();

            String privateAndPublic[] = new String[2];
            privateAndPublic[0] = byte2Hex(rsaPrivate.getEncoded());
            privateAndPublic[1] = byte2Hex(rsaPublic.getEncoded());
            System.err.println("16私钥:" + privateAndPublic[0]);
            System.err.println("16公钥:" + privateAndPublic[1]);
            return privateAndPublic;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 得到私钥对象
     *
     * @param key 密钥字符串(经过16进制编码)
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String key) {
        try {
            byte[] keyBytes = hex2Byte(key);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(keySpec);
        } catch (Exception e) {
            String info = "getPrivateKey failed: " + key + " | " + e.getMessage();
            return null;
        }
    }

    /**
     * 获取公钥
     *
     * @param publicKey 公钥字符串
     * @return
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] keyBytes = hex2Byte(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        return keyFactory.generatePublic(keySpec);
    }

    /** */
    /**
     * <p>
     * 私钥加密
     * </p>
     *
     * @param str        源数据
     * @param privateKey 私钥(16 进制)
     * @return 16进制加密数据
     * @throws Exception
     */
    public static String encryptByPrivateKey(String str, String privateKey) {

        try {
            byte[] keyBytes = hex2Byte(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateK = keyFactory.generatePrivate(keySpec);

            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateK);
            byte[] data = str.getBytes("utf-8");
            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();
            //转16进制
            String s = byte2Hex(encryptedData);
            return s;
        } catch (Exception e) {
            throw new RuntimeException("私钥加密错误");
        }
    }


    /** */
    /**
     * <p>
     * 公钥解密
     * </p>
     *
     * @param str       已加密数据(16进制)
     * @param publicKey 公钥(16进制)
     * @return 原数据
     * @throws Exception
     */
    public static String decryptByPublicKey(String str, String publicKey) {

        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] keyBytes = hex2Byte(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            PublicKey publicK = keyFactory.generatePublic(keySpec);
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicK);
            //16进制数据转byte[]
            byte[] encryptedData = hex2Byte(str);
            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 new String(decryptedData);
        } catch (Exception e) {
            throw new RuntimeException("公钥解密错误");
        }
    }



    public static void main(String[] args) {
        //生成1024位16进制密钥
//        genRSAKeyPair();



//        私钥
        String privateKeyString = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMjT4WYC7xFo5CRw\n" +
                "dHSseOsAqZKV2Ksrjp54yysba66TbVJ9Ai1WioCsP7WBkCSnMbECfb1jfJl37km2\n" +
                "moMMrhrKXNmrKhO5kEKLKZQZdg+/wVugFyzRhxEOIBbEQ6mIeyWVee4zkg+R9GIy\n" +
                "gt9mGhrAhBqqO1lZaAn5/iF43seLAgMBAAECgYAWRlH4w5iKoMy1MffovPyIbEFi\n" +
                "rdYjXihqcVFvjZILAfUdMhpctv2Tugcy9ZTsS9MaJAGYUQGP8Bpw+Jz4rh5dTebx\n" +
                "c8cqZ9NhI9h0gceGYJPyvtw7KdUnFRkYnlcj3vOwR9x793nJl1Yo0APCYl4jk7he\n" +
                "sm4YcCGY52uF7dQGuQJBAPQpRp5VJYuLXzsNNVkxIb27gpfTJVaYZoto2FqlpYhV\n" +
                "USRKGuTP+/5BZjJOBTRMaJvDqy15Ev/PrIm+8+5mvxUCQQDSkLazWyzVPfFAWO7I\n" +
                "3ICv/REtNdXkFQ6FYtYLzgusxFaNr75RsJsgeXfSQxD9RmPb2ipKeY3ertU25ZIl\n" +
                "gBQfAkBURKat4N9LcTfV7rIZ7X4iuMPS2LoLUCAcP3xklMUz75ZIuxbbH/luAG5g\n" +
                "MFNVgIWeNQMwd5gaGDgJdpFEF8wdAkAYkOWf2z1Jy6Y/2aBSMteYsK+2VJeVupct\n" +
                "HLDYQ7u89lMayKwtn6sZiNJf548t3W59EeDpO3E/z6n0c6gvU9gFAkBRxq0RXi/2\n" +
                "5wpEjeRd+tL30WrC2PoTVN6San5cPkv2k6vVWmZJAAMB6RKHtp+r7yUYLcEcrZOG\n" +
                "7ARIDVY19ou5";

        //公钥
        String publicKeyString = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI0+FmAu8RaOQkcHR0rHjrAKmS\n" +
                "ldirK46eeMsrG2uuk21SfQItVoqArD+1gZAkpzGxAn29Y3yZd+5JtpqDDK4aylzZ\n" +
                "qyoTuZBCiymUGXYPv8FboBcs0YcRDiAWxEOpiHsllXnuM5IPkfRiMoLfZhoawIQa\n" +
                "qjtZWWgJ+f4heN7HiwIDAQAB";

        //私钥16进制
        byte[] bytes1 = Base64.decodeBase64(privateKeyString);
        String pri = byte2Hex(bytes1);

        //私钥16进制
        byte[] ddd = Base64.decodeBase64(publicKeyString);
        String pub = byte2Hex(ddd);

        try {
            //原数据
            String data = "123456";
            System.err.println("代签名数据:" + data);
            //签名
            String sign = sign(getPrivateKey(pri), data, "utf-8");
            System.err.println("私钥16签名:" + sign);
            //验证
            verify(getPublicKey(pub), sign, data, "utf-8");


            //私钥加密 数据转16进制
            String s = encryptByPrivateKey(data, pri);
            System.err.println("私钥加密:" + s);
            //公钥解密
            String s1 = decryptByPublicKey(s, pub);
            System.err.println("公钥解密:" + s1);

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

}

 main运行后结果

代签名数据:123456
私钥16签名:885d59e3ff349d7fb03903e2304556ceadfea1bf38c972575d20489e69e4b178bc7076db216a9150e7beac7b263eb967fe9129c6c1d70e127d379d0fe048531e0083fb3cd7e8415f68c91f7f1756c0e50dc98866bb9004c0db402be7f1d8e8acd5d5365bffae1259d3d347f233bebc348e9a52ac4aebaa165eac0269015fc622
验证结果:=====true=====
私钥加密:41b200f969b3d25be82d13141c4a0f1c1058f8fd122ed3a19e2a5652a6ae8d7f790c422c29633b92166311322fd5b0e4fd06086c1b4e708b4c38513482a95d8b9f66a2f09ca48c0effd164263a2483e589acc24f30473b56cf78d60af9b66fa8701d8f071c4f197930f2c9abd4e360e356cfdd167fa35d2d6dde5bc5650d5f6f
公钥解密:123456 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值