RSA密钥转换问题

密钥是用C#类库生成的XML格式,
要转成JS下能使用的密钥PEM格式,
最好能互转,详见后附示例说明。

谢谢~

附:

C#生成的私钥(XML):
<RSAKeyValue><Modulus>ww7D0rNm47u+lpe0RmQfZJ5c81LT1yVQjrwPh8V2KYeN1ukSNtQcxXR0up0sOeswtdR2K91FHxY+W2LbBDmB7VvlSbeRCu5UuAVP5N6bGjrXmMxG0TL8eeN+lCfCkIEMppxvcPC+yodxGrSz8LsK/pIkwktQucIwV6136GoceIc=</Modulus><Exponent>AQAB</Exponent><P>8X6BRa4AyPlpSXZhSmbSxoEMFkK1wKkRti2y2AxuHPQ3EJHTw6c4qpvlHAYH0j/duOiHUzFxJaN95zD7qWMBOQ==</P><Q>zsYy1hF7m5+2hMhwwb/Mn/dUp97kfky1H1iboxg62ULnLC/w4e8+/T8+xoF4TNMJTXllL7LEZjRfmctBE+YHvw==</Q><DP>62Nrjge1LDAvuDNzUZo4CNTweyI7Fre1U+XnVT+IdSB2K+h4iVUNnv6lq1MVfJJUBFBi12xx5UYfCqJsKwcdwQ==</DP><DQ>WfUgaMFyZWI2pc4OQDyRaYbQ7beq8MeuhNSn4WzJLXxN1ouE4MaVQNgjF3l8PPATPAF0ZCwCBfUDIoWq6l1JQQ==</DQ><InverseQ>SwxDBI/2cCam37QQ4X3TXRh2gj8rCgz9xCbmtJaFzFQdEn+QCPPHpxsf1sc0HzIeBk4fgHm0jpXbtciqIUX/Cw==</InverseQ><D>q90GjU+lCGMTunxQSvVM88rU+0+vd5FZOWpaBLbnNhBJ2WHiuoyKDTBe6U4y+ZVQheV9eYisrodaygqAD2jcIEwvYaK5MW4J7EQYtwzXtKIKg8ly4MiCXqGgb0N4ndql6lLjIzvVe6+k4qSso0vJfHWYZeUCODvqGTu4e7r7UQE=</D></RSAKeyValue>

JS下的PEM密钥格式(PEM):
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDRhGF7X4A0ZVlEg594WmODVVUIiiPQs04aLmvfg8SborHss5gQ
Xu0aIdUT6nb5rTh5hD2yfpF2WIW6M8z0WxRhwicgXwi80H1aLPf6lEPPLvN29EhQ
NjBpkFkAJUbS8uuhJEeKw0cE49g80eBBF4BCqSL6PFQbP9/rByxdxEoAIQIDAQAB
AoGAA9/q3Zk6ib2GFRpKDLO/O2KMnAfR+b4XJ6zMGeoZ7Lbpi3MW0Nawk9ckVaX0
ZVGqxbSIX5Cvp/yjHHpww+QbUFrw/gCjLiiYjM9E8C3uAF5AKJ0r4GBPl4u8K4bp
bXeSxSB60/wPQFiQAJVcA5xhZVzqNuF3EjuKdHsw+dk+dPECQQDubX/lVGFgD/xY
uchz56Yc7VHX+58BUkNSewSzwJRbcueqknXRWwj97SXqpnYfKqZq78dnEF10SWsr
/NMKi+7XAkEA4PVqDv/OZAbWr4syXZNv/Mpl4r5suzYMMUD9U8B2JIRnrhmGZPzL
x23N9J4hEJ+Xh8tSKVc80jOkrvGlSv+BxwJAaTOtjA3YTV+gU7Hdza53sCnSw/8F
YLrgc6NOJtYhX9xqdevbyn1lkU0zPr8mPYg/F84m6MXixm2iuSz8HZoyzwJARi2p
aYZ5/5B2lwroqnKdZBJMGKFpUDn7Mb5hiSgocxnvMkv6NjT66Xsi3iYakJII9q8C
Ma1qZvT/cigmdbAh7wJAQNXyoizuGEltiSaBXx4H29EdXNYWDJ9SS5f070BRbAIl
dqRh3rcNvpY6BKJqFapda1DjdcncZECMizT/GMrc1w==
-----END RSA PRIVATE KEY-----

