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就是加密后得到的字符串。

 

 

 

你可能感兴趣的:(windows phone)