zoukankan      html  css  js  c++  java
  • windows phone 从cer中提出公钥然后再RSA加密的问题

    首先.net平台SDK提供的RSA加密由于加了随机数,所以在解密的时候必须也要在.net平台解密。如果要跟java平台这样的跨平台解密就会出问题。

    参考文档:http://blog.csdn.net/lubiaopan/article/details/6233517   

    其中提到两种解决方案,一种是在.net平台是用BigInteger 来实现,另外一种是java端也用添加随机数的方式解决。

    我下面主要写下用在.net平台用BigInteger 来实现的方式。

    第一步:提取cer文件中的公钥

    using (var cerStream = App.GetResourceStream(new Uri("/xxxx;component/cert.der", UriKind.Relative)).Stream)
                {
                    byte[] cerBuffer = new byte[cerStream.Length];
                    cerStream.Read(cerBuffer, 0, cerBuffer.Length);
                    System.Security.Cryptography.X509Certificates.X509Certificate cer = new System.Security.Cryptography.X509Certificates.X509Certificate(cerBuffer);
                    string publickkey = cer.GetPublicKeyString();
                }

    第二步:将提取的公钥转换成能够进行RSA加密的字节流。
    这里需要用到X509PublicKeyParser类,这个类windows phone SDK本身不提供,这里贴出该类的实现代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    
    namespace System.Security.Cryptography
    {
    
        /// <summary>
        /// Summary description for AbstractAsn1Container.
        /// </summary>
        internal abstract class AbstractAsn1Container
        {
            private int offset;
            private byte[] data;
            private byte tag;
    
    
            internal protected AbstractAsn1Container(byte[] abyte, int i, byte tag)
            {
                this.tag = tag;
                if (abyte[i] != tag)
                {
                    throw new Exception("Invalid data. The tag byte is not valid");
                }
                int length = DetermineLength(abyte, i + 1);
                int bytesInLengthField = DetermineLengthLen(abyte, i + 1);
                int start = i + bytesInLengthField + 1;
                this.offset = start + length;
                data = new byte[length];
                Array.Copy(abyte, start, data, 0, length);
            }
    
    
            internal int Offset
            {
                get
                {
                    return offset;
                }
            }
    
    
            internal byte[] Bytes
            {
                get
                {
                    return this.data;
                }
            }
    
    
            internal protected virtual int DetermineLengthLen(byte[] abyte0, int i)
            {
                int j = abyte0[i] & 0xff;
                switch (j)
                {
                    case 129:
                        return 2;
    
    
                    case 130:
                        return 3;
    
    
                    case 131:
                        return 4;
    
    
                    case 132:
                        return 5;
    
    
                    case 128:
                    default:
                        return 1;
                }
            }
    
    
            internal protected virtual int DetermineLength(byte[] abyte0, int i)
            {
                int j = abyte0[i] & 0xff;
                switch (j)
                {
                    case 128:
                        return DetermineIndefiniteLength(abyte0, i);
    
    
                    case 129:
                        return abyte0[i + 1] & 0xff;
    
    
                    case 130:
                        int k = (abyte0[i + 1] & 0xff) << 8;
                        k |= abyte0[i + 2] & 0xff;
                        return k;
    
    
                    case 131:
                        int l = (abyte0[i + 1] & 0xff) << 16;
                        l |= (abyte0[i + 2] & 0xff) << 8;
                        l |= abyte0[i + 3] & 0xff;
                        return l;
                }
                return j;
            }
    
    
            internal protected virtual int DetermineIndefiniteLength(byte[] abyte0, int i)
            {
                if ((abyte0[i - 1] & 0xff & 0x20) == 0)
                    throw new Exception("Invalid indefinite length.");
                int j = 0;
                int k;
                int l;
                for (i++; abyte0[i] != 0 && abyte0[i + 1] != 0; i += 1 + k + l)
                {
                    j++;
                    k = DetermineLengthLen(abyte0, i + 1);
                    j += k;
                    l = DetermineLength(abyte0, i + 1);
                    j += l;
                }
    
    
                return j;
            }
    
    
    
    
        }
    
    
        internal class IntegerContainer : AbstractAsn1Container
        {
            internal IntegerContainer(byte[] abyte, int i)
                : base(abyte, i, 0x2)
            {
            }
        }
    
    
        internal class SequenceContainer : AbstractAsn1Container
        {
            internal SequenceContainer(byte[] abyte, int i)
                : base(abyte, i, 0x30)
            {
            }
        }
    
    
        public class X509PublicKeyParser
        {
            public static RSAParameters GetRSAPublicKeyParameters(byte[] bytes)
            {
                return GetRSAPublicKeyParameters(bytes, 0);
            }
    
    
            public static RSAParameters GetRSAPublicKeyParameters(byte[] bytes, int i)
            {
                SequenceContainer seq = new SequenceContainer(bytes, i);
                IntegerContainer modContainer = new IntegerContainer(seq.Bytes, 0);
                IntegerContainer expContainer = new IntegerContainer(seq.Bytes, modContainer.Offset);
                return LoadKeyData(modContainer.Bytes, 0, modContainer.Bytes.Length, expContainer.Bytes, 0, expContainer.Bytes.Length);
            }
    
    
            public static RSAParameters GetRSAPublicKeyParameters(X509Certificate cert)
            {
                return GetRSAPublicKeyParameters(cert.GetPublicKey(), 0);
            }
    
    
            private static RSAParameters LoadKeyData(byte[] abyte0, int i, int j, byte[] abyte1, int k, int l)
            {
                byte[] modulus = null;
                byte[] publicExponent = null;
                for (; abyte0[i] == 0; i++)
                    j--;
    
    
                modulus = new byte[j];
                Array.Copy(abyte0, i, modulus, 0, j);
                int i1 = modulus.Length * 8;
                int j1 = modulus[0] & 0xff;
                for (int k1 = j1 & 0x80; k1 == 0; k1 = j1 << 1 & 0xff)
                    i1--;
    
    
                if (i1 < 256 || i1 > 4096)
                    throw new Exception("Invalid RSA modulus size.");
                for (; abyte1[k] == 0; k++)
                    l--;
    
    
                publicExponent = new byte[l];
                Array.Copy(abyte1, k, publicExponent, 0, l);
                RSAParameters p = new RSAParameters();
                p.Modulus = modulus;
                p.Exponent = publicExponent;
                return p;
            }
        }
    }

    然后是用X509PublicKeyParser来转换公钥

      System.Security.Cryptography.RSAParameters RSAKeyInfo;
                using (var cerStream = App.GetResourceStream(new Uri("/xxxx;component/cert.der", UriKind.Relative)).Stream)
                {
                    byte[] cerBuffer = new byte[cerStream.Length];
                    cerStream.Read(cerBuffer, 0, cerBuffer.Length);
                    System.Security.Cryptography.X509Certificates.X509Certificate cer = new System.Security.Cryptography.X509Certificates.X509Certificate(cerBuffer);
                    RSAKeyInfo = X509PublicKeyParser.GetRSAPublicKeyParameters(cer.GetPublicKey());
                }

    第三步:使用BigInteger来加密数据,这里有一个BigInteger开源类库http://www.codeproject.com/Articles/2728/C-BigInteger-Class

     BigInteger bi_e = new BigInteger(RSAKeyInfo.Exponent);
                BigInteger bi_n = new BigInteger(RSAKeyInfo.Modulus);
                BigInteger bi_data = new BigInteger(System.Text.Encoding.UTF8.GetBytes("123456789"));
                BigInteger bi_encrypted = bi_data.modPow(bi_e, bi_n);
                //rsa加密后的Base64字符串
                string rsaEncryptString = Convert.ToBase64String(bi_encrypted.getBytes());

    rsaEncryptString就是加密后得到的字符串。

  • 相关阅读:
    MySQL配置文件mysql.ini参数详解、MySQL性能优化
    破解许可
    mysql本地可以访问 网络不能访问
    解决远程连接mysql很慢的方法(mysql_connect 打开连接慢)
    MYSQL数据库如何赋予远程某个IP访问权限
    linux网络编程 no route to host 解决方案
    CentOS添加路由表
    CentOS安装zip unzip命令
    Centos7下的systemctl命令与service和chkconfig
    header头参数不能带下划线
  • 原文地址:https://www.cnblogs.com/dagehaoshuang/p/3023759.html
Copyright © 2011-2022 走看看