回答: RSA密钥转换问题

  1. 需要依赖一个第三方库,叫BouncyCastlenuget链接

    xml转pem:

    var rsa = new RSACryptoServiceProvider();
    using(var sr = new StreamReader("e:\\key.xml"))
    {
        rsa.FromXmlString(sr.ReadToEnd());
    }
    var p = rsa.ExportParameters(true);

    var key = new RsaPrivateCrtKeyParameters(
        new BigInteger(1, p.Modulus), new BigInteger(1, p.Exponent), new BigInteger(1, p.D),
        new BigInteger(1, p.P), new BigInteger(1, p.Q), new BigInteger(1, p.DP), new BigInteger(1, p.DQ), 
        new BigInteger(1, p.InverseQ));

    using (var sw = new StreamWriter("e:\\key.pem"))
    {
        var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
        pemWriter.WriteObject(key);
    }

    pem转xml:

    AsymmetricCipherKeyPair keyPair;
    using(var sr = new StreamReader("e:\\key.pem"))
    {
        var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sr);
        keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
    }
    var key = (RsaPrivateCrtKeyParameters)keyPair.Private;
    var p = new RSAParameters {
        Modulus = key.Modulus.ToByteArrayUnsigned(),
        Exponent = key.PublicExponent.ToByteArrayUnsigned(),
        D = key.Exponent.ToByteArrayUnsigned(),
        P = key.P.ToByteArrayUnsigned(),
        Q = key.Q.ToByteArrayUnsigned(),
        DP = key.DP.ToByteArrayUnsigned(),
        DQ = key.DQ.ToByteArrayUnsigned(),
        InverseQ = key.QInv.ToByteArrayUnsigned(),
    };
    var rsa = new RSACryptoServiceProvider();
    rsa.ImportParameters(p);
    using (var sw = new StreamWriter("e:\\key.xml"))
    {
        sw.Write(rsa.ToXmlString(true));
    }

openssl rsa 密钥格式 转换

  1. Q
    使用 rsa密钥生成函数,可以生成 (n,d)  (p,q,dp,dq,dinv)。
    那么通过(p,q,dp,dq,dinv)使用openssl函数,如果能够得到 (n,d)的?

    请高手出手相助,多谢!!!!!!
  2. A
    不知是不是这个?


    private:
    // 公钥
    struct {
    long e;
    long n;
    }pu;
    // 私钥
    struct {
    long d;
    long n;
    }pr;

    // 计算公、私钥
    void AccountKey(long p,long q,long e);



    // 计算公、私钥
    void CMyRSA::AccountKey(long p,long q,long e)
    {
    pu.n=pr.n=p*q;
    pu.e=e;

    long t,d;
    t=(p-1)*(q-1);

    d = 1;
    while(((e * d) % t) != 1)
    {
    d++;
    }
    pr.d=d;
    }

关于RSA 密钥文件结构的问题

  1. Q
    最近在做一个小项目,其中的数字签名部分采用RSA算法,但有一个要求是要使用指定的密钥对,从网上找了些代码,都是自己用KeyPairGenerator生成密钥对,然手再使用,代码如下:

    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    keyPairGen.initialize(512);
    KeyPair keyPair = keyPairGen.generateKeyPair();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

    请问各位大侠,如何使用指定的密钥对来生成RSAPrivateKey 和 RSAPublicKey呢?,或者不采用以上该类,有其他的解决办法没?
  2. A
    http://hi.baidu.com/youshizhihu/blog/item/de40658d95dfae10b31bba8a.html
    这个很详细

