配色: 字号:
.net core中使用openssl的公钥私钥进行加解密
2016-11-04 | 阅:  转:  |  分享 
  
.netcore中使用openssl的公钥私钥进行加解密



这篇博文分享的是C#中使用OpenSSL的公钥加密/私钥解密一文中的解决方法在.netcore中的改进。之前的博文针对的是.NETFramework,加解密用的是RSACryptoServiceProvider。虽然在corefx(.NETCoreFramework)中也有RSACryptoServiceProvider,但它目前只支持Windows,不能跨平台。



之前的newRSACryptoServiceProvider();代码在mac上运行,会报下面的错误:



System.PlatformNotSupportedException:Operationisnotsupportedonthisplatform.

atSystem.Security.Cryptography.RSACryptoServiceProvider..ctor()

要解决这个问题,需要改用System.Security.Cryptography.RSA.Create()工厂方法,使用它之后,在Windows上创建的是System.Security.Cryptography.RSACng的实例,在Mac与Linux上创建的是System.Security.Cryptography.RSAOpenSsl的实例,它们都继承自System.Security.Cryptography.RSA抽象类。



使用了RSA.Create()之后,带来了一个问题,RSA中没有RSACryptoServiceProvider中的以下2个签名的加解密方法。



publicbyte[]Encrypt(byte[]rgb,boolfOAEP);

publicbyte[]Decrypt(byte[]rgb,boolfOAEP);

只有



publicabstractbyte[]Encrypt(byte[]data,RSAEncryptionPaddingpadding);

publicabstractbyte[]Decrypt(byte[]data,RSAEncryptionPaddingpadding);

调用时它们时需要传递RSAEncryptionPadding类型的参数值:







但对于openssl生成的公钥私钥不知道选择哪种RSAEncryptionPadding,只能采取笨方法——一个一个试试,试出来的结果是RSAEncryptionPadding.Pkcs1。



openssl的公钥与私钥是在Mac上通过下面的2个命令生成的:



opensslgenrsa-outrsa_1024_priv.pem102

opensslrsa-pubout-inrsa_1024_priv.pem-outrsa_1024_pub.peml

(注:一定要用openssl命令,用ssh-keygen-trsa命令生成的公钥私钥是不行的)



修改这两个地方(RSA.Create与RSAEncryptionPadding.Pkcs1)之后,就可以在.netcore上使用openssl的公钥私钥进行加解密了,以下是测试时所用的完整代码(.netcore控制台程序)。经测试,在Windows,macOS,LinuxUbuntu上都能成功进行加解密。



Program.cs



复制代码

usingSystem;

usingSystem.IO;

usingSystem.Security.Cryptography;

usingSystem.Text;



namespaceTryRsa

{

publicclassProgram

{

//opensslgenrsa-outrsa_1024_priv.pem1024

privatestaticreadonlystring_privateKey=@"MIICXgIBAAKBgQC0xP5HcfThSQr43bAMoopbzcCyZWE0xfUeTA4Nx4PrXEfDvybJ

EIjbU/rgANAty1yp7g20J7+wVMPCusxftl/d0rPQiCLjeZ3HtlRKld+9htAZtHFZ

osV29h/hNE9JkxzGXstaSeXIUIWquMZQ8XyscIHhqoOmjXaCv58CSRAlAQIDAQAB

AoGBAJtDgCwZYv2FYVk0ABw6F6CWbuZLUVykks69AG0xasti7Xjh3AximUnZLefs

iuJqg2KpRzfv1CM+Cw5cp2GmIVvRqq0GlRZGxJ38AqH9oyUa2m3TojxWapY47zye

PYEjWwRTGlxUBkdujdcYj6/dojNkm4azsDXl9W5YaXiPfbgJAkEA4rlhSPXlohDk

FoyfX0v2OIdaTOcVpinv1jjbSzZ8KZACggjiNUVrSFV3Y4oWom93K5JLXf2mV0Sy

80mPR5jOdwJBAMwciAk8xyQKpMUGNhFX2jKboAYY1SJCfuUnyXHAPWeHp5xCL2UH

tjryJp/Vx8TgsFTGyWSyIE9R8hSup+32rkcCQBe+EAkC7yQ0np4Z5cql+sfarMMm

4+Z9t8b4N0a+EuyLTyfs5Dtt5JkzkggTeuFRyOoALPJP0K6M3CyMBHwb7WsCQQCi

TM2fCsUO06fRQu8bO1A1janhLz3K0DU24jw8RzCMckHE7pvhKhCtLn+n+MWwtzl/

L9JUT4+BgxeLepXtkolhAkEA2V7er7fnwww.baiyuewang.netEuL0+kKIjmOm5F3kvMIDh9YC1JwLGSvu

1fnzxK34QwSdxgQRF1dfIKJw73lClQpHZfQxL/2XRG8IoA==".Replace("\n","");



//opensslrsa-pubout-inrsa_1024_priv.pem-outrsa_1024_pub.pem

privatestaticreadonlystring_publicKey=@"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0xP5HcfThSQr43bAMoopbzcCy

ZWE0xfUeTA4Nx4PrXEfDvybJEIjbU/rgANAty1yp7g20J7+wVMPCusxftl/d0rPQ

iCLjeZ3HtlRKld+9htAZtHFZosV29h/hNE9JkxzGXstaSeXIUIWquMZQ8XyscIHh

qoOmjXaCv58CSRAlAQIDAQAB".Replace("\n","");



publicstaticvoidMain(string[]args)

{

varplainText="cnblogs.com";



//Encrypt

RSArsa=CreateRsaFromPublicKey(_publicKey);

varplainTextBytes=Encoding.UTF8.GetBytes(plainText);

varcipherBytes=rsa.Encrypt(plainTextBytes,RSAEncryptionPadding.Pkcs1);

varcipher=Convert.ToBasewww.wang027.com64String(cipherBytes);

Console.WriteLine($"{nameof(cipher)}:{cipher}");



//Decrypt

rsa=CreateRsaFromPrivateKey(_privateKey);

cipherBytes=System.Convert.FromBase64String(cipher);

plainTextBytes=rsa.Decrypt(cipherBytes,RSAEncryptionPadding.Pkcs1);

plainText=Encoding.UTF8.GetString(plainTextBytes);

Console.WriteLine($"{nameof(plainText)}:{plainText}");

}privatestaticRSACreateRsaFromPrivateKey(stringprivateKey)

{

varprivateKeyBits=System.Convert.FromBase64String(privateKey);

varrsa=RSA.Create();

varRSAparams=newRSAParameters();



using(varbinr=newBinaryReader(newMemoryStream(privateKeyBits)))

{

bytebt=0;

ushorttwobytes=0;

twobytes=binr.ReadUInt16();

if(twobytes==0x8130)

binr.ReadByte();

elseif(twobytes==0x8230)

binr.ReadInt16();

else

thrownewException("Unexpectedvaluereadbinr.ReadUInt16()");



twobytes=binr.ReadUInt16();

if(twobytes!=0x0102)

thrownewException("Unexpectedversion");



bt=binr.ReadByte();

if(bt!=0x00)

thrownewException("Unexpectedvaluereadbinr.ReadByte()");



RSAparams.Modulus=binr.ReadBytes(GetIntegerSize(binr));

RSAparams.Exponent=binr.ReadBytes(GetIntegerSize(binr));

RSAparams.D=binr.ReadBytes(GetIntegerSize(binr));

RSAparams.P=binr.ReadBytes(GetIntegerSize(binr));

RSAparams.Q=binr.ReadBytes(GetIntegerSize(binr));

RSAparams.DP=binr.ReadBytes(GetIntegerSize(binr));

RSAparams.DQ=binr.ReadBytes(GetIntegerSize(binr));

RSAparams.InverseQ=binr.ReadBytes(GetIntegerSize(binr));

}



rsa.ImportParameters(RSAparams);

returnrsa;

}



privatestaticintGetIntegerSize(BinaryReaderbinr)

{

bytebt=0;

bytelowbyte=0x00;

bytehighbyte=0x00;

intcount=0;

bt=binr.ReadByte();

if(bt!=0x02)

return0;

bt=binr.ReadByte();



if(bt==0x81)

count=binr.ReadByte();

else

if(bt==0x82)

{

highbyte=binr.ReadByte();

lowbyte=binr.ReadByte();

byte[]modint={lowbyte,highbyte,0x00,0x00};

count=BitConverter.ToInt32(modint,0);

}

else

{

count=bt;

}



while(binr.ReadByte()==0x00)

{

count-=1;

}

binr.BaseStream.Seek(-1,SeekOrigin.Current);

returncount;

}



privatestaticRSACreateRsaFromPublicKey(stringpublicKeyString)

{

byte[]SeqOID={0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00};

byte[]x509key;

byte[]seq=newbyte[15];

intx509size;



x509key=Convert.FromBase64String(publicKeyString);

x509size=x509key.Length;



using(varmem=newMemoryStream(x509key))

{

using(varbinr=newBinaryReader(mem))

{

bytebt=0;

ushorttwobytes=0;



twobytes=binr.ReadUInt16();

if(twobytes==0x8130)

binr.ReadByte();

elseif(twobytes==0x8230)

binr.ReadInt16();

else

returnnull;



seq=binr.ReadBytes(15);

if(!CompareBytearrays(seq,SeqOID))

returnnull;



twobytes=binr.ReadUInt16();

if(twobytes==0x8103)

binr.ReadByte();

elseif(twobytes==0x8203)

binr.ReadInt16();

else

returnnull;



bt=binr.ReadByte();

if(bt!=0x00)

returnnull;



twobytes=binr.ReadUInt16();

if(twobytes==0x8130)

binr.ReadByte();

elseif(twobytes==0x8230)

binr.ReadInt16();

else

returnnull;



twobytes=binr.ReadUInt16();

bytelowbyte=0x00;

bytehighbyte=0x00;



if(twobytes==0x8102)

lowbyte=binr.ReadByte();

elseif(twobytes==0x8202)

{

highbyte=binr.ReadByte();

lowbyte=binr.ReadByte();

}

else

returnnull;

byte[]modint={lowbyte,highbyte,0x00,0x00};

intmodsize=BitConverter.ToInt32(modint,0);



intfirstbyte=binr.PeekChar();

if(firstbyte==0x00)

{

binr.ReadByte();

modsize-=1;

}



byte[]modulus=binr.ReadBytes(modsize);



if(binr.ReadByte()!=0x02)

returnnull;

intexpbytes=(int)binr.ReadByte();

byte[]exponent=binr.ReadBytes(expbytes);



varrsa=RSA.Create();

varrsaKeyInfo=newRSAParameters

{

Modulus=modulus,

Exponent=exponent

};

rsa.ImportParameters(rsaKeyInfo);

returnrsa;

}



}

}



privatestaticboolCompareBytearrays(byte[]a,byte[]b)

{

if(a.Length!=b.Length)

returnfalse;

inti=0;

foreach(bytecina)

{

if(c!=b[i])

returnfalse;

i++;

}

returntrue;

}

}

}

复制代码

project.json



复制代码

{

"version":"1.0.0-",

"buildOptions":{

"emitEntryPoint":true

},



"dependencies":{

"Microsoft.NETCore.App":{

"type":"platform",

"version":"1.1.0-preview1-001100-00"

},

"System.Security.Cryptography.Algorithms":"4.3.0-preview1-24530-04"

},



"frameworks":{

"netcoreapp1.1":{

"imports":"dnxcore50"

}

}

}

献花(0)
+1
(本文系thedust79首藏)