JAVA RSA非对称加密 XMLSignature/X509Certificate
2013-05-17 23:46
274 查看
仅供参考。
私钥自己持有用来加密,公钥用来解密,报文包含的主要几部分是:未加密数据、公钥、签名、摘要
报文:
MPIRES内容是传输数据,ID对应下面REFERENCE中的URI
DIGESTVALUE的值是摘要,是由指定METHOD得到的数据的哈希值
SIGNATUREVALUE是签名值,是由私钥将数据加密得到的值
X509CERTIFICATE里面一大串字符是公钥,用来解密
验签的步骤:
1:验公钥是否由根证书发行,如果数据、摘要被修改,公钥被修改->野鸡公钥,这一步通不过
2:验摘要,取数据的哈希值跟摘要比较,如果仅仅数据被修改,这一步通不过
3:验签名,用公钥给签名解密,结果与摘要(是否再次哈希数据?)比较,如果数据和摘要被修改,这一步通不过
验签JAVA代码:参数为如上XML类型
生成签名:参数是证书、私钥、需要签名的XML格式数据,返回XML文件如上
这里X509DATA里面添加了5个节点,对应XML文件的五个节点
OK
---------------------------------------------------------------------------从前的理解-仅供参考--------------------------------------------------------------------------------------------------------------
(用来保证传输数据没有被修改,在我们项目里面,从商户网站确认支付转入我们这边的支付网关时、支付扣款完成返回支付成功或者失败状态到商户网站时,用到了密钥加密。其他地方都没有。因为,支付金额被篡改、支付结果被篡改都是绝对不允许的。
非对称密钥基本特点,有一个加密密钥称公钥,一个解密密钥称私钥,成对出现。公钥仅仅用来加密,私钥仅仅用来解密。
比如用户登录网站,输入卡号密码,提交以后服务器返回卡内余额,如果用这种加密方法流程就可能是这样的:
用户登录网站时访问服务器,服务器生成一对密钥A,把公钥A发送给客户端;
登录完成后客户端本地生成一对密钥B;
提交卡号密码时,用公钥A把数据加密,同时传到服务器的还有公钥B;
服务器接收到数据后,用私钥A把卡号密码解密,查出余额,用公钥B加密,传给客户端;
客户端用私钥B解密余额;
OK。
整个过程中,只传输公钥。
这是我理解的一点点,打个比方,解释非对称原理,实际中不知道有没有这么玩。也不知道有没有客户端生成密钥这回事。
签名:
其实密钥不会对数据加密。
服务器接收到的数据有三部分,一是实体数据,这是加密不加密都无所谓,可以为明文;二是公钥;三是签名;
这里的签名是一段加密过的密文,就是由私钥把实体数据进行加密的结果。
服务器端的步骤是:先验证公钥,然后将签名解密,然后比较实体数据和解密后的结果。
JAVA代码以后看看再贴了。)
私钥自己持有用来加密,公钥用来解密,报文包含的主要几部分是:未加密数据、公钥、签名、摘要
报文:
<?xml version="1.0" encoding="UTF-8"?><PGGATE><Message id="A20130521113348"> <MPIRes id="S20130521113348"> <RespCode>0000</RespCode> </MPIRes> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" xmlns="http://www.w3.org/2000/09/xmldsig#"/> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns="http://www.w3.org/2000/09/xmldsig#"/> <Reference URI="#S20130521113348" xmlns="http://www.w3.org/2000/09/xmldsig#"> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns="http://www.w3.org/2000/09/xmldsig#"/> <DigestValue xmlns="http://www.w3.org/2000/09/xmldsig#">wj2BDi23oLeVtmG/uZg4n49aKdk=</DigestValue> </Reference> </SignedInfo> <SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#"> DVrRdcY7fZRCCPUtSjiOJBaMEJRualXZyuSzzcavYyyOXCnBZhd7w3XLvw66fJSvaHC1GHOECpTF hRETWlp47bxvYUYIwA+jaltXb0BgkQiwkFYO8U0YEYPfVESG9lKL7cLWbz122OaxJSQkn5ZEf+Dn Cp8kMGVR2BnW1ZC7VIE= </SignatureValue> <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> <X509Data xmlns="http://www.w3.org/2000/09/xmldsig#"> <X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#"> MIIDxjCCAy+gAwIBAgIQICPnBGbBhVL4rB50L9wn4zANBgkqhkiG9w0BAQUFADAkMQswCQYDVQQG EwJDTjEVMBMGA1UEChMMQ0ZDQSBURVNUIENBMB4XDTA2MDYxMjA4MTEyNVoXDTA4MDYxMjAyNTIy MVowgbIxCzAJBgNVBAYTAkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0ExETAPBgNVBAsTCExvY2Fs IFJBMRQwEgYDVQQLEwtlbnRlcnByaXNlczFjMGEGA1UEAx5aADAANAAxAEAAOAA5ADkAMAAxADkA OQAwADEAOQA5ADAAMQAxAEAAMAA0ADAANgAyADQAMQAwADoAQQBQAEkAIABTAEkARwBOAEAAMAAw ADAAMAAwADAAMAAxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+jdc6rFyssSyXlu6AqzYX x6/GkbZWSjGwd1fOy6z627fKxb5RdUPdra683+cE11iKJKn8C/UZ8DLHCijLSeryy9JskXIAPWZr ccj42ig0r+1usIYZG21DKi5Q6Cx+tuxzjLcmyMiMkVYEhYedMKD/nWSETgsQYut+EZjOFvcZkwID AQABo4IBaDCCAWQwHwYDVR0jBBgwFoAURnLcJXKfAk5Vg7WA+Qvb6ZOz9EUwHQYDVR0OBBYEFAdj vrCDQvhIBeO0M+g1KvYZbJTdMA4GA1UdDwEB/wQEAwIEsDAeBgNVHREEFzAVgRNEYWlfYW1pQGhv dG1haWwuY29tMAwGA1UdEwQFMAMBAQAwgeMGA1UdHwSB2zCB2DBNoEugSaRHMEUxCzAJBgNVBAYT AkNOMRUwEwYDVQQKEwxDRkNBIFRFU1QgQ0ExDDAKBgNVBAsTA0NSTDERMA8GA1UEAxMIY3JsMTMy XzIwgYaggYOggYCGfmxkYXA6Ly8yMTAuNzQuNDEuODc6Mzg5L0NOPWNybDEzMl8yLE9VPUNSTCxP PUNGQ0EgVEVTVCBDQSxDPUNOP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3Rj bGFzcz1jUkxEaXN0cmlidXRpb25Qb2ludDANBgkqhkiG9w0BAQUFAAOBgQB4RknyLopJ+RXWkITL fiDmSIIW+JQX7MZKM/TtdoT45XdYc3ngAY3qRzM10xa0JU5GjwrOm9JzBU7NYVtzvc8AVOpoHh/X I7Ocl03k6k07ZJZBgcgpzpayW6cjlyE+r62PenXAtNqkVtx5sW+TGNSpfzb284ldM2ezoBdZqhNu mA== </X509Certificate> <X509SubjectName xmlns="http://www.w3.org/2000/09/xmldsig#">CN=041@89901990199011@04062410:API SIGN@00000001,OU=enterprises,OU=Local RA,O=CFCA TEST CA,C=CN</X509SubjectName> <X509CRL xmlns="http://www.w3.org/2000/09/xmldsig#"> UzIwMTMwNTIxMTEzMzQ4 </X509CRL> <X509SKI xmlns="http://www.w3.org/2000/09/xmldsig#"> B2O+sINC+EgF47Qz6DUq9hlslN0= </X509SKI> <X509IssuerSerial xmlns="http://www.w3.org/2000/09/xmldsig#"> <X509IssuerName xmlns="http://www.w3.org/2000/09/xmldsig#">O=CFCA TEST CA,C=CN</X509IssuerName> <X509SerialNumber xmlns="http://www.w3.org/2000/09/xmldsig#">42721711840498543783102462139127572451</X509SerialNumber> </X509IssuerSerial> </X509Data> </KeyInfo> </Signature></Message></PGGATE>
MPIRES内容是传输数据,ID对应下面REFERENCE中的URI
DIGESTVALUE的值是摘要,是由指定METHOD得到的数据的哈希值
SIGNATUREVALUE是签名值,是由私钥将数据加密得到的值
X509CERTIFICATE里面一大串字符是公钥,用来解密
验签的步骤:
1:验公钥是否由根证书发行,如果数据、摘要被修改,公钥被修改->野鸡公钥,这一步通不过
2:验摘要,取数据的哈希值跟摘要比较,如果仅仅数据被修改,这一步通不过
3:验签名,用公钥给签名解密,结果与摘要(是否再次哈希数据?)比较,如果数据和摘要被修改,这一步通不过
验签JAVA代码:参数为如上XML类型
public boolean checkXmlSignature(Document inputDoc) throws Exception { try { if (inputDoc == null) { return false; } coverCert(inputDoc); XmlConv xmlConv = new XmlConv(); String str = new String(xmlConv.converDocByte(inputDoc),"utf-8"); Element signatureElement = (Element) inputDoc .getElementsByTagNameNS(Constants.SignatureSpecNS, Constants._TAG_SIGNATURE).item(0); XMLSignature sig = new XMLSignature(signatureElement, XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1); //用根证书的公钥验证公钥 X509Certificate certificate = sig.getKeyInfo().getX509Certificate(); String strCA = "-----BEGIN CERTIFICATE-----" + "\n" + "MIIDezCCAmOgAwIBAgIJAMx6VPEfkqaLMA0GCSqGSIb3DQEBBAUAMHQxFjAUBgNV" + "\n" + "BAoTDUFjY29yU2VydmljZXMxFDASBgNVBAsTC1N5c3RlbUFkbWluMRgwFgYDVQQD" + "\n" + "Ew9BY2NvclNlcnZpY2VzQ0ExKjAoBgkqhkiG9w0BCQEWG2NvbGluLmJhaUBhY2Nv" + "\n" + "cnNlcnZpY2VzLmNvbTAeFw0xMDA1MjQxNjM0MjZaFw0xNjA1MjIxNjM0MjZaMHQx" + "\n" + "FjAUBgNVBAoTDUFjY29yU2VydmljZXMxFDASBgNVBAsTC1N5c3RlbUFkbWluMRgw" + "\n" + "FgYDVQQDEw9BY2NvclNlcnZpY2VzQ0ExKjAoBgkqhkiG9w0BCQEWG2NvbGluLmJh" + "\n" + "ggEBAJqZOQmf1P6iocEOsTRyWfaX9ZlJXS5+3Z0Cu1IhwqUM2WDB1fpR9FVAbs5j" + "\n" + "JAn3vjfvDjqdttRTLavGV79EmDctUHoK2W2XkAWMa7Hg9x7leXNRLZ4nFMP8hI5v" + "\n" + "4CxzUJl7gMgpsmCsv4oo9d38UmU2O2MvZ5Q5LOwGTbNTdZQ4SHNKcc3wumlMI90h" + "\n" + "mhhCRzDjF3dYeapr28oy/7uHPaWK+eNQwioBXJMmbn1RFMEa8PeXcG2PYEHSDHHi" + "\n" + "BtSSS0pLtMOXq+hmUliHxZymGObY13Fx1KfqLbbn6A4gKCnp8T97Kb7jvtBY8nR4" + "\n" + "8M58/uB8Ej1J2m7CTZiIEolbD9kCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq" + "\n" + "hkiG9w0BAQQFAAOCAQEAig1mlEYTpRDs+H5UPLd4KQDZBEy2xS9diePAihgne9/4" + "\n" + "qvXnolq6vD4kvnObdb1ne48ZlLlps7ikDfC1Ylv2DvUmGhJDCG76ffvgapo2Z83p" + "\n" + "msTQY06ZxJqxpfhYclu7IFNWgFPAv49jInIpDdZa0svwDPy0PILXj975pH6pPBat" + "\n" + "83rzNts7NO0D/MI8rLF0MA6Fspz62lR+uqFeHMJfuy3C45DhzZ5ppQIwEvwbgdnE" + "\n" + "HoERDxu8i//SbtRPVsbX82X4E5Sv7YEeFj3diYfn1ig3ix6RwATpboSTlQzH9BcI" + "\n" + "rtCpKZ5xnjj+3BaNl9rmaP37hpeNVBJE9BPe2dBaPw==" + "\n" + "-----END CERTIFICATE-----" + "\n"; X509Certificate RTPubCA = cvt2Cert(strCA); certificate.verify(RTPubCA.getPublicKey()); //验签名 if (!sig.checkSignatureValue(certificate)) { return false; } } catch (XMLSecurityException xsex) { throw new Exception(xsex); } catch (Exception ex) { throw new Exception(ex); } return true; } public static X509Certificate cvt2Cert(String certInfo)throws Exception{ try{ CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream in = new ByteArrayInputStream(certInfo.getBytes()); X509Certificate c = (X509Certificate)cf.generateCertificate(in); return c; }catch(Exception ex){ throw ex; } }-------------------------------------------------------------------------------------------验签结束--------------------------------------------------------------------------------------------------------------
生成签名:参数是证书、私钥、需要签名的XML格式数据,返回XML文件如上
public Node doCreateXmlSignature(Document inputDoc, String sigidString, PrivateKey privateKey, X509Certificate certInfo) throws PGException { Node outNode; try { if(inputDoc == null) { return inputDoc; } if(sigidString == null || privateKey == null || certInfo == null) { return null; } XMLSignature sig = new XMLSignature(inputDoc, null, XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1); XMLSignature.setDefaultPrefix(sig.getBaseNamespace(), servercommon.Constants.BLANK); sig.setFollowNestedManifests(false); sig.addDocument("#" + sigidString, null, Constants.ALGO_ID_DIGEST_SHA1, null, null); /* sig.addDocument("#" + sigidString, null, Constants.ALGO_ID_DIGEST_SHA1, null, null);*/ // sig.addDocument("#" + sigidString, (Transforms) null, // Constants.ALGO_ID_DIGEST_SHA1, null, // "http://www.w3.org/2000/09/xmldsig#Object"); XMLX509SubjectName subjectName = new XMLX509SubjectName(inputDoc, certInfo); X509Data x509Data = new X509Data(inputDoc); XMLX509Certificate xmlCert = new XMLX509Certificate(x509Data .getDocument(), certInfo); XMLX509CRL xmlCrl = new XMLX509CRL(inputDoc, sigidString .getBytes(server.common.Constants.XML_ENCODE_UTF8)); XMLX509SKI xmlKI = new XMLX509SKI(inputDoc, certInfo); XMLX509IssuerSerial xmlIssuerSerial = new XMLX509IssuerSerial( inputDoc, certInfo); x509Data.add(xmlCert); x509Data.add(subjectName); x509Data.add(xmlCrl); x509Data.add(xmlKI); x509Data.add(xmlIssuerSerial); sig.getKeyInfo().add(x509Data); sig.sign(privateKey); Element rootCup = inputDoc.getDocumentElement(); rootCup.getFirstChild().appendChild(sig.getElement()); outNode = inputDoc; } catch (XMLSecurityException xsex) { xsex.printStackTrace(); throw new PGException(Module.SYSTEM_MODULE, Rescode.XML_SIGNATURE_ERROR, xsex); } catch (UnsupportedEncodingException ueex) { throw new PGException(Module.SYSTEM_MODULE, Rescode.TOUTF8_ERROR, ueex); } catch (Exception ex) { ex.printStackTrace(); throw new PGException(Module.DEFAULT_MODULE, Rescode.DEFAULT_RESCODE, ex); } return outNode; }
这里X509DATA里面添加了5个节点,对应XML文件的五个节点
OK
---------------------------------------------------------------------------从前的理解-仅供参考--------------------------------------------------------------------------------------------------------------
(用来保证传输数据没有被修改,在我们项目里面,从商户网站确认支付转入我们这边的支付网关时、支付扣款完成返回支付成功或者失败状态到商户网站时,用到了密钥加密。其他地方都没有。因为,支付金额被篡改、支付结果被篡改都是绝对不允许的。
非对称密钥基本特点,有一个加密密钥称公钥,一个解密密钥称私钥,成对出现。公钥仅仅用来加密,私钥仅仅用来解密。
比如用户登录网站,输入卡号密码,提交以后服务器返回卡内余额,如果用这种加密方法流程就可能是这样的:
用户登录网站时访问服务器,服务器生成一对密钥A,把公钥A发送给客户端;
登录完成后客户端本地生成一对密钥B;
提交卡号密码时,用公钥A把数据加密,同时传到服务器的还有公钥B;
服务器接收到数据后,用私钥A把卡号密码解密,查出余额,用公钥B加密,传给客户端;
客户端用私钥B解密余额;
OK。
整个过程中,只传输公钥。
这是我理解的一点点,打个比方,解释非对称原理,实际中不知道有没有这么玩。也不知道有没有客户端生成密钥这回事。
签名:
其实密钥不会对数据加密。
服务器接收到的数据有三部分,一是实体数据,这是加密不加密都无所谓,可以为明文;二是公钥;三是签名;
这里的签名是一段加密过的密文,就是由私钥把实体数据进行加密的结果。
服务器端的步骤是:先验证公钥,然后将签名解密,然后比较实体数据和解密后的结果。
JAVA代码以后看看再贴了。)
相关文章推荐
- java实现RSA非对称加密算法 对数据进行加密【附代码】
- Java加密技术(四)非对称加密算法RSA
- Java对称与非对称加密解密,AES与RSA
- java非对称加密的源代码(RSA)
- java安全(二)非对称加密RSA
- RSA非对称加密,使用OpenSSL生成证书,iOS加密,java解密
- java对称加为密DESede 与 非对称加密RSA 示例
- 使用RSA非对称加密完成JavaScript前端分段加密和java后端分段解密
- OpenSSL生成证书进行iOS加密,java解密的RSA非对称加密 详解
- java非对称加密的源代码(RSA)
- 基于公私钥文件的RSA非对称加密的Java端实现
- java非对称加密的源代码(RSA)
- java非对称加密RSA的工具类及其源代码
- Java非对称加密的源代码(RSA)
- RSA非对称加密Java实现
- Java对称与非对称加密解密,AES与RSA
- Java对称与非对称加密解密,AES与RSA
- java RSA非对称加密详解
- RSA非对称加密 java后台不能解析安卓生成的密文