关于RSA 加解密 java生成秘钥对 传给 C#进行加密,c#生成的密文怎么转换格式能在JAVA上用私钥解密

  1. Q
     java生成秘钥对  经过转换格式后传给 C#进行加密,C#生成的密文怎么转换格式能在JAVA上用私钥解密
    tes是在C#生成的密文经过BASE64转码存到.txt文件,然后再JAVA中读出来


                     Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    BASE64Decoder decoder = new BASE64Decoder();
    byte[] b1 = decoder.decodeBuffer(tes);
                     /** 执行解密操作 */
    byte[] b = cipher.doFinal(b1);←这行代码解析出错,网上查原因是因为C#加密后得到的格式不正确

    求大神解答
  2. A
    http://www.cnblogs.com/datous/p/RSAKeyConvert.html#

    格式转换要用到一个开源加密库Bouncy Castle Crypto APIs,官网地址: http://www.bouncycastle.org/csharp/


    /// <summary>
    /// RSA密钥格式转换
    /// </summary>
    public class RSAKeyConvert
    {
        /// <summary>
        /// RSA私钥格式转换,java->.net
        /// </summary>
        /// <param name="privateKey">java生成的RSA私钥</param>
        /// <returns></returns>
        public static string RSAPrivateKeyJava2DotNet(string privateKey)
        {
            RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
     
            return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",
                Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),
                Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));
        }
     
        /// <summary>
        /// RSA私钥格式转换,.net->java
        /// </summary>
        /// <param name="privateKey">.net生成的私钥</param>
        /// <returns></returns>
        public static string RSAPrivateKeyDotNet2Java(string privateKey)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(privateKey);
            BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
            BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
            BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));
            BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));
            BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));
            BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));
            BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));
     
            RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);
     
            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
            byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
            return Convert.ToBase64String(serializedPrivateBytes);
        }
     
        /// <summary>
        /// RSA公钥格式转换,java->.net
        /// </summary>
        /// <param name="publicKey">java生成的公钥</param>
        /// <returns></returns>
        public static string RSAPublicKeyJava2DotNet(string publicKey)
        {
            RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
            return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",
                Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),
                Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));
        }
     
        /// <summary>
        /// RSA公钥格式转换,.net->java
        /// </summary>
        /// <param name="publicKey">.net生成的公钥</param>
        /// <returns></returns>
        public static string RSAPublicKeyDotNet2Java(string publicKey)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(publicKey);
            BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
            BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
            RsaKeyParameters pub = new RsaKeyParameters(false, m, p);
     
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
            byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
            return Convert.ToBase64String(serializedPublicBytes);
        }
    }

VPN配置

  1. Q
    手上有台cisco 5505设备,主要用于VPN,拿到手的时候里面有配置,而且据说可以正常使用的。

    为了学习,我保存了配置到tftp服务器上,后来再把配置拿回来以后,改了内网地址什么的,也没能连上vpn,不知问题出在哪里了。

    ASA Version 8.0(2)
    !
    hostname yangguoxuan
    enable password HDyb9X5DtkDtm/mp encrypted
    names
    !
    interface Vlan1
     nameif outside
     security-level 0
     pppoe client vpdn group adsl
     ip address pppoe setroute
    !
    interface Vlan2
     nameif inside
     security-level 100
     ip address 10.0.1.1 255.255.255.0
    !
    interface Ethernet0/0
    !
    interface Ethernet0/1
     switchport access vlan 2
    !
    interface Ethernet0/2
     switchport access vlan 2
    !
    interface Ethernet0/3
     switchport access vlan 2
    !
    interface Ethernet0/4
     switchport access vlan 2
    !
    interface Ethernet0/5
     switchport access vlan 2
    !
    interface Ethernet0/6
     switchport access vlan 2
    !
    interface Ethernet0/7
     switchport access vlan 2
    !
    passwd HDyb9X5DtkDtm/mp encrypted
    boot system disk0:/asa802-k8.bin
    ftp mode passive
    object-group network LAN
     network-object 10.0.1.0 255.255.255.0
    object-group network server
     network-object host 192.168.0.7
     network-object host 192.168.0.88
     network-object host 192.168.0.55
    access-list no_nat extended permit ip object-group LAN object-group server
    access-list nat_acl extended permit ip object-group LAN any
    access-list outside_1_cryptomap extended permit tcp object-group LAN object-grou
    p server eq 211
    access-list outside_1_cryptomap extended permit tcp object-group LAN object-grou
    p server eq 1433
    pager lines 24
    logging enable
    logging asdm informational
    mtu outside 1500
    mtu inside 1500
    icmp unreachable rate-limit 1 burst-size 1
    asdm image disk0:/asdm-602.bin
    no asdm history enable
    arp timeout 14400
    global (outside) 1 interface
    nat (inside) 0 access-list no_nat
    nat (inside) 1 access-list nat_acl
    timeout xlate 3:00:00
    timeout conn 1:00:00 half-closed 0:10:00 udp 0:02:00 icmp 0:00:02
    timeout sunrpc 0:10:00 h323 0:05:00 h225 1:00:00 mgcp 0:05:00 mgcp-pat 0:05:00
    timeout sip 0:30:00 sip_media 0:02:00 sip-invite 0:03:00 sip-disconnect 0:02:00
    timeout uauth 0:05:00 absolute
    dynamic-access-policy-record DfltAccessPolicy
    aaa authentication http console LOCAL
    aaa authentication ssh console LOCAL
    http server enable
    http 0.0.0.0 0.0.0.0 inside
    no snmp-server location
    no snmp-server contact
    snmp-server enable traps snmp authentication linkup linkdown coldstart
    crypto ipsec transform-set ESP-DES-MD5 esp-des esp-md5-hmac
    crypto map outside_map 1 match address outside_1_cryptomap
    crypto map outside_map 1 set peer ***
    crypto map outside_map 1 set transform-set ESP-DES-MD5
    crypto map outside_map interface outside
    crypto isakmp enable outside
    crypto isakmp policy 10
     authentication pre-share
     encryption des
     hash md5
     group 2
     lifetime 86400
    crypto isakmp policy 65535
     authentication pre-share
     encryption 3des
     hash sha
     group 2
     lifetime 86400
    no crypto isakmp nat-traversal
    telnet 0.0.0.0 0.0.0.0 inside
    telnet timeout 5
    ssh 0.0.0.0 0.0.0.0 outside
    ssh timeout 5
    console timeout 0
    vpdn group adsl request dialout pppoe
    vpdn group adsl localname 076900557382
    vpdn group adsl ppp authentication pap
    vpdn username 076900557382 password ********* store-local
    dhcpd dns 202.96.128.166 202.96.128.86
    !
    dhcpd address 10.0.1.10-10.0.1.128 inside
    dhcpd enable inside
    !

    threat-detection basic-threat
    threat-detection statistics access-list
    !
    class-map inspection_default
     match default-inspection-traffic
    !
    !
    policy-map type inspect dns preset_dns_map
     parameters
      message-length maximum 512
    policy-map global_policy
     class inspection_default
      inspect dns preset_dns_map
      inspect ftp
      inspect h323 h225
      inspect h323 ras
      inspect netbios
      inspect rsh
      inspect rtsp
      inspect skinny
      inspect esmtp
      inspect sqlnet
      inspect sunrpc
      inspect tftp
      inspect sip
      inspect xdmcp
      inspect icmp
    !
    service-policy global_policy global
    username 3610 password S/bwGIFg810AsVgn encrypted privilege 15
    tunnel-group *** type ipsec-l2l
    tunnel-group *** ipsec-attributes
     pre-shared-key *
    prompt hostname context
    Cryptochecksum:2167a23681f222e9cf8f49275f4ec74d
    : end


    VPN学的不多,现学的。但既然此配置能正常用,我在试验时也没改动太多,就换了下内网地址和连接外网方式,正常联通Internet后,VPN却未能联通。
    是保存配置的时候某些东西没能保存出来么?RSA密钥对好像是这样的,不过上面配置里用的是预共享密钥,应该与这个无关吧。不过配置里面有aaa认证,那东西不知道是否引用了RSA密钥。
    还是其他的原因呢?
  2. A
    VPN不是简单保存配置就可以的吧

