jsrsasign 前台簽名,Java后台驗證前台簽名


rsa  具體是什么  這個就不在多說。算法實現啊應用啊 已經有很多了。今天記錄下 這種特殊的需求,前台簽名,后台驗證

Java后台產生 密匙對

pom.xml 添加BC 依賴

 <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.51</version>
        </dependency>

RSATools

package com.oscgc.securevideo.server.tool.rsa;

import java.io.IOException;
import java.io.StringWriter;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.util.io.pem.PemObject;

/**
 * Created by Yq on 2015/6/10.
 */
public class RsaKeyTools {
    
    public static final String PEM_PUBLICKEY = "PUBLIC KEY";
    
    public static final String PEM_PRIVATEKEY = "PRIVATE KEY";
    
    /**
     * generateRSAKeyPair
     * 
     * @param keySize
     * @return
     */
    public static KeyPair generateRSAKeyPair(int keySize) {
        KeyPairGenerator generator = null;
        SecureRandom random = new SecureRandom();
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        try {
            generator = KeyPairGenerator.getInstance("RSA", "BC");
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        catch (NoSuchProviderException e) {
            e.printStackTrace();
        }
        
        generator.initialize(keySize, random);
        
        KeyPair keyPair = generator.generateKeyPair();
        
        return keyPair;
    }
    
    /**
     * convertToPemKey
     * 
     * @param publicKey
     * @param privateKey
     * @return
     */
    public static String convertToPemKey(RSAPublicKey publicKey,
                                         RSAPrivateKey privateKey) {
        if (publicKey == null && privateKey == null) {
            return null;
        }
        StringWriter stringWriter = new StringWriter();
        
        try {
            PEMWriter pemWriter = new PEMWriter(stringWriter, "BC");
            
            if (publicKey != null) {
                
                pemWriter.writeObject(new PemObject(PEM_PUBLICKEY,
                                                    publicKey.getEncoded()));
            }
            else {
          //此處產生的privatekey 的格式是 PKCS#8 的格式 pemWriter.writeObject(
new PemObject(PEM_PRIVATEKEY, privateKey.getEncoded())); } pemWriter.flush(); } catch (IOException e) { e.printStackTrace(); } return stringWriter.toString(); } public static byte[] sign(String data, byte[] privateKey) throws Exception { PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initSign(privateKey2); signature.update(data.getBytes()); return signature.sign(); } //后台測試簽名的時候 要和前台保持一致,所以需要將結果轉換 private static String bytes2String(byte[] bytes) { StringBuilder string = new StringBuilder(); for (byte b : bytes) { String hexString = Integer.toHexString(0x00FF & b); string.append(hexString.length() == 1 ? "0" + hexString : hexString); } return string.toString(); } public static boolean verify(String data, byte[] publicKey, byte[] signatureResult) { try { X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec); Signature signature = Signature.getInstance("SHA1WithRSA"); signature.initVerify(publicKey2); signature.update(data.getBytes()); return signature.verify(signatureResult); } catch (Exception e) { e.printStackTrace(); } return false; }
//前台的簽名結果是將byte 中的一些 負數轉換成了正數,
//但是后台驗證的方法需要的又必須是轉換之前的
public static byte[] hexStringToByteArray(String data) { int k = 0; byte[] results = new byte[data.length() / 2]; for (int i = 0; i + 1 < data.length(); i += 2, k++) { results[k] = (byte) (Character.digit(data.charAt(i), 16) << 4); results[k] += (byte) (Character.digit(data.charAt(i + 1), 16)); } return results; } public static void main(String[] args) { String str = "coder"; KeyPair k = generateRSAKeyPair(1024); String publicKey = convertToPemKey((RSAPublicKey) k.getPublic(), null); String privateKey = convertToPemKey(null, (RSAPrivateKey) k.getPrivate()); System.out.println("publicKey__\n" + publicKey); System.out.println("privateKey_\n" + privateKey); try { byte[] signautreResult = sign(str, k.getPrivate().getEncoded()); String signatureStr = bytes2String(signautreResult); byte[] signatureResult2 = hexStringToByteArray(signatureStr); boolean b = verify(str, k.getPublic().getEncoded(), signatureResult2); System.out.print("iii " + b); } catch (Exception e) { e.printStackTrace(); } } }

 

 

 

 

 

Javascript    簽名用到的lib 是 jsrsasign  包含:

    更多的詳細  github 地址:https://kjur.github.io/jsrsasign/

   在官網給定的簽名例子代碼如下:

function doSign() {
  var rsa = new RSAKey();
  rsa.readPrivateKeyFromPEMString(document.form1.prvkey1.value);
  var hashAlg = document.form1.hashalg.value;
  var hSig = rsa.signString(document.form1.msgsigned.value, hashAlg);
  document.form1.siggenerated.value = linebrk(hSig, 64);
}

這里我們需要改動一下:

 rsa.readPrivateKeyFromPEMString(document.form1.prvkey1.value);

官方api 中對這個方法有這樣的說明:
readPrivateKeyFromPEMString(keyPEM)
read PKCS#1 private key from a string 

這個方法傳入的privatekey 是需要 PKCS#1 格式的,但是后台 產生出來的private key 是PKCS#8的格式的,這里就不能用這個方法,簽名會通不過。

查看jsrsasign 的 api 

KEYUTIL - loading RSA/EC/DSA private/public key from PEM formatted PKCS#1/5/8 and X.509 certificate

因此 js  生成RSAkey  對象

 rsa=KEYUTIL.getKey(document.form1.prvkey1.value);

 

這個方法支持PKCS#8 pem 格式的privatekey  可以通過簽名。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM