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流水账公众号
  • 相关阅读:
    我的插件架构
    .net 处理图片亮度
    封装自己的对称加密模块
    漏洞无处不在之窃取你的QQ信息
    写自己的自动升级模块
    抓到一只网马,发文顺便鄙视下360
    .net 3.5的Socket异步完成端口
    检测本机是否登录了指定QQ账号
    C++/CLR写的Data Blocks
    修改的Vista风格多功能日历Demo
  • 原文地址:https://www.cnblogs.com/guofu-angela/p/10905180.html
Copyright © 2011-2022 走看看