哪位大神帮忙用crypto库实现一个RSA签名的算法,密钥文件一直有了,填充方式是RSA_PKCS1_PADDING

  1. Q
    我的需求是用密钥文件签名,用公钥文件验签。
    python的代码我已经实现了,已经签名和验签成功。但是c版本的一直搞不定。

    下面是python的代码
    from Crypto.PublicKey import RSA
    from Crypto.Hash import SHA
    from Crypto.Signature import PKCS1_v1_5 as pk
    import base64
    #rsa-sha1签名
    def sha1Sign(key, data = None):
    if data == None:
    return None
    privateKey=RSA.importKey(open(key,'r').read())
    h=SHA.new(data) 
    signer = pk.new(privateKey) 
    signn=signer.sign(h) 
    return base64.b64encode(signn) 

    请帮忙看下用c语言版本怎么实现,python的PKCS1_v1_5 对应crypto库的RSA_PKCS1_PADDING吧。
  2. A
    仅供参考:
    #pragma comment(lib, "crypt32.lib")
    #pragma comment(lib, "advapi32.lib")
    #define _WIN32_WINNT 0x0400
    #include <stdio.h>
    #include <windows.h>
    #include <wincrypt.h>
    #define KEYLENGTH  0x00800000
    void HandleError(char *s);
    //--------------------------------------------------------------------
    //  These additional #define statements are required.
    #define ENCRYPT_ALGORITHM CALG_RC4
    #define ENCRYPT_BLOCK_SIZE 8
    //   Declare the function EncryptFile. The function definition
    //   follows main.
    BOOL EncryptFile(
        PCHAR szSource,
        PCHAR szDestination,
        PCHAR szPassword);
    //--------------------------------------------------------------------
    //   Begin main.
    void main(void) {
        CHAR szSource[100];
        CHAR szDestination[100];
        CHAR szPassword[100];
        printf("Encrypt a file. \n\n");
        printf("Enter the name of the file to be encrypted: ");
        scanf("%s",szSource);
        printf("Enter the name of the output file: ");
        scanf("%s",szDestination);
        printf("Enter the password:");
        scanf("%s",szPassword);
        //--------------------------------------------------------------------
        // Call EncryptFile to do the actual encryption.
        if(EncryptFile(szSource, szDestination, szPassword)) {
            printf("Encryption of the file %s was a success. \n", szSource);
            printf("The encrypted data is in file %s.\n",szDestination);
        } else {
            HandleError("Error encrypting file!");
        }
    } // End of main
    //--------------------------------------------------------------------
    //   Code for the function EncryptFile called by main.
    static BOOL EncryptFile(
        PCHAR szSource,
        PCHAR szDestination,
        PCHAR szPassword)
    //--------------------------------------------------------------------
    //   Parameters passed are:
    //     szSource, the name of the input, a plaintext file.
    //     szDestination, the name of the output, an encrypted file to be
    //         created.
    //     szPassword, the password.
    {
        //--------------------------------------------------------------------
        //   Declare and initialize local variables.
        FILE *hSource;
        FILE *hDestination;
        HCRYPTPROV hCryptProv;
        HCRYPTKEY hKey;
        HCRYPTHASH hHash;
        PBYTE pbBuffer;
        DWORD dwBlockLen;
        DWORD dwBufferLen;
        DWORD dwCount;
        //--------------------------------------------------------------------
        // Open source file.
        if(hSource = fopen(szSource,"rb")) {
            printf("The source plaintext file, %s, is open. \n", szSource);
        } else {
            HandleError("Error opening source plaintext file!");
        }
        //--------------------------------------------------------------------
        // Open destination file.
        if(hDestination = fopen(szDestination,"wb")) {
            printf("Destination file %s is open. \n", szDestination);
        } else {
            HandleError("Error opening destination ciphertext file!");
        }
        //以下获得一个CSP句柄
        if(CryptAcquireContext(
                    &hCryptProv,
                    NULL,               //NULL表示使用默认密钥容器,默认密钥容器名
                    //为用户登陆名
                    NULL,
                    PROV_RSA_FULL,
                    0)) {
            printf("A cryptographic provider has been acquired. \n");
        } else {
            if(CryptAcquireContext(
                        &hCryptProv,
                        NULL,
                        NULL,
                        PROV_RSA_FULL,
                        CRYPT_NEWKEYSET))//创建密钥容器
            {
                //创建密钥容器成功,并得到CSP句柄
                printf("A new key container has been created.\n");
            } else {
                HandleError("Could not create a new key container.\n");
            }
        }
        //--------------------------------------------------------------------
        // 创建一个会话密钥(session key)
        // 会话密钥也叫对称密钥,用于对称加密算法。
        // (注: 一个Session是指从调用函数CryptAcquireContext到调用函数
        //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程)
        //--------------------------------------------------------------------
        // Create a hash object.
        if(CryptCreateHash(
                    hCryptProv,
                    CALG_MD5,
                    0,
                    0,
                    &hHash)) {
            printf("A hash object has been created. \n");
        } else {
            HandleError("Error during CryptCreateHash!\n");
        }
        //--------------------------------------------------------------------
        // 用输入的密码产生一个散列
        if(CryptHashData(
                    hHash,
                    (BYTE *)szPassword,
                    strlen(szPassword),
                    0)) {
            printf("The password has been added to the hash. \n");
        } else {
            HandleError("Error during CryptHashData. \n");
        }
        //--------------------------------------------------------------------
        // 通过散列生成会话密钥
        if(CryptDeriveKey(
                    hCryptProv,
                    ENCRYPT_ALGORITHM,
                    hHash,
                    KEYLENGTH,
                    &hKey)) {
            printf("An encryption key is derived from the password hash. \n");
        } else {
            HandleError("Error during CryptDeriveKey!\n");
        }
        //--------------------------------------------------------------------
        // Destroy the hash object.
        CryptDestroyHash(hHash);
        hHash = NULL;
        //--------------------------------------------------------------------
        //  The session key is now ready.
        //--------------------------------------------------------------------
        // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的,所以被加密的
        // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的
        // 数据长度。
        dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
        //--------------------------------------------------------------------
        // Determine the block size. If a block cipher is used,
        // it must have room for an extra block.
        if(ENCRYPT_BLOCK_SIZE > 1)
            dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
        else
            dwBufferLen = dwBlockLen;
        //--------------------------------------------------------------------
        // Allocate memory.
        if(pbBuffer = (BYTE *)malloc(dwBufferLen)) {
            printf("Memory has been allocated for the buffer. \n");
        } else {
            HandleError("Out of memory. \n");
        }
        //--------------------------------------------------------------------
        // In a do loop, encrypt the source file and write to the destination file.
        do {
            //--------------------------------------------------------------------
            // Read up to dwBlockLen bytes from the source file.
            dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
            if(ferror(hSource)) {
                HandleError("Error reading plaintext!\n");
            }
            //--------------------------------------------------------------------
            // 加密数据
            if(!CryptEncrypt(
                        hKey,           //密钥
                        0,              //如果数据同时进行散列和加密,这里传入一个
                        //散列对象
                        feof(hSource),  //如果是最后一个被加密的块,输入TRUE.如果不是输.
                        //入FALSE这里通过判断是否到文件尾来决定是否为
                        //最后一块。
                        0,              //保留
                        pbBuffer,       //输入被加密数据,输出加密后的数据
                        &dwCount,       //输入被加密数据实际长度,输出加密后数据长度
                        dwBufferLen))   //pbBuffer的大小。
            {
                HandleError("Error during CryptEncrypt. \n");
            }
            //--------------------------------------------------------------------
            // Write data to the destination file.
            fwrite(pbBuffer, 1, dwCount, hDestination);
            if(ferror(hDestination)) {
                HandleError("Error writing ciphertext.");
            }
        } while(!feof(hSource));
        //--------------------------------------------------------------------
        //  End the do loop when the last block of the source file has been
        //  read, encrypted, and written to the destination file.
        //--------------------------------------------------------------------
        // Close files.
        if(hSource)
            fclose(hSource);
        if(hDestination)
            fclose(hDestination);
        //--------------------------------------------------------------------
        // Free memory.
        if(pbBuffer)
            free(pbBuffer);
        //--------------------------------------------------------------------
        // Destroy session key.
        if(hKey)
            CryptDestroyKey(hKey);
        //--------------------------------------------------------------------
        // Destroy hash object.
        if(hHash)
            CryptDestroyHash(hHash);
        //--------------------------------------------------------------------
        // Release provider handle.
        if(hCryptProv)
            CryptReleaseContext(hCryptProv, 0);
        return(TRUE);
    } // End of Encryptfile
    //--------------------------------------------------------------------
    //  This example uses the function HandleError, a simple error
    //  handling function, to print an error message to the standard error
    //  (stderr) file and exit the program.
    //  For most applications, replace this function with one
    //  that does more extensive error reporting.
    void HandleError(char *s) {
        fprintf(stderr,"An error occurred in running the program. \n");
        fprintf(stderr,"%s\n",s);
        fprintf(stderr, "Error number %x.\n", GetLastError());
        fprintf(stderr, "Program terminating. \n");
        exit(1);
    } // End of HandleError

