精华内容
下载资源
问答
  • java实现数字签名

    2009-08-05 15:11:33
    电子政务是依赖于计算机和网络技术而...由于Java在网络编程中的适用性,以及Java的安全系统结构日益完善和目前Java开发网络安全软件的便利性,因此在电子政务系统中用Java来实现数字签名会具有更好的安全性和现实意义。
  • 另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥RSA本文主要介绍如何基于java、php、c#在客户端使用rsa签名,然后在服务端使用Java验签。基于openssl生成RSA公私钥对a)从网上下载...

    在开放平台领域,需要给isv提供sdk,签名是Sdk中需要提供的功能之一。由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版 本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥RSA

    本文主要介绍如何基于java、php、c#在客户端使用rsa签名,然后在服务端使用Java验签。

    基于openssl生成RSA公私钥对a)从网上下载openssl工具:http://www.slproweb.com/products/Win32OpenSSL.html

    b)生成私钥

    进入到openssl的bin目录下,执行以下命令:

    openssl genrsa -out rsa_private_key.pem 1024

    会在bin目录下看到新生成的私钥文件rsa_private_key.pem,文件内容如下:

    Xml代码

    1 -----BEGIN RSA PRIVATE KEY-----2 MIICXgIBAAKBgQDtd1lKsX6ylsAEWFi7E/ut8krJy9PQ7sGYKhIm9TvIdZiq5xzy3 aw8NOLzKZ1k486MePYG4tSuoaxSbwuPLwVUzYFvnUZo7aWCIGKn16UWTM4nxc/+d4 wce+bhcKrlLbTWi8l580LTE7GxclTh8z7gHq59ivhaoGbK7FNxlUfB4TSQIDAQAB5 AoGBAIgTk0x1J+hI8KHMypPxoJCOPoMi1S9uEewTd7FxaB+4G5Mbuv/Dj62A7NaD6 oKI9IyUqE9L3ppvtOLMFXCofkKU0p4j7MEJdZ+CjVvgextkWa80nj/UZiM1oOL6Y7 HwH4ZtPtY+pFCTK1rdn3+070qBB9tnVntbN/jq0Ld7f0t7UNAkEA9ryI0kxJL9Pu8 pO9NEeWuCUo4xcl9x/M9+mtkfY3VoDDDV1E/eUjmoTfANYwrjcddiQrO0MLyEdoo9 tiLpN77qOwJBAPZhtv/+pqMVTrLxWnVKLZ4ZVTPPgJQQkFdhWwYlz7oKzB3VbQRt10 /jLFXUyCN2eCP7rglrXnaz7AYBftF0ajHEsCQQDDNfkeQULqN0gpcDdOwKRIL1Pp11 kHgWmWlg1lTETVJGEi6Kx/prL/VgeiZ1dzgCTUjAoy9r1cEFxM/PAqH3+/F/AkEA12 zsTCp6Q2hLblDRewKq7OCdiIwKpr5dbgy/RQR6CD7EYTdxYeH5GPu1wXKJY/mQae13 JV9GG/LS9h7MhkfbONS6cQJAdBEb5vloBDLcSQFDQO/VZ9SKFHCmHLXluhhIizYK14 Gzgf3OXEGNDSAC3qy+ZTnLd3N5iYrVbK52UoiLOLhhNMqA==15 -----END RSA PRIVATE KEY-----

    c)生成公钥

    在bin目录下,执行以下命令:

    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

    会在bin目录下看到新生成的公钥文件rsa_public_key.pem,文件内容如下:

    Xml代码

    1 -----BEGIN PUBLIC KEY-----2 MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDtd1lKsX6ylsAEWFi7E/ut8krJ3 y9PQ7sGYKhIm9TvIdZiq5xzyaw8NOLzKZ1k486MePYG4tSuoaxSbwuPLwVUzYFvn4 UZo7aWCIGKn16UWTM4nxc/+dwce+bhcKrlLbTWi8l580LTE7GxclTh8z7gHq59iv5 haoGbK7FNxlUfB4TSQIDAQAB6 -----END PUBLIC KEY-----

    2. 客户端签名

    2.1 java版签名实现

    Java代码

    1 /**

    2 * rsa签名4 *@paramcontent5 * 待签名的字符串6 *@paramprivateKey7 * rsa私钥字符串8 *@paramcharset9 * 字符编码10 *@return签名结果11 *@throwsException12 * 签名失败则抛出异常13 */

    14 public String rsaSign(String content, String privateKey, String charset) throwsSignatureException {15 try{16 PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", newByteArrayInputStream(privateKey.getBytes()));17

    18 Signature signature = Signature.getInstance("SHA1WithRSA");19 signature.initSign(priKey);20 if(StringUtils.isEmpty(charset)) {21 signature.update(content.getBytes());22 } else{23 signature.update(content.getBytes(charset));24 }25

    26 byte[] signed =signature.sign();27 return newString(Base64.encodeBase64(signed));28 } catch(Exception e) {29 throw new SignatureException("RSAcontent = " + content + "; charset = " +charset, e);30 }31 }32

    33 public PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throwsException {34 if (ins == null ||StringUtils.isEmpty(algorithm)) {35 return null;36 }37

    38 KeyFactory keyFactory =KeyFactory.getInstance(algorithm);39 byte[] encodedKey =StreamUtil.readText(ins).getBytes();40 encodedKey =Base64.decodeBase64(encodedKey);41 return keyFactory.generatePrivate(newPKCS8EncodedKeySpec(encodedKey));42 }

    注意:参数privateKey是Pem私钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串。

    如果签名报以下错误:

    java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

    则说明rsa私钥的格式不是pksc8格式,需要使用以下命令转换一下:

    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

    然后再提取去除头和尾以及换行符后字符串作为java版用的rsa私钥

    2.2 php签名实现

    Php代码

    1 function sign($content, $rsaPrivateKeyPem) {2 $priKey = file_get_contents($rsaPrivateKeyPem);3 $res = openssl_get_privatekey($priKey);4 openssl_sign($content, $sign, $res);5 openssl_free_key($res);6 $sign = base64_encode($sign);7 return $sign;8 }

    注意:$rsaPrivateKeyPem为pem私钥文件路径

    2.3 c#签名实现(引用了国外某位仁兄的方案)

    C#代码

    1 usingSystem;2 usingSystem.Text;3 usingSystem.Security.Cryptography;4 usingSystem.Web;5 usingSystem.IO;6

    7 namespaceAop.Api.Util8 {9 ///

    10 ///RSA签名工具类。11 ///

    12 public classRSAUtil13 {14

    15 public static string RSASign(string data, stringprivateKeyPem)16 {17 RSACryptoServiceProvider rsaCsp =LoadCertificateFile(privateKeyPem);18 byte[] dataBytes =Encoding.UTF8.GetBytes(data);19 byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");20 returnConvert.ToBase64String(signatureBytes);21 }22

    23 private static byte[] GetPem(string type, byte[] data)24 {25 string pem =Encoding.UTF8.GetString(data);26 string header = String.Format("-----BEGIN {0}-----\\n", type);27 string footer = String.Format("-----END {0}-----", type);28 int start = pem.IndexOf(header) +header.Length;29 int end =pem.IndexOf(footer, start);30 string base64 = pem.Substring(start, (end -start));31 returnConvert.FromBase64String(base64);32 }33

    34 private static RSACryptoServiceProvider LoadCertificateFile(stringfilename)35 {36 using (System.IO.FileStream fs =System.IO.File.OpenRead(filename))37 {38 byte[] data = new byte[fs.Length];39 byte[] res = null;40 fs.Read(data, 0, data.Length);41 if (data[0] != 0x30)42 {43 res = GetPem("RSA PRIVATE KEY", data);44 }45 try

    46 {47 RSACryptoServiceProvider rsa =DecodeRSAPrivateKey(res);48 returnrsa;49 }50 catch(Exception ex)51 {52 }53 return null;54 }55 }56

    57 private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)58 {59 byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;60

    61 //--------- Set up stream to decode the asn.1 encoded RSA private key ------

    62 MemoryStream mem = newMemoryStream(privkey);63 BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading

    64 byte bt = 0;65 ushort twobytes = 0;66 int elems = 0;67 try

    68 {69 twobytes =binr.ReadUInt16();70 if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)

    71 binr.ReadByte(); //advance 1 byte

    72 else if (twobytes == 0x8230)73 binr.ReadInt16(); //advance 2 bytes

    74 else

    75 return null;76

    77 twobytes =binr.ReadUInt16();78 if (twobytes != 0x0102) //version number

    79 return null;80 bt =binr.ReadByte();81 if (bt != 0x00)82 return null;83

    84

    85 //------ all private key components are Integer sequences ----

    86 elems =GetIntegerSize(binr);87 MODULUS =binr.ReadBytes(elems);88

    89 elems =GetIntegerSize(binr);90 E =binr.ReadBytes(elems);91

    92 elems =GetIntegerSize(binr);93 D =binr.ReadBytes(elems);94

    95 elems =GetIntegerSize(binr);96 P =binr.ReadBytes(elems);97

    98 elems =GetIntegerSize(binr);99 Q =binr.ReadBytes(elems);100

    101 elems =GetIntegerSize(binr);102 DP =binr.ReadBytes(elems);103

    104 elems =GetIntegerSize(binr);105 DQ =binr.ReadBytes(elems);106

    107 elems =GetIntegerSize(binr);108 IQ =binr.ReadBytes(elems);109

    110

    111 //------- create RSACryptoServiceProvider instance and initialize with public key -----

    112 CspParameters CspParameters = newCspParameters();113 CspParameters.Flags =CspProviderFlags.UseMachineKeyStore;114 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);115 RSAParameters RSAparams = newRSAParameters();116 RSAparams.Modulus =MODULUS;117 RSAparams.Exponent =E;118 RSAparams.D =D;119 RSAparams.P =P;120 RSAparams.Q =Q;121 RSAparams.DP =DP;122 RSAparams.DQ =DQ;123 RSAparams.InverseQ =IQ;124 RSA.ImportParameters(RSAparams);125 returnRSA;126 }127 catch(Exception ex)128 {129 return null;130 }131 finally

    132 {133 binr.Close();134 }135 }136

    137 private static intGetIntegerSize(BinaryReader binr)138 {139 byte bt = 0;140 byte lowbyte = 0x00;141 byte highbyte = 0x00;142 int count = 0;143 bt =binr.ReadByte();144 if (bt != 0x02) //expect integer

    145 return 0;146 bt =binr.ReadByte();147

    148 if (bt == 0x81)149 count = binr.ReadByte(); //data size in next byte

    150 else

    151 if (bt == 0x82)152 {153 highbyte = binr.ReadByte(); //data size in next 2 bytes

    154 lowbyte =binr.ReadByte();155 byte[] modint = { lowbyte, highbyte, 0x00, 0x00};156 count = BitConverter.ToInt32(modint, 0);157 }158 else

    159 {160 count = bt; //we already have the data size

    161 }162

    163 while (binr.ReadByte() == 0x00)164 { //remove high order zeros in data

    165 count -= 1;166 }167 binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte

    168 returncount;169 }170 }171 }

    注:privateKeyPem为私钥文件路径

    3. 服务端java验签

    Java代码

    1 /**

    2 * rsa验签3 *4 *@paramcontent 被签名的内容5 *@paramsign 签名后的结果6 *@parampublicKey rsa公钥7 *@paramcharset 字符集8 *@return验签结果9 *@throwsSignatureException 验签失败,则抛异常10 */

    11 boolean doCheck(String content, String sign, String publicKey, String charset) throwsSignatureException {12 try{13 PublicKey pubKey = getPublicKeyFromX509("RSA", newByteArrayInputStream(publicKey.getBytes()));14

    15 Signature signature = Signature.getInstance("SHA1WithRSA");16 signature.initVerify(pubKey);17 signature.update(getContentBytes(content, charset));18 returnsignature.verify(Base64.decodeBase64(sign.getBytes()));19 } catch(Exception e) {20 throw new SignatureException("RSA验证签名[content = " + content + "; charset = " +charset21 + "; signature = " + sign + "]发生异常!", e);22 }23 }24

    25 private PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throwsNoSuchAlgorithmException {26 try{27 KeyFactory keyFactory =KeyFactory.getInstance(algorithm);28

    29 StringWriter writer = newStringWriter();30 StreamUtil.io(newInputStreamReader(ins), writer);31 byte[] encodedKey =writer.toString().getBytes();32

    33 //先base64解码

    34 encodedKey =Base64.decodeBase64(encodedKey);35 return keyFactory.generatePublic(newX509EncodedKeySpec(encodedKey));36 } catch(IOException ex) {37 //不可能发生

    38 } catch(InvalidKeySpecException ex) {39 //不可能发生

    40 }41 return null;42 }43

    44 private byte[] getContentBytes(String content, String charset) throwsUnsupportedEncodingException {45 if(StringUtil.isEmpty(charset)) {46 returncontent.getBytes();47 }48

    49 returncontent.getBytes(charset);50 }

    注意:参数publicKey是Pem公钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串。

    展开全文
  • 本论文介绍了基于java带数字签名电子邮件系统,对使用的相关的技术进行了详细的阐述。按照软件开发的生命周期论述了系统分析、概要设计、详细设计和代码实现。具体论述了数字签名在邮件系统中的实现原理。以及邮件...
  • 电子签名,盖章实例

    2017-02-18 18:58:49
    java jQuery html5 电子签名 盖章实例,需要研发整合才行。本人开发已实现 电子签名盖章 安全认证领域。。方法有很多,看需求,看知识面有多广。
  • 这里是想说明自己在开发工程中遇到的坑,有这么一个需求,就是利用java 实现生成电子表单,里面用到了openoffice中间件,同时将电子表单内容生成excel后转为pdf 后生成图片,里面实现了动态签名,盖章等效果,
  • 由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥RSA 本文主要介绍如何基于java、php、c#在...

    在开放平台领域,需要给isv提供sdk,签名是Sdk中需要提供的功能之一。由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥RSA

    本文主要介绍如何基于java、php、c#在客户端使用rsa签名,然后在服务端使用Java验签。

    1.基于openssl生成RSA公私钥对

    a)从网上下载openssl工具:http://www.slproweb.com/products/Win32OpenSSL.html

    b)生成私钥

    进入到opensslbin目录下,执行以下命令:

    openssl genrsa -out rsa_private_key.pem 1024

    会在bin目录下看到新生成的私钥文件rsa_private_key.pem,文件内容如下:

    -----BEGIN RSA PRIVATE KEY-----
    MIICXgIBAAKBgQDtd1lKsX6ylsAEWFi7E/ut8krJy9PQ7sGYKhIm9TvIdZiq5xzy
    aw8NOLzKZ1k486MePYG4tSuoaxSbwuPLwVUzYFvnUZo7aWCIGKn16UWTM4nxc/+d
    wce+bhcKrlLbTWi8l580LTE7GxclTh8z7gHq59ivhaoGbK7FNxlUfB4TSQIDAQAB
    AoGBAIgTk0x1J+hI8KHMypPxoJCOPoMi1S9uEewTd7FxaB+4G5Mbuv/Dj62A7NaD
    oKI9IyUqE9L3ppvtOLMFXCofkKU0p4j7MEJdZ+CjVvgextkWa80nj/UZiM1oOL6Y
    HwH4ZtPtY+pFCTK1rdn3+070qBB9tnVntbN/jq0Ld7f0t7UNAkEA9ryI0kxJL9Pu
    pO9NEeWuCUo4xcl9x/M9+mtkfY3VoDDDV1E/eUjmoTfANYwrjcddiQrO0MLyEdoo
    tiLpN77qOwJBAPZhtv/+pqMVTrLxWnVKLZ4ZVTPPgJQQkFdhWwYlz7oKzB3VbQRt
    /jLFXUyCN2eCP7rglrXnaz7AYBftF0ajHEsCQQDDNfkeQULqN0gpcDdOwKRIL1Pp
    kHgWmWlg1lTETVJGEi6Kx/prL/VgeiZ1dzgCTUjAoy9r1cEFxM/PAqH3+/F/AkEA
    zsTCp6Q2hLblDRewKq7OCdiIwKpr5dbgy/RQR6CD7EYTdxYeH5GPu1wXKJY/mQae
    JV9GG/LS9h7MhkfbONS6cQJAdBEb5vloBDLcSQFDQO/VZ9SKFHCmHLXluhhIizYK
    Gzgf3OXEGNDSAC3qy+ZTnLd3N5iYrVbK52UoiLOLhhNMqA==
    -----END RSA PRIVATE KEY-----

    c)生成公钥

    bin目录下,执行以下命令:

    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

    会在bin目录下看到新生成的公钥文件rsa_public_key.pem,文件内容如下:

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDtd1lKsX6ylsAEWFi7E/ut8krJ
    y9PQ7sGYKhIm9TvIdZiq5xzyaw8NOLzKZ1k486MePYG4tSuoaxSbwuPLwVUzYFvn
    UZo7aWCIGKn16UWTM4nxc/+dwce+bhcKrlLbTWi8l580LTE7GxclTh8z7gHq59iv
    haoGbK7FNxlUfB4TSQIDAQAB
    -----END PUBLIC KEY-----

    2. 客户端签名

    2.1 java版签名实现

    /**
         * rsa签名
         * 
         * @param content
         *            待签名的字符串
         * @param privateKey
         *            rsa私钥字符串
         * @param charset
         *            字符编码
         * @return 签名结果
         * @throws Exception
         *             签名失败则抛出异常
         */
        public String rsaSign(String content, String privateKey, String charset) throws SignatureException {
            try {
                PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));
    
                Signature signature = Signature.getInstance("SHA1WithRSA");
                signature.initSign(priKey);
                if (StringUtils.isEmpty(charset)) {
                    signature.update(content.getBytes());
                } else {
                    signature.update(content.getBytes(charset));
                }
    
                byte[] signed = signature.sign();
                return new String(Base64.encodeBase64(signed));
            } catch (Exception e) {
                throw new SignatureException("RSAcontent = " + content + "; charset = " + charset, e);
            }
        }
    
        public PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {
            if (ins == null || StringUtils.isEmpty(algorithm)) {
                return null;
            }
    
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            byte[] encodedKey = StreamUtil.readText(ins).getBytes();
            encodedKey = Base64.decodeBase64(encodedKey);
            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
        }

    注意:参数privateKeyPem私钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串。

    如果签名报以下错误:

    java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

    则说明rsa私钥的格式不是pksc8格式,需要使用以下命令转换一下:

    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

    然后再提取去除头和尾以及换行符后字符串作为java版用的rsa私钥。

    2.2 php签名实现

    function sign($content, $rsaPrivateKeyPem) {
            $priKey = file_get_contents($rsaPrivateKeyPem);
            $res = openssl_get_privatekey($priKey);
            openssl_sign($content, $sign, $res);
            openssl_free_key($res);
            $sign = base64_encode($sign);
            return $sign;
        }

    注意:$rsaPrivateKeyPempem私钥文件路径

    2.3 c#签名实现(引用了国外某位仁兄的方案)

    using System;
    using System.Text;
    using System.Security.Cryptography;
    using System.Web;
    using System.IO;
    
    namespace Aop.Api.Util
    {
        /// <summary>
        /// RSA签名工具类。
        /// </summary>
        public class RSAUtil
        {
    
            public static string RSASign(string data, string privateKeyPem)
            {
                RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem);
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
                byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
                return Convert.ToBase64String(signatureBytes);
            }
    
            private static byte[] GetPem(string type, byte[] data)
            {
                string pem = Encoding.UTF8.GetString(data);
                string header = String.Format("-----BEGIN {0}-----\\n", type);
                string footer = String.Format("-----END {0}-----", type);
                int start = pem.IndexOf(header) + header.Length;
                int end = pem.IndexOf(footer, start);
                string base64 = pem.Substring(start, (end - start));
                return Convert.FromBase64String(base64);
            }
    
            private static RSACryptoServiceProvider LoadCertificateFile(string filename)
            {
                using (System.IO.FileStream fs = System.IO.File.OpenRead(filename))
                {
                    byte[] data = new byte[fs.Length];
                    byte[] res = null;
                    fs.Read(data, 0, data.Length);
                    if (data[0] != 0x30)
                    {
                        res = GetPem("RSA PRIVATE KEY", data);
                    }
                    try
                    {
                        RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);
                        return rsa;
                    }
                    catch (Exception ex)
                    {
                    }
                    return null;
                }
            }
    
            private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
            {
                byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
    
                // --------- Set up stream to decode the asn.1 encoded RSA private key ------
                MemoryStream mem = new MemoryStream(privkey);
                BinaryReader binr = new BinaryReader(mem);  //wrap Memory Stream with BinaryReader for easy reading
                byte bt = 0;
                ushort twobytes = 0;
                int elems = 0;
                try
                {
                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                        binr.ReadByte();    //advance 1 byte
                    else if (twobytes == 0x8230)
                        binr.ReadInt16();    //advance 2 bytes
                    else
                        return null;
    
                    twobytes = binr.ReadUInt16();
                    if (twobytes != 0x0102) //version number
                        return null;
                    bt = binr.ReadByte();
                    if (bt != 0x00)
                        return null;
    
    
                    //------ all private key components are Integer sequences ----
                    elems = GetIntegerSize(binr);
                    MODULUS = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    E = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    D = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    P = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    Q = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    DP = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    DQ = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    IQ = binr.ReadBytes(elems);
    
    
                    // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                    CspParameters CspParameters = new CspParameters();
                    CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
                    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
                    RSAParameters RSAparams = new RSAParameters();
                    RSAparams.Modulus = MODULUS;
                    RSAparams.Exponent = E;
                    RSAparams.D = D;
                    RSAparams.P = P;
                    RSAparams.Q = Q;
                    RSAparams.DP = DP;
                    RSAparams.DQ = DQ;
                    RSAparams.InverseQ = IQ;
                    RSA.ImportParameters(RSAparams);
                    return RSA;
                }
                catch (Exception ex)
                {
                    return null;
                }
                finally
                {
                    binr.Close();
                }
            }
    
            private static int GetIntegerSize(BinaryReader binr)
            {
                byte bt = 0;
                byte lowbyte = 0x00;
                byte highbyte = 0x00;
                int count = 0;
                bt = binr.ReadByte();
                if (bt != 0x02)        //expect integer
                    return 0;
                bt = binr.ReadByte();
    
                if (bt == 0x81)
                    count = binr.ReadByte();    // data size in next byte
                else
                    if (bt == 0x82)
                    {
                        highbyte = binr.ReadByte();    // data size in next 2 bytes
                        lowbyte = binr.ReadByte();
                        byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                        count = BitConverter.ToInt32(modint, 0);
                    }
                    else
                    {
                        count = bt;        // we already have the data size
                    }
    
                while (binr.ReadByte() == 0x00)
                {    //remove high order zeros in data
                    count -= 1;
                }
                binr.BaseStream.Seek(-1, SeekOrigin.Current);        //last ReadByte wasn't a removed zero, so back up a byte
                return count;
            }
        }
    }

    注:privateKeyPem为私钥文件路径

    3. 服务端java验签

    /**
         * rsa验签
         * 
         * @param content 被签名的内容
         * @param sign 签名后的结果
         * @param publicKey rsa公钥
         * @param charset 字符集
         * @return 验签结果
         * @throws SignatureException 验签失败,则抛异常
         */
        boolean doCheck(String content, String sign, String publicKey, String charset) throws SignatureException {
            try {
                PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));
    
                Signature signature = Signature.getInstance("SHA1WithRSA");
                signature.initVerify(pubKey);
                signature.update(getContentBytes(content, charset));
                return signature.verify(Base64.decodeBase64(sign.getBytes()));
            } catch (Exception e) {
                throw new SignatureException("RSA验证签名[content = " + content + "; charset = " + charset
                                             + "; signature = " + sign + "]发生异常!", e);
            }
        }
    
        private PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws NoSuchAlgorithmException {
            try {
                KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
    
                StringWriter writer = new StringWriter();
                StreamUtil.io(new InputStreamReader(ins), writer);
                byte[] encodedKey = writer.toString().getBytes();
    
                // 先base64解码
                encodedKey = Base64.decodeBase64(encodedKey);
                return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
            } catch (IOException ex) {
                // 不可能发生
            } catch (InvalidKeySpecException ex) {
                // 不可能发生
            }
            return null;
        }
    
        private byte[] getContentBytes(String content, String charset) throws UnsupportedEncodingException {
            if (StringUtil.isEmpty(charset)) {
                return content.getBytes();
            }
    
            return content.getBytes(charset);
        }

    注意:参数publicKeyPem公钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串。

    展开全文
  • 由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥RSA 本文主要介绍如何基于java、php、c#在...

    在开放平台领域,需要给isv提供sdk,签名是Sdk中需要提供的功能之一。由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥RSA

           本文主要介绍如何基于java、php、c#在客户端使用rsa签名,然后在服务端使用Java验签。

     

    1. 基于openssl生成RSA公私钥对
    a)从网上下载openssl工具:http://www.slproweb.com/products/Win32OpenSSL.html

      b)生成私钥

    进入到openssl的bin目录下,执行以下命令:

    openssl genrsa -out rsa_private_key.pem 1024

    会在bin目录下看到新生成的私钥文件rsa_private_key.pem,文件内容如下:

    -----BEGIN RSA PRIVATE KEY-----
    MIICXgIBAAKBgQDtd1lKsX6ylsAEWFi7E/ut8krJy9PQ7sGYKhIm9TvIdZiq5xzy
    aw8NOLzKZ1k486MePYG4tSuoaxSbwuPLwVUzYFvnUZo7aWCIGKn16UWTM4nxc/+d
    wce+bhcKrlLbTWi8l580LTE7GxclTh8z7gHq59ivhaoGbK7FNxlUfB4TSQIDAQAB
    AoGBAIgTk0x1J+hI8KHMypPxoJCOPoMi1S9uEewTd7FxaB+4G5Mbuv/Dj62A7NaD
    oKI9IyUqE9L3ppvtOLMFXCofkKU0p4j7MEJdZ+CjVvgextkWa80nj/UZiM1oOL6Y
    HwH4ZtPtY+pFCTK1rdn3+070qBB9tnVntbN/jq0Ld7f0t7UNAkEA9ryI0kxJL9Pu
    pO9NEeWuCUo4xcl9x/M9+mtkfY3VoDDDV1E/eUjmoTfANYwrjcddiQrO0MLyEdoo
    tiLpN77qOwJBAPZhtv/+pqMVTrLxWnVKLZ4ZVTPPgJQQkFdhWwYlz7oKzB3VbQRt
    /jLFXUyCN2eCP7rglrXnaz7AYBftF0ajHEsCQQDDNfkeQULqN0gpcDdOwKRIL1Pp
    kHgWmWlg1lTETVJGEi6Kx/prL/VgeiZ1dzgCTUjAoy9r1cEFxM/PAqH3+/F/AkEA
    zsTCp6Q2hLblDRewKq7OCdiIwKpr5dbgy/RQR6CD7EYTdxYeH5GPu1wXKJY/mQae
    JV9GG/LS9h7MhkfbONS6cQJAdBEb5vloBDLcSQFDQO/VZ9SKFHCmHLXluhhIizYK
    Gzgf3OXEGNDSAC3qy+ZTnLd3N5iYrVbK52UoiLOLhhNMqA==
    -----END RSA PRIVATE KEY-----

      c)生成公钥

    在bin目录下,执行以下命令:

    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

    会在bin目录下看到新生成的公钥文件rsa_public_key.pem,文件内容如下:

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDtd1lKsX6ylsAEWFi7E/ut8krJ
    y9PQ7sGYKhIm9TvIdZiq5xzyaw8NOLzKZ1k486MePYG4tSuoaxSbwuPLwVUzYFvn
    UZo7aWCIGKn16UWTM4nxc/+dwce+bhcKrlLbTWi8l580LTE7GxclTh8z7gHq59iv
    haoGbK7FNxlUfB4TSQIDAQAB
    -----END PUBLIC KEY-----

     2. 客户端签名

      2.1 java版签名实现

    /**
         * rsa签名
         * 
         * @param content
         *            待签名的字符串
         * @param privateKey
         *            rsa私钥字符串
         * @param charset
         *            字符编码
         * @return 签名结果
         * @throws Exception
         *             签名失败则抛出异常
         */
        public String rsaSign(String content, String privateKey, String charset) throws SignatureException {
            try {
                PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));
    
                Signature signature = Signature.getInstance("SHA1WithRSA");
                signature.initSign(priKey);
                if (StringUtils.isEmpty(charset)) {
                    signature.update(content.getBytes());
                } else {
                    signature.update(content.getBytes(charset));
                }
    
                byte[] signed = signature.sign();
                return new String(Base64.encodeBase64(signed));
            } catch (Exception e) {
                throw new SignatureException("RSAcontent = " + content + "; charset = " + charset, e);
            }
        }
    
        public PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {
            if (ins == null || StringUtils.isEmpty(algorithm)) {
                return null;
            }
    
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            byte[] encodedKey = StreamUtil.readText(ins).getBytes();
            encodedKey = Base64.decodeBase64(encodedKey);
            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
        }

     注意:参数privateKey是Pem私钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串。

    如果签名报以下错误:

    java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

    则说明rsa私钥的格式不是pksc8格式,需要使用以下命令转换一下:

    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

    然后再提取去除头和尾以及换行符后字符串作为java版用的rsa私钥。

    2.2 php签名实现

    function sign($content, $rsaPrivateKeyPem) {
            $priKey = file_get_contents($rsaPrivateKeyPem);
            $res = openssl_get_privatekey($priKey);
            openssl_sign($content, $sign, $res);
            openssl_free_key($res);
            $sign = base64_encode($sign);
            return $sign;
        }

    注意:$rsaPrivateKeyPem为pem私钥文件路径

      2.3 c#签名实现(引用了国外某位仁兄的方案)

    using System;
    using System.Text;
    using System.Security.Cryptography;
    using System.Web;
    using System.IO;
    
    namespace Aop.Api.Util
    {
        /// <summary>
        /// RSA签名工具类。
        /// </summary>
        public class RSAUtil
        {
    
            public static string RSASign(string data, string privateKeyPem)
            {
                RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem);
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
                byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
                return Convert.ToBase64String(signatureBytes);
            }
    
            private static byte[] GetPem(string type, byte[] data)
            {
                string pem = Encoding.UTF8.GetString(data);
                string header = String.Format("-----BEGIN {0}-----\\n", type);
                string footer = String.Format("-----END {0}-----", type);
                int start = pem.IndexOf(header) + header.Length;
                int end = pem.IndexOf(footer, start);
                string base64 = pem.Substring(start, (end - start));
                return Convert.FromBase64String(base64);
            }
    
            private static RSACryptoServiceProvider LoadCertificateFile(string filename)
            {
                using (System.IO.FileStream fs = System.IO.File.OpenRead(filename))
                {
                    byte[] data = new byte[fs.Length];
                    byte[] res = null;
                    fs.Read(data, 0, data.Length);
                    if (data[0] != 0x30)
                    {
                        res = GetPem("RSA PRIVATE KEY", data);
                    }
                    try
                    {
                        RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);
                        return rsa;
                    }
                    catch (Exception ex)
                    {
                    }
                    return null;
                }
            }
    
            private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
            {
                byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
    
                // --------- Set up stream to decode the asn.1 encoded RSA private key ------
                MemoryStream mem = new MemoryStream(privkey);
                BinaryReader binr = new BinaryReader(mem);  //wrap Memory Stream with BinaryReader for easy reading
                byte bt = 0;
                ushort twobytes = 0;
                int elems = 0;
                try
                {
                    twobytes = binr.ReadUInt16();
                    if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
                        binr.ReadByte();    //advance 1 byte
                    else if (twobytes == 0x8230)
                        binr.ReadInt16();    //advance 2 bytes
                    else
                        return null;
    
                    twobytes = binr.ReadUInt16();
                    if (twobytes != 0x0102) //version number
                        return null;
                    bt = binr.ReadByte();
                    if (bt != 0x00)
                        return null;
    
    
                    //------ all private key components are Integer sequences ----
                    elems = GetIntegerSize(binr);
                    MODULUS = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    E = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    D = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    P = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    Q = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    DP = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    DQ = binr.ReadBytes(elems);
    
                    elems = GetIntegerSize(binr);
                    IQ = binr.ReadBytes(elems);
                    
    
                    // ------- create RSACryptoServiceProvider instance and initialize with public key -----
                    CspParameters CspParameters = new CspParameters();
                    CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
                    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
                    RSAParameters RSAparams = new RSAParameters();
                    RSAparams.Modulus = MODULUS;
                    RSAparams.Exponent = E;
                    RSAparams.D = D;
                    RSAparams.P = P;
                    RSAparams.Q = Q;
                    RSAparams.DP = DP;
                    RSAparams.DQ = DQ;
                    RSAparams.InverseQ = IQ;
                    RSA.ImportParameters(RSAparams);
                    return RSA;
                }
                catch (Exception ex)
                {
                    return null;
                }
                finally
                {
                    binr.Close();
                }
            }
    
            private static int GetIntegerSize(BinaryReader binr)
            {
                byte bt = 0;
                byte lowbyte = 0x00;
                byte highbyte = 0x00;
                int count = 0;
                bt = binr.ReadByte();
                if (bt != 0x02)        //expect integer
                    return 0;
                bt = binr.ReadByte();
    
                if (bt == 0x81)
                    count = binr.ReadByte();    // data size in next byte
                else
                    if (bt == 0x82)
                    {
                        highbyte = binr.ReadByte();    // data size in next 2 bytes
                        lowbyte = binr.ReadByte();
                        byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                        count = BitConverter.ToInt32(modint, 0);
                    }
                    else
                    {
                        count = bt;        // we already have the data size
                    }
    
                while (binr.ReadByte() == 0x00)
                {    //remove high order zeros in data
                    count -= 1;
                }
                binr.BaseStream.Seek(-1, SeekOrigin.Current);        //last ReadByte wasn't a removed zero, so back up a byte
                return count;
            }
        }
    }

    注:privateKeyPem为私钥文件路径

      3. 服务端java验签

    /**
         * rsa验签
         * 
         * @param content 被签名的内容
         * @param sign 签名后的结果
         * @param publicKey rsa公钥
         * @param charset 字符集
         * @return 验签结果
         * @throws SignatureException 验签失败,则抛异常
         */
        boolean doCheck(String content, String sign, String publicKey, String charset) throws SignatureException {
            try {
                PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));
    
                Signature signature = Signature.getInstance("SHA1WithRSA");
                signature.initVerify(pubKey);
                signature.update(getContentBytes(content, charset));
                return signature.verify(Base64.decodeBase64(sign.getBytes()));
            } catch (Exception e) {
                throw new SignatureException("RSA验证签名[content = " + content + "; charset = " + charset
                                             + "; signature = " + sign + "]发生异常!", e);
            }
        }
    
        private PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws NoSuchAlgorithmException {
            try {
                KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
    
                StringWriter writer = new StringWriter();
                StreamUtil.io(new InputStreamReader(ins), writer);
                byte[] encodedKey = writer.toString().getBytes();
    
                // 先base64解码
                encodedKey = Base64.decodeBase64(encodedKey);
                return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
            } catch (IOException ex) {
                // 不可能发生
            } catch (InvalidKeySpecException ex) {
                // 不可能发生
            }
            return null;
        }
    
        private byte[] getContentBytes(String content, String charset) throws UnsupportedEncodingException {
            if (StringUtil.isEmpty(charset)) {
                return content.getBytes();
            }
    
            return content.getBytes(charset);
        }

     注意:参数publicKey是Pem公钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串。

     

    原文地址:http://xw-z1985.iteye.com/blog/1837376

     

    转载于:https://www.cnblogs.com/davidwang456/p/3924834.html

    展开全文
  • 由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥RSA  本文主要介绍如何基于java、php、c#在...
    在开放平台领域,需要给isv提供sdk,签名是Sdk中需要提供的功能之一。由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较高,所以会采用非对称密钥RSA
           本文主要介绍如何基于java、php、c#在客户端使用rsa签名,然后在服务端使用Java验签。
     
    基于openssl生成RSA公私钥对
    a)从网上下载openssl工具:http://www.slproweb.com/products/Win32OpenSSL.html
      b)生成私钥
    进入到openssl的bin目录下,执行以下命令:
    openssl genrsa -out rsa_private_key.pem 1024

    会在bin目录下看到新生成的私钥文件rsa_private_key.pem,文件内容如下:

    -----BEGIN RSA PRIVATE KEY-----  
    MIICXgIBAAKBgQDtd1lKsX6ylsAEWFi7E/ut8krJy9PQ7sGYKhIm9TvIdZiq5xzy  
    aw8NOLzKZ1k486MePYG4tSuoaxSbwuPLwVUzYFvnUZo7aWCIGKn16UWTM4nxc/+d  
    wce+bhcKrlLbTWi8l580LTE7GxclTh8z7gHq59ivhaoGbK7FNxlUfB4TSQIDAQAB  
    AoGBAIgTk0x1J+hI8KHMypPxoJCOPoMi1S9uEewTd7FxaB+4G5Mbuv/Dj62A7NaD  
    oKI9IyUqE9L3ppvtOLMFXCofkKU0p4j7MEJdZ+CjVvgextkWa80nj/UZiM1oOL6Y  
    HwH4ZtPtY+pFCTK1rdn3+070qBB9tnVntbN/jq0Ld7f0t7UNAkEA9ryI0kxJL9Pu  
    pO9NEeWuCUo4xcl9x/M9+mtkfY3VoDDDV1E/eUjmoTfANYwrjcddiQrO0MLyEdoo  
    tiLpN77qOwJBAPZhtv/+pqMVTrLxWnVKLZ4ZVTPPgJQQkFdhWwYlz7oKzB3VbQRt  
    /jLFXUyCN2eCP7rglrXnaz7AYBftF0ajHEsCQQDDNfkeQULqN0gpcDdOwKRIL1Pp  
    kHgWmWlg1lTETVJGEi6Kx/prL/VgeiZ1dzgCTUjAoy9r1cEFxM/PAqH3+/F/AkEA  
    zsTCp6Q2hLblDRewKq7OCdiIwKpr5dbgy/RQR6CD7EYTdxYeH5GPu1wXKJY/mQae  
    JV9GG/LS9h7MhkfbONS6cQJAdBEb5vloBDLcSQFDQO/VZ9SKFHCmHLXluhhIizYK  
    Gzgf3OXEGNDSAC3qy+ZTnLd3N5iYrVbK52UoiLOLhhNMqA==  
    -----END RSA PRIVATE KEY-----  

    c)生成公钥
    在bin目录下,执行以下命令:
    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
    会在bin目录下看到新生成的公钥文件rsa_public_key.pem,文件内容如下:

    -----BEGIN PUBLIC KEY-----  
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDtd1lKsX6ylsAEWFi7E/ut8krJ  
    y9PQ7sGYKhIm9TvIdZiq5xzyaw8NOLzKZ1k486MePYG4tSuoaxSbwuPLwVUzYFvn  
    UZo7aWCIGKn16UWTM4nxc/+dwce+bhcKrlLbTWi8l580LTE7GxclTh8z7gHq59iv  
    haoGbK7FNxlUfB4TSQIDAQAB  
    -----END PUBLIC KEY-----  
    2. 客户端签名
      2.1 java版签名实现
    /** 
         * rsa签名 
         *  
         * @param content 
         *            待签名的字符串 
         * @param privateKey 
         *            rsa私钥字符串 
         * @param charset 
         *            字符编码 
         * @return 签名结果 
         * @throws Exception 
         *             签名失败则抛出异常 
         */  
        public String rsaSign(String content, String privateKey, String charset) throws SignatureException {  
            try {  
                PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));  
      
                Signature signature = Signature.getInstance("SHA1WithRSA");  
                signature.initSign(priKey);  
                if (StringUtils.isEmpty(charset)) {  
                    signature.update(content.getBytes());  
                } else {  
                    signature.update(content.getBytes(charset));  
                }  
      
                byte[] signed = signature.sign();  
                return new String(Base64.encodeBase64(signed));  
            } catch (Exception e) {  
                throw new SignatureException("RSAcontent = " + content + "; charset = " + charset, e);  
            }  
        }  
      
        public PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {  
            if (ins == null || StringUtils.isEmpty(algorithm)) {  
                return null;  
            }  
      
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);  
            byte[] encodedKey = StreamUtil.readText(ins).getBytes();  
            encodedKey = Base64.decodeBase64(encodedKey);  
            return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));  
        }  
    

    注意:参数privateKey是Pem私钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串。
    如果签名报以下错误:
    java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
    则说明rsa私钥的格式不是pksc8格式,需要使用以下命令转换一下:
    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
    然后再提取去除头和尾以及换行符后字符串作为java版用的rsa私钥
      2.2 php签名实现

    function sign($content, $rsaPrivateKeyPem) {  
            $priKey = file_get_contents($rsaPrivateKeyPem);  
            $res = openssl_get_privatekey($priKey);  
            openssl_sign($content, $sign, $res);  
            openssl_free_key($res);  
            $sign = base64_encode($sign);  
            return $sign;  
        }  

    注意:$rsaPrivateKeyPem为pem私钥文件路径
      2.3 c#签名实现(引用了国外某位仁兄的方案)

    using System;  
    using System.Text;  
    using System.Security.Cryptography;  
    using System.Web;  
    using System.IO;  
      
    namespace Aop.Api.Util  
    {  
        /// <summary>  
        /// RSA签名工具类。  
        /// </summary>  
        public class RSAUtil  
        {  
      
            public static string RSASign(string data, string privateKeyPem)  
            {  
                RSACryptoServiceProvider rsaCsp = LoadCertificateFile(privateKeyPem);  
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);  
                byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");  
                return Convert.ToBase64String(signatureBytes);  
            }  
      
            private static byte[] GetPem(string type, byte[] data)  
            {  
                string pem = Encoding.UTF8.GetString(data);  
                string header = String.Format("-----BEGIN {0}-----\\n", type);  
                string footer = String.Format("-----END {0}-----", type);  
                int start = pem.IndexOf(header) + header.Length;  
                int end = pem.IndexOf(footer, start);  
                string base64 = pem.Substring(start, (end - start));  
                return Convert.FromBase64String(base64);  
            }  
      
            private static RSACryptoServiceProvider LoadCertificateFile(string filename)  
            {  
                using (System.IO.FileStream fs = System.IO.File.OpenRead(filename))  
                {  
                    byte[] data = new byte[fs.Length];  
                    byte[] res = null;  
                    fs.Read(data, 0, data.Length);  
                    if (data[0] != 0x30)  
                    {  
                        res = GetPem("RSA PRIVATE KEY", data);  
                    }  
                    try  
                    {  
                        RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);  
                        return rsa;  
                    }  
                    catch (Exception ex)  
                    {  
                    }  
                    return null;  
                }  
            }  
      
            private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)  
            {  
                byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;  
      
                // --------- Set up stream to decode the asn.1 encoded RSA private key ------  
                MemoryStream mem = new MemoryStream(privkey);  
                BinaryReader binr = new BinaryReader(mem);  //wrap Memory Stream with BinaryReader for easy reading  
                byte bt = 0;  
                ushort twobytes = 0;  
                int elems = 0;  
                try  
                {  
                    twobytes = binr.ReadUInt16();  
                    if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)  
                        binr.ReadByte();    //advance 1 byte  
                    else if (twobytes == 0x8230)  
                        binr.ReadInt16();    //advance 2 bytes  
                    else  
                        return null;  
      
                    twobytes = binr.ReadUInt16();  
                    if (twobytes != 0x0102) //version number  
                        return null;  
                    bt = binr.ReadByte();  
                    if (bt != 0x00)  
                        return null;  
      
      
                    //------ all private key components are Integer sequences ----  
                    elems = GetIntegerSize(binr);  
                    MODULUS = binr.ReadBytes(elems);  
      
                    elems = GetIntegerSize(binr);  
                    E = binr.ReadBytes(elems);  
      
                    elems = GetIntegerSize(binr);  
                    D = binr.ReadBytes(elems);  
      
                    elems = GetIntegerSize(binr);  
                    P = binr.ReadBytes(elems);  
      
                    elems = GetIntegerSize(binr);  
                    Q = binr.ReadBytes(elems);  
      
                    elems = GetIntegerSize(binr);  
                    DP = binr.ReadBytes(elems);  
      
                    elems = GetIntegerSize(binr);  
                    DQ = binr.ReadBytes(elems);  
      
                    elems = GetIntegerSize(binr);  
                    IQ = binr.ReadBytes(elems);  
                      
      
                    // ------- create RSACryptoServiceProvider instance and initialize with public key -----  
                    CspParameters CspParameters = new CspParameters();  
                    CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;  
                    RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);  
                    RSAParameters RSAparams = new RSAParameters();  
                    RSAparams.Modulus = MODULUS;  
                    RSAparams.Exponent = E;  
                    RSAparams.D = D;  
                    RSAparams.P = P;  
                    RSAparams.Q = Q;  
                    RSAparams.DP = DP;  
                    RSAparams.DQ = DQ;  
                    RSAparams.InverseQ = IQ;  
                    RSA.ImportParameters(RSAparams);  
                    return RSA;  
                }  
                catch (Exception ex)  
                {  
                    return null;  
                }  
                finally  
                {  
                    binr.Close();  
                }  
            }  
      
            private static int GetIntegerSize(BinaryReader binr)  
            {  
                byte bt = 0;  
                byte lowbyte = 0x00;  
                byte highbyte = 0x00;  
                int count = 0;  
                bt = binr.ReadByte();  
                if (bt != 0x02)     //expect integer  
                    return 0;  
                bt = binr.ReadByte();  
      
                if (bt == 0x81)  
                    count = binr.ReadByte();    // data size in next byte  
                else  
                    if (bt == 0x82)  
                    {  
                        highbyte = binr.ReadByte(); // data size in next 2 bytes  
                        lowbyte = binr.ReadByte();  
                        byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };  
                        count = BitConverter.ToInt32(modint, 0);  
                    }  
                    else  
                    {  
                        count = bt;     // we already have the data size  
                    }  
      
                while (binr.ReadByte() == 0x00)  
                {   //remove high order zeros in data  
                    count -= 1;  
                }  
                binr.BaseStream.Seek(-1, SeekOrigin.Current);       //last ReadByte wasn't a removed zero, so back up a byte  
                return count;  
            }  
        }  
    }  

    注:privateKeyPem为私钥文件路径
      3. 服务端java验签

    /** 
         * rsa验签 
         *  
         * @param content 被签名的内容 
         * @param sign 签名后的结果 
         * @param publicKey rsa公钥 
         * @param charset 字符集 
         * @return 验签结果 
         * @throws SignatureException 验签失败,则抛异常 
         */  
        boolean doCheck(String content, String sign, String publicKey, String charset) throws SignatureException {  
            try {  
                PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));  
      
                Signature signature = Signature.getInstance("SHA1WithRSA");  
                signature.initVerify(pubKey);  
                signature.update(getContentBytes(content, charset));  
                return signature.verify(Base64.decodeBase64(sign.getBytes()));  
            } catch (Exception e) {  
                throw new SignatureException("RSA验证签名[content = " + content + "; charset = " + charset  
                                             + "; signature = " + sign + "]发生异常!", e);  
            }  
        }  
      
        private PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws NoSuchAlgorithmException {  
            try {  
                KeyFactory keyFactory = KeyFactory.getInstance(algorithm);  
      
                StringWriter writer = new StringWriter();  
                StreamUtil.io(new InputStreamReader(ins), writer);  
                byte[] encodedKey = writer.toString().getBytes();  
      
                // 先base64解码  
                encodedKey = Base64.decodeBase64(encodedKey);  
                return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));  
            } catch (IOException ex) {  
                // 不可能发生  
            } catch (InvalidKeySpecException ex) {  
                // 不可能发生  
            }  
            return null;  
        }  
      
        private byte[] getContentBytes(String content, String charset) throws UnsupportedEncodingException {  
            if (StringUtil.isEmpty(charset)) {  
                return content.getBytes();  
            }  
      
            return content.getBytes(charset);  
        }  


    注意:参数publicKey是Pem公钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串。









    展开全文
  • 由于电子商务和电子政务的普及,安全加密技术在其中应用非常广泛,对安全加密技术的要求也很高。目前在JAVA环境下实现IDEA 加密具有很多的优势,因为JAVA 是基于面向对象的编程语言, 并且由于它的平台无关性能被大量...
  • 这时就可以通过程序实现在Word中在线打开要签字的电子版文件,然后通过手写批注接口实现在线批阅文件并签名。具体实现步骤如下:第一步:拷贝文件到WEB项目的“WEB-INF/lib”目录下。拷贝PageOffice示例中下的“WEB-...
  • 这时就可以通过程序实现在Word中在线打开要签字的电子版文件,然后通过手写批注接口实现在线批阅文件并签名。具体实现步骤如下:第一步:拷贝文件到WEB项目的“WEB-INF/lib”目录下。拷贝PageOffice示例中下的“WEB-...
  • Java案例开发锦集

    2008-03-04 09:47:42
    目录 第一章 Java与Applet 案例一 图形按钮 案例二 模拟工具条 案例三 Applet与Applet在页内的通信 案例四 电子相册 案例五 百页窗效果 案例六 波浪彩虹文字 案例七 3D立体渐层文字...
  • 此文档包括Java案例开发锦集中所有实例的源代码,具体见下面 目录 第一章 Java与Applet 案例一 图形按钮 案例二 模拟工具条 案例三 Applet与Applet在页内的通信 案例四 电子相册 案例五 ...
  • 一个android项目开发完成之后要安装到设备上或者放到电子市场的话需要签名认证. 下面就详细简介android签名认证的过程及常见问题的解决.   1. 搭建java环境, 安装并配置jdk 2. 安装完成之后进行下列操作(本人jdk...
  • 电子支付的过程中,通过实现身份认证和数 字签名来保证交易的真实性、完整性和不可抵赖 性,是实现电子支付的安全技术基础。0121,集成了 大量的安全特性工具,可以非常方便而快速地开发 含身份认证、数字签名和...
  • 这里是想说明自己在开发工程中遇到的坑,有这么一个需求,就是利用java 实现生成电子表单,里面用到了openoffice中间件,同时将电子表单内容生成excel后转为pdf 后生成图片,里面实现了动态签名,盖章等效果, ...
  • 在开放平台领域,需要给isv提供sdk,签名是Sdk中需要提供的功能之一。由于isv使用的开发语言不是单一的,因此sdk需要提供多种语言的版 本。譬如java、php、c#。另外,在电子商务尤其是支付领域,对安全性的要求比较...
  • 这时就可以通过程序实现在Word中在线打开要签字的电子版文件,然后通过手写批注接口实现在线批阅文件并签名。 具体实现步骤如下: 第一步:拷贝文件到WEB项目的“WEB-INF/lib”目录下。拷贝PageOffice示例中下的...
  • 该扩展允许在电子采购应用程序中进行数字签名 GoK eProcurement签名在Windows ...开发此扩展程序是为了使浏览器能够使用用户的数字证书对文档进行签名,并且Chrome浏览器支持该扩展程序,而无需Java。 支持语言:English
  • java源码包---java 源码 大量 实例

    千次下载 热门讨论 2013-04-18 23:15:26
     用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。 Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历,...
  • 书名:《Java开发实战1200例(第II卷)》(清华大学出版社.李钟尉,陈丹丹) PDF格式扫描版,全书分为6篇21章,共905页。2011年6月出版。 全书压缩打包成2部分,这是第1部分。 注:本电子版缺失了第19-21章的部分,仅...
  • 书名:《Java开发实战1200例(第II卷)》(清华大学出版社.李钟尉,陈丹丹) PDF格式扫描版,全书分为6篇21章,共905页。2011年6月出版。 全书压缩打包成2部分,这是第2部分。 注:本电子版缺失了第19-21章的部分,仅...
  • java源码包2

    千次下载 热门讨论 2013-04-20 11:28:17
     用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。 Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历...
  • java源码包3

    千次下载 热门讨论 2013-04-20 11:30:13
     用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。 Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历...
  • java源码包4

    千次下载 热门讨论 2013-04-20 11:31:44
     用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。 Java日期选择控件完整源代码 14个目标文件 内容索引:JAVA源码,系统相关,日历...
  • Java 图片合成

    2021-03-26 17:23:50
    在web应用开发,有时候会遇到图片合成的场景,比如生成某某申请表时要合成电子签名、某某签章等水印。下面简单介绍一种图片合成工具。 Thumbnailator是一个用来生成图像缩略图的 Java类库,也可以用来进行图片合成。...

空空如也

空空如也

1 2 3 4 5
收藏数 96
精华内容 38
关键字:

java开发电子签名

java 订阅