jsrsasign 前台签名,Java后台验证前台签名
2015-06-17 14:04
239 查看
rsa 具体是什么 这个就不在多说。算法实现啊应用啊 已经有很多了。今天记录下 这种特殊的需求,前台签名,后台验证
Java后台产生 密匙对
pom.xml 添加BC 依赖
RSATools
Javascript 签名用到的lib 是 jsrsasign 包含:
Signature - RSA/RSAPSS/ECDSA/DSA digital signtature class wrapper of Java JCE style
MessageDigest - cryptographic hash calculation class wrapper of Java JCE style
MAC - message authentication code hash calculation class wrapper of Java JCE style
ASN.1 encoder/generator
ASN.1 structure for X.509 ceritificate, CRL and CSR(PKCS#10) generation
ASN.1 structure for CMS SignedData generation
ASN.1 structure for RFC 3161 TimeStamp generation
ASN.1 structure for RFC 5126 CAdES Long Term Signature generation
simple ASN.1 data parser
simple X.509 certificate parser/reader
KEYUTIL - loading RSA/EC/DSA private/public key from PEM formatted PKCS#1/5/8 and X.509 certificate
JSON Web Siguature(JWS), JSON Web Token(JWT) and JSON Web Key(JWK)
更多的详细 github 地址:https://kjur.github.io/jsrsasign/
在官网给定的签名例子代码如下:
这里我们需要改动一下:
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 对象
这个方法支持PKCS#8 pem 格式的privatekey 可以通过签名。
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 包含:
Signature - RSA/RSAPSS/ECDSA/DSA digital signtature class wrapper of Java JCE style
MessageDigest - cryptographic hash calculation class wrapper of Java JCE style
MAC - message authentication code hash calculation class wrapper of Java JCE style
ASN.1 encoder/generator
ASN.1 structure for X.509 ceritificate, CRL and CSR(PKCS#10) generation
ASN.1 structure for CMS SignedData generation
ASN.1 structure for RFC 3161 TimeStamp generation
ASN.1 structure for RFC 5126 CAdES Long Term Signature generation
simple ASN.1 data parser
simple X.509 certificate parser/reader
KEYUTIL - loading RSA/EC/DSA private/public key from PEM formatted PKCS#1/5/8 and X.509 certificate
JSON Web Siguature(JWS), JSON Web Token(JWT) and JSON Web Key(JWK)
更多的详细 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 可以通过签名。
相关文章推荐
- Java: 在dos窗口输入密码,不要把密码直接显示出来,原来可以这么简单
- spring定时器quartz
- JavaWeb学习总结第五篇--认识Cookie机制
- eclipse打开选中文件(文件夹,包)的当前目录
- 解决Myeclipse/eclipse控制台输出乱码的问题
- Java: String.split(....); 结果很意外
- 路径或文件名中含有中文的jar文件双击启动不了 -> Java7的Bug?
- 解决Java Web项目中文乱码的方法
- 中科院NLPIR中文分词java版
- java注释
- code::Blocks生成的dll 在 java jni 调用遇到的问题
- 随笔:spring+quartz定时任务(1)
- 由于对必需的库\jdk1.7.0\jre\lib\rt.jar 具有一定的访问限制问题 解决方法
- Hashtable 删除元素, 抛出异常 java.util.ConcurrentModificationException
- 三大框架(SSH)关于URL转发乱码问题(最简单暴力的一种解决办法)
- Spring+MyBatis多数据源配置实现
- Spring+MyBatis多数据源配置实现
- maven环境搭建、Eclipse安装
- Java生成和操作Excel文件
- mybatis+springmvc缓存设置