IOS RSA加密解密

背景介绍:

服务器在传输数据前先进行RSA加密,然后在手机端进行RSA解密。


开发任务:

IOS客户端进行RSA解密


已知数据:

.net仅仅提供了公钥和私钥,但是格式为XML格式。格式如下:

 公钥!!加密
private static string publickey = @"<RSAKeyValue><Modulus>loChDDauMkcVdcentrn123EttwW66zx8hcPQmSu3yaWKq3q7kCFhnbQv4+MfylbzekpweH8896WqDPNtTl+gIE6UCJckHXmGspJI9OXZ7zAtLVMB9nDoLhBeEqpNBC93ACkNyI29VN6YvqnVuIrxsputcb5MBcb4slmVeus6668=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";


 私钥!!解密
private static string privatekey = @"<RSAKeyValue><Modulus>loChDDauMkcVdcentrn0SvEttwW66zx8hcPQmSu3yaWKq3q7kCFhnbQv4+MfylbzekpweHcziwWqDPNtTl+gIE6UCJckHXmGspJI9OXZ7zAtLVMB9nDoLhBeEqpNBC93ACkNyI29VN6YtyuVuIrxsputcb5MBcb4slmVeus2q5M=</Modulus><Exponent>AQAB</Exponent><P>0UENxry9MzrOo/tZboOiOLh8Z+7dUUgQqhAeBuR31Or4S/88b2A+HCCjwjpSqlV6eX13kJOoD+XNCBnZdr3+yw==</P><Q>uB+mtbKnAf6JcoRyCwIMs2S/KGU0IB53boj4KKSwsb/ffhg12346saekETWuRN8Rse5q8ExcFUmxMO7ZmYllWQ==</Q><DP>AjGLYmzyEspoBiIJYvYwSiXs7+36FfMKca3vkqTseKfp6GoJiSVaIVNaRBv2Z+CzgviEu1hA58HB73bN58fAFw==</DP><DQ>ont7+JghfUcMMDzlDwXOA3mCn7k/mKCKMMc6h1Negl2acoIXtusicihIRs+ibDCWQvjs8gXQtRCFB3OgHzf6cQ==</DQ><InverseQ>PFnyOHfoeraI+n6325ddKgIS6kY5ZWuguqmI+66XFZn+8Pq4gTIpXFhXZFBH/SYyNhWB2sOi94lhfdWcOwPX4A==</InverseQ><D>JUbx3M0UY2ag5Z3QqB0x6XgIOytjq009iIJCQhYGfR8QFD4fg+kIvR96tyaz4pGb19/lMKlRrm72OiP3IHDl/4kXmA7PUY4d3LoJTsXCrnJNQrPWD4DLs3iFpYWgymDqRFuVBv06OWjewXiEFDCybnlie6CahmL0q4EebYgIOTk=</D></RSAKeyValue>";


解决方案:

步骤一:XML-->PEM(参考http://bbs.csdn.net/topics/390913872),可以找.net帮忙转换

私钥:

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);
}


公钥:

public static String ExportPublicKeyToPEMFormat(RSACryptoServiceProvider csp)
{
    TextWriter outputStream = new StringWriter();


    var parameters = csp.ExportParameters(false);
    using (var stream = new MemoryStream())
    {
        var writer = new BinaryWriter(stream);
        writer.Write((byte)0x30); // SEQUENCE
        using (var innerStream = new MemoryStream())
        {
            var innerWriter = new BinaryWriter(innerStream);
            EncodeIntegerBigEndian(innerWriter, new byte[] { 0x00 }); // Version
            EncodeIntegerBigEndian(innerWriter, parameters.Modulus);
            EncodeIntegerBigEndian(innerWriter, parameters.Exponent);


            //All Parameter Must Have Value so Set Other Parameter Value Whit Invalid Data  (for keeping Key Structure  use "parameters.Exponent" value for invalid data)
            EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.D
            EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.P
            EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.Q
            EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.DP
            EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.DQ
            EncodeIntegerBigEndian(innerWriter, parameters.Exponent); // instead of parameters.InverseQ


            var length = (int)innerStream.Length;
            EncodeLength(writer, length);
            writer.Write(innerStream.GetBuffer(), 0, length);
        }


        var base64 = Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length).ToCharArray();
        outputStream.WriteLine("-----BEGIN PUBLIC KEY-----");
        // Output as Base64 with lines chopped at 64 characters
        for (var i = 0; i < base64.Length; i += 64)
        {
            outputStream.WriteLine(base64, i, Math.Min(64, base64.Length - i));
        }
        outputStream.WriteLine("-----END PUBLIC KEY-----");


        return outputStream.ToString();


    }
}


private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bool forceUnsigned = true)
{
    stream.Write((byte)0x02); // INTEGER
    var prefixZeros = 0;
    for (var i = 0; i < value.Length; i++)
    {
        if (value[i] != 0) break;
        prefixZeros++;
    }
    if (value.Length - prefixZeros == 0)
    {
        EncodeLength(stream, 1);
        stream.Write((byte)0);
    }
    else
    {
        if (forceUnsigned && value[prefixZeros] > 0x7f)
        {
            // Add a prefix zero to force unsigned if the MSB is 1
            EncodeLength(stream, value.Length - prefixZeros + 1);
            stream.Write((byte)0);
        }
        else
        {
            EncodeLength(stream, value.Length - prefixZeros);
        }
        for (var i = prefixZeros; i < value.Length; i++)
        {
            stream.Write(value[i]);
        }
    }
}


private static void EncodeLength(BinaryWriter stream, int length)
{
    if (length < 0) throw new ArgumentOutOfRangeException("length", "Length must be non-negative");
    if (length < 0x80)
    {
        // Short form
        stream.Write((byte)length);
    }
    else
    {
        // Long form
        var temp = length;
        var bytesRequired = 0;
        while (temp > 0)
        {
            temp >>= 8;
            bytesRequired++;
        }
        stream.Write((byte)(bytesRequired | 0x80));
        for (var i = bytesRequired - 1; i >= 0; i--)
        {
            stream.Write((byte)(length >> (8 * i) & 0xff));
        }
    }
}


经过转换,我们可以得到PEM格式的公钥和私钥,格式如下:

公钥:

-----BEGIN PUBLIC KEY—— 

MIGqAgEAAoGBAJaAoQw2rjJHFXXHp7a59ErxLbcFuus8fIXD0Jkrt8mliqt6u5Ah YZ20L+PjH8pW83pKcHh3M4sFqgzzbU5foCBOlAiXJB15hrKSSPTl2e8wLS1TAfZw 6C4QXhKqTQQvdwApDciNvVTemL6p1biK8bKbrXG+TAXG+LJZlXrrNquTAgMBAAEC 

AwEAAQIDAQABAgMBAAECAwEAAQIDAQABAgMBAAE= 

-----END PUBLIC KEY——



私钥:

-----BEGIN RSA PRIVATE KEY-----

MIICXAIBAAKBgQCWgKEMNq4yRxV1x6e2ufRK8S23BbrrPHyFw9CZK7fJpYqreruQ

IWGdtC/j4x/KVvN6SnB4dzOLBaoM821OX6AgTpQIlyQdeYaykkj05dnvMC0tUwH2

cOguEF4Sqk0EL3cAKQ3Ijb1U3pi+qdW4ivGym61xvkwFxviyWZV66zarkwIDAQAB

AoGAJUbx3M0UY2ag5Z3QqB0x6XgIOytjq009iIJCQhYGfR8QFD4fg+kIvR96tyaz

4pGb19/lMKlRrm72OiP3IHDl/4kXmA7PUY4d3LoJTsXCrnJNQrPWD4DLs3iFpYWg

ymDqRFuVBv06OWjewXiEFDCybnlie6CahmL0q4EebYgIOTkCQQDRQQ3GvL0zOs6j

+1lug6I4uHxn7t1RSBCqEB4G5HfU6vhL/zxvYD4cIKPCOlKqVXp5fXeQk6gP5c0I

Gdl2vf7LAkEAuB+mtbKnAf6JcoRyCwIMs2S/KGU0IB53boj4KKSwsb/ffhg2ty36

saekETWuRN8Rse5q8ExcFUmxMO7ZmYllWQJAAjGLYmzyEspoBiIJYvYwSiXs7+36

FfMKca3vkqTseKfp6GoJiSVaIVNaRBv2Z+CzgviEu1hA58HB73bN58fAFwJBAKJ7

e/iYIX1HDDA85Q8FzgN5gp+5P5igijDHOodTXoJdmnKCF7brInIoSEbPomwwlkL4

7PIF0LUQhQdzoB83+nECQDxZ8jh36Hq2iPp37yInXSoCEupGOWVroLqpiPuulxWZ

/vD6uIEyKVxYV2RQR/0mMjYVgdrDoveJBkx1nDsD1+A=

-----END RSA PRIVATE KEY——


步骤二:生成私钥pem文件

1.打开终端,输入  “openssl genrsa -out private_key.pem 1024"

2.打开Finder,在【这台Mac】查找".pem",应该可以看到 private_key.pem。

3.选中private_key.pem , 选择用文本编辑的方式打开

4.将里面的内容替换成你的私钥


步骤三:生成公钥pem文件

1.在终端输入

openssl rsa -in private_key.pem -pubout -out public_key.pem

2.打开Finder,在【这台Mac】查找".pem",应该可以看到 public_key.pem.

3.选中public_key.pem , 选择用文本编辑的方式打开

4.将里面的内容替换成你的公钥


步骤四:demo测试(参考:https://github.com/jslim89/RSA-objc)

打开demo,会有报错,

step01:添加必要的文件(把工程里红色的文件加进来)

step02:全局替换:把”#include<openssl/“  替换成 ”#include <

step03:全局替换:把”# include <openssl/“  替换成 ”#include <“


步骤五:代码接入到自己的项目



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值