zoukankan      html  css  js  c++  java
  • 使用RSA私钥或pfx私钥签名String

    项目有个需求,使用私钥签名请求body内容,放在请求头部,作为头部一个字段内容请求外部服务,签名有二种方式,对方提供私钥串/直接提供pfx私钥文件。

    一. 提供私钥串  示例代码如下:

    public static void main(String[] args) {
           String key2 = "MII***=="  //使用自己的私钥替换
            try {
                byte[] data = "test".getBytes("UTF8");
                Signature sig = Signature.getInstance("MD5withRSA");//SHA1WithRSA  签名算法
                sig.initSign(readRSAPrivateKey(key2));
                sig.update(data);
                byte[] signatureBytes = sig.sign();
                System.out.println("Signature:" + new BASE64Encoder().encode(signatureBytes));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static String signContent(String content) throws Exception{
            byte[] data = content.getBytes("UTF8");
            Signature sig = Signature.getInstance("MD5withRSA");
            sig.initSign(readRSAPrivateKey(key2));
            sig.update(data);
            byte[] signatureBytes = sig.sign();
            return new String(java.util.Base64.getEncoder().encode(signatureBytes)); //new BASE64Encoder().encode(signatureBytes); 
      }

    public static PrivateKey readRSAPrivateKey(String privateKey) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { byte[] keyBytes = java.util.Base64.getDecoder().decode(privateKey.getBytes());
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); 
    KeyFactory kf
    = KeyFactory.getInstance("RSA");
    PrivateKey key
    = kf.generatePrivate(spec);

    return key; }

    如果需要公钥解码,结合私钥签名,代码如下

    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.Signature;
    
    import sun.misc.BASE64Encoder;
    
    public class MainClass {
        public static void main(String[] args) throws Exception {
    
            KeyPair keyPair = getKeyPair();
    
            byte[] data = "test".getBytes("UTF8");
    
            Signature sig = Signature.getInstance("SHA1WithRSA");
            sig.initSign(keyPair.getPrivate());
            sig.update(data);
            byte[] signatureBytes = sig.sign();
            System.out.println("Signature:" + new BASE64Encoder().encode(signatureBytes));
    
            sig.initVerify(keyPair.getPublic());
            sig.update(data);
    
            System.out.println(sig.verify(signatureBytes));
        }
    
        private static KeyPair getKeyPair() throws NoSuchAlgorithmException {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(1024);
            return kpg.genKeyPair();
        }
    }

    二. 如果别人提供给你的是pfx文件,你可以选择把peivate key提取出来,或者直接使用pfx文件签名也可以。

    1. 提取的命令:openssl pkcs12 -in test-private.pfx -nocerts -nodes -out key2.pem

     如果需要的是老格式的:openssl pkcs8 -in key.pem -out rsakey.pem

    2. 直接使用pfx文件签名String代码如下

    /**
         * @param algorithm  签名算法: SHA1WithRSA / MD5withRSA等
         * @param password 密码
         * @param privateKeyPath pfx文件路径
         * @throws Exception
         */
        public RSASignUtils(String algorithm, String password, String privateKeyPath) throws Exception {
            this.algorithm = algorithm;
            this.password = password;
    
            try{
                KeyStore ks = KeyStore.getInstance("PKCS12");
                InputStream fis = RSASignUtils.class.getResourceAsStream(privateKeyPath);
                char[] nPassword = null;
                if ((password == null) || password.trim().equals("")) {
                    nPassword = null;
                } else {
                    nPassword = password.toCharArray();
                }
                ks.load(fis, nPassword);
                fis.close();
                Enumeration enuml = ks.aliases();
                String keyAlias = null;
                if (enuml.hasMoreElements()) {
                    keyAlias = (String) enuml.nextElement();
                    logger.info("RSASignUtils alias=[" + keyAlias + "]");
                }
                logger.info("RSASignUtils is key entry = " + ks.isKeyEntry(keyAlias));
                PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, nPassword);
                logger.info("RSASignUtils keystore type = " + ks.getType());
                signature = Signature.getInstance(algorithm);
                signature.initSign(prikey);
    
            } catch (Exception e) {
                logger.error(String.format("RSA signature object generate failure...%s", e.getMessage()));
                throw e;
            }
    
        }
    
        public String generate(String body) throws UnsupportedEncodingException, SignatureException {
    
            //Read the string into a buffer
            byte[] dataInBytes = body.getBytes("UTF-8");
    
            //update signature with data to be signed
            signature.update(dataInBytes);
    
                //sign the data
            byte[] signedInfo = signature.sign();
    
            return Base64.getEncoder().encodeToString(signedInfo);//Base64.encode(signedInfo);
        }
    欢迎关注Java流水账公众号
  • 相关阅读:
    TensorflowJS 教程
    理解TCP序列号(Sequence Number)和确认号(Acknowledgment Number)
    Wireshark 过滤 基本语法
    LSTM如何解决梯度消失或爆炸的?
    K-Means ++ 和 kmeans 区别
    LSTM UEBA异常检测——deeplog里其实提到了,就是多分类LSTM算法,结合LSTM预测误差来检测异常参数
    python 多进程练习 调用 os.system命令
    TLS 改变密码标准协议(Change Cipher Spec Protocol) 就是加密传输中每隔一段时间必须改变其加解密参数的协议
    ssl tls 证书链 根证书和叶证书查询
    TLS与SSL之间关系——SSL已经被IEFT组织废弃,你可以简单认为TLS是SSL的加强版
  • 原文地址:https://www.cnblogs.com/guofu-angela/p/10905180.html
Copyright © 2011-2022 走看看