RSA算法如何用辗转相除法求密钥的

  1. Q
    课本里RSA算法写着
    选取2个大素数p,q
    求n=p*q;
    随即选取加密密钥e,使e与(p-1)(q-1)互质
    用辗转相除法计算解密密钥 de=1 mod (p-1)(q-1)
    则 d=1/e mod (p-1)(q-1)

    如de=1 mod 3480
    取e=31
    d=1/e mod 3480=3031

    关键对最后2步不懂,辗转相除法不是用来求最大公约数的吗?
    为什么这里要用辗转相除法,是速度快,还是便于笔算
    d=1/e mod 3480=3031  这步的具体过程是什么
    如果写程序,大概过程是什么


  2. A
    我记得这个问题好像和欧拉公式有关的,具体忘记了(记性比较差)。不好意思啊。

    建议楼主找本《数论》有关的书参考一下吧。我们学的时候用的是机械工业出版社出版的《密码学导引》,讲得很简单,但是翻译质量不太好。

如何把DER编码的数据转成PEM的数据?C++使用OPENSSL的RSA算法加密--PHP来解密

  1. Q
    各位大哥。。。小弟现在碰到一个棘手的问题,描述如下: 

    我用C++写了一个COM组件,这个组件用到了OPENSSL库中RSA算对字符串比如“AAAA”进行公钥加密, 然后打算用PHP来私钥解密

    生成密钥 
    m_pRsa = RSA_generate_key(m_rsa_bits,RSA_F4,NULL,NULL);//公钥指数默认指定为RSA_F4(。。。) 

    //得到公钥 保存
    len = i2d_RSAPublicKey(m_pRsa, &Pt); 
    //得到私钥 保存
    len = i2d_RSAPrivateKey(m_pRsa, &Pt); 

    而这两个函数得到的公钥和私钥是DER编码格式的。。。


    在PHP中,我要使用公钥和私钥,必须是PEM格式的
    http://www.php.net/manual/en/function.openssl-private-decrypt.php


    这样。。。除非我当初保存密钥的时候就用PEM格式来保存。。。或者我能将DER编码格式转换成PEM格式。。。

    这两点目前我都没辙。。。。望有相关经验的大哥能指点小弟一二。。。
  2. A
    回复下!

用C++ with openssl 做的RSA加密 Java 解不了。

  1. Q
    用C++ with openssl 做的RSA加密 Java 解不了。

    但同样的密钥,java加的密,C++倒可以解开的。

    是不是Java的RSA有不同的算法开关?


    参见的JAVA文章:
    http://blog.csdn.net/chaijunkun/article/details/7275632#comments

    有知道原因的高手吗?谢谢。
  2. A
    多半是 padding 方式不一样导致

    http://en.wikipedia.org/wiki/RSA_(algorithm)#Padding_schemes

如何保存密钥文件更安全

  1. Q

    下面是一个进行加密的工具类,加密类会产生一个密钥文件,密钥文件保存到了硬盘文件中,程序中要进行对数据的加解密操作。密钥文件保存在文件,别人也就可以读取密钥文件,获得加密数据的内容。有什么可以安全保存密钥文件的方式么?

     

    public class EncryptUtil {	
    	private static String keyPath = null;
    
    	private static String getKeyPath() {
    		keyPath = "c:\\yhb.des";
    		return keyPath;
    	}
    	
    	/**
    	 * 对称加密-产生密钥<br/>
    	 */
    	public static void generatorKey() {
    		SecretKey key = null;
    		try {
    			// 指定算法,这里为DES;如果想用Blowfish算法,则用getInstance("Blowfish")
    			// BouncyCastle基本上支持所有通用标准算法
    			KeyGenerator keygen = KeyGenerator.getInstance("DES");
    			// 指定密钥长度,长度越高,加密强度越大
    			keygen.init(56);
    			// 产生密钥
    			key = keygen.generateKey();
    			// 构造输出文件,这里的目录是动态的,根据用户名称来构造目录
    			ObjectOutputStream keyFile = new ObjectOutputStream(
    					new FileOutputStream(getKeyPath()));
    			keyFile.writeObject(key);
    			keyFile.close();
    		} catch (NoSuchAlgorithmException e5) {
    			e5.printStackTrace();	
    			System.exit(0);
    		} catch (IOException e4) {
    			e4.printStackTrace();
    			System.exit(0);
    		}
    	}
    	
    	/**
    	 * 对称加密-读取密钥.<br/>
    	 */
    	private static SecretKey getSecretKey() {
    		// 从密钥文件中读密钥
    		SecretKey key = null;
    		try {
    			ObjectInputStream keyFile = new ObjectInputStream(
    					new FileInputStream(getKeyPath()));
    			key = (SecretKey) keyFile.readObject();
    			keyFile.close();
    		} catch (FileNotFoundException ey1) {
    			e1.printStackTrace();
    			System.exit(0);
    		} catch (Exception ey2) {
    			e2.printStackTrace();
    		}
    		return key;
    	}
    
    	/**
    	 * 加密文本信息.<br/>
    	 */
    	public static String encrypt(String encryptStr) {
    		SecretKey key = getSecretKey();
    		Cipher cipher = null;
    		try {
    			// 设置算法,应该与加密时的设置一样
    			cipher = Cipher.getInstance("DES");
    			// 设置解密模式
    			cipher.init(Cipher.ENCRYPT_MODE, key);
    		} catch (Exception ey3) {
    			ey3.printStackTrace();
    		}
    		byte[] data = null;
    		try {
    			data = cipher.doFinal(encryptStr.getBytes());
    		} catch (IllegalBlockSizeException e) {
    			e.printStackTrace();
    		} catch (BadPaddingException e) {
    			e.printStackTrace();
    		}
    		encryptStr = Base64.encodeBase64String(data);
    		return encryptStr;
    	}
    	
    	/**
    	 * 解密文本信息.<br/>
    	 */
    	public static String decrypt(String decryptStr) {
    		SecretKey key = getSecretKey();
    		// 用key产生Cipher
    		Cipher cipher = null;
    		try {
    			// 设置算法,应该与加密时的设置一样
    			cipher = Cipher.getInstance("DES");
    			// 设置解密模式
    			cipher.init(Cipher.DECRYPT_MODE, key);
    		} catch (Exception ey3) {
    			ey3.printStackTrace();
    			System.exit(0);
    		}
    		byte[] data = Base64.decodeBase64(decryptStr);
    		try {
    			data = cipher.doFinal(data);
    		} catch (IllegalBlockSizeException e) {
    			e.printStackTrace();
    		} catch (BadPaddingException e) {
    			e.printStackTrace();
    		}
    		decryptStr = new String(data);
    		return decryptStr;
    	}	
    }

     

  2. A
    为什么不用RSA 那样更安全.
    换个角度
      你的DES密钥文件 存储在服务器端 应该很安全了.