.NET에서 PEM RSA 개인 키를 읽는 방법
-
04-07-2019 - |
문제
나는있다 RSA
개인 키 PEM
형식, .NET에서 그것을 읽고 인스턴스화하는 간단한 방법이 있습니까? RSACryptoServiceProvider
해당 공개 키와 암호화 된 데이터를 암호화하려면?
해결책
고마워요. 누구나 관심이있는 경우 바운시 캐슬 트릭을했는데, 내 편과 문서의 지식 부족으로 인해 시간이 걸렸습니다. 이것은 코드입니다.
var bytesToDecrypt = Convert.FromBase64String("la0Cz.....D43g=="); // string to decrypt, base64 encoded
AsymmetricCipherKeyPair keyPair;
using (var reader = File.OpenText(@"c:\myprivatekey.pem")) // file containing RSA PKCS1 private key
keyPair = (AsymmetricCipherKeyPair) new PemReader(reader).ReadObject();
var decryptEngine = new Pkcs1Encoding(new RsaEngine());
decryptEngine.Init(false, keyPair.Private);
var decrypted = Encoding.UTF8.GetString(decryptEngine.ProcessBlock(bytesToDecrypt, 0, bytesToDecrypt.Length));
다른 팁
Bouncycastle과 같은 제 3 자 코드를 사용하지 않고 RSA 개인 키를 쉽게 가져 오는 것과 관련하여, 나는 대답이 "개인 키의 PEM이 아니라"라고 생각합니다.
그러나 Simone이 위에서 언급 한 것처럼 개인 키 (*.key)의 PEM과 해당 키 (*.crt)를 사용하여 인증서 파일을*.pfx 파일로 결합하여 쉽게 가져올 수 있습니다.
명령 줄에서 pfx 파일을 생성하려면 다음과 같습니다.
openssl pkcs12 -in a.crt -inkey a.key -export -out a.pfx
그런 다음 다음과 같은 .NET 인증서 클래스와 함께 일반적으로 사용하십시오.
using System.Security.Cryptography.X509Certificates;
X509Certificate2 combinedCertificate = new X509Certificate2(@"C:\path\to\file.pfx");
이제 예제를 따라갈 수 있습니다 MSDN rsacryptoserviceprovider를 통해 암호화 및 해독하려면 :
해독하려면 PFX 비밀번호와 내보낼 수있는 플래그를 사용하여 가져와야합니다. (보다: .net rsaprivatekey에서 Bouncycastle rsaprivatekey)
X509KeyStorageFlags flags = X509KeyStorageFlags.Exportable;
X509Certificate2 cert = new X509Certificate2("my.pfx", "somepass", flags);
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey;
RSAParameters rsaParam = rsa.ExportParameters(true);
당신은 살펴볼 수 있습니다 Javascience 's 소스 OpenSSLKEY
당신이하고 싶은 일을 정확하게 수행하는 코드가 있습니다.
사실, 그들은 많은 암호 소스 코드를 가지고 있습니다. 여기에서 사용할 수 있습니다.
소스 코드 스 니펫 :
//------- Parses binary ans.1 RSA private key; returns RSACryptoServiceProvider ---
public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
{
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ ;
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
MemoryStream mem = new MemoryStream(privkey) ;
BinaryReader binr = new BinaryReader(mem) ; //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
try {
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
return null;
bt = binr.ReadByte();
if (bt !=0x00)
return null;
//------ all private key components are Integer sequences ----
elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems) ;
elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems) ;
elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems) ;
elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems) ;
elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems) ;
elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems) ;
elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems) ;
Console.WriteLine("showing components ..");
if (verbose) {
showBytes("\nModulus", MODULUS) ;
showBytes("\nExponent", E);
showBytes("\nD", D);
showBytes("\nP", P);
showBytes("\nQ", Q);
showBytes("\nDP", DP);
showBytes("\nDQ", DQ);
showBytes("\nIQ", IQ);
}
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSAParameters RSAparams = new RSAParameters();
RSAparams.Modulus =MODULUS;
RSAparams.Exponent = E;
RSAparams.D = D;
RSAparams.P = P;
RSAparams.Q = Q;
RSAparams.DP = DP;
RSAparams.DQ = DQ;
RSAparams.InverseQ = IQ;
RSA.ImportParameters(RSAparams);
return RSA;
}
catch (Exception) {
return null;
}
finally {
binr.Close();
}
}
사이의 것들
-----BEGIN RSA PRIVATE KEY----
그리고
-----END RSA PRIVATE KEY-----
PKCS#8 PrivateKeyInfo의 Base64 인코딩입니다 (RSA가 암호화 된 개인 키가 표시되지 않는 한 암호화 된 프리 테 키인포가 표시되지 않는 한).
수동으로 디코딩하는 것은 그리 어렵지 않지만 그렇지 않으면 가장 좋은 방법은 p/호출입니다. cryptimportpkcs8.
업데이트: 그만큼 cryptimportpkcs8 Windows Server 2008 및 Windows Vista에서는 기능을 더 이상 사용할 수 없습니다. 대신 사용하십시오 pfximportCertStore 기능.
자, 자체 서명 키를 생성하기 위해 Mac을 사용합니다. 다음은 내가 사용한 작업 방법입니다.
키 생성 속도를 높이기 위해 쉘 스크립트를 만들었습니다.
genkey.sh
#/bin/sh
ssh-keygen -f host.key
openssl req -new -key host.key -out request.csr
openssl x509 -req -days 99999 -in request.csr -signkey host.key -out server.crt
openssl pkcs12 -export -inkey host.key -in server.crt -out private_public.p12 -name "SslCert"
openssl base64 -in private_public.p12 -out Base64.key
스크립트에 +x 실행 플래그를 추가하십시오
chmod +x genkey.sh
그런 다음 genkey.sh를 호출하십시오
./genkey.sh
비밀번호를 입력합니다 (최소한 수출에 대한 비밀번호를 포함시키는 것이 중요합니다).
Enter pass phrase for host.key:
Enter Export Password: {Important to enter a password here}
Verifying - Enter Export Password: { Same password here }
그런 다음 Base64. Key에서 모든 것을 가져 와서 sslkey라는 문자열에 넣습니다.
private string sslKey = "MIIJiAIBA...................................." +
"......................ETC...................." +
"......................ETC...................." +
"......................ETC...................." +
".............ugICCAA=";
그런 다음 게으른로드 속성 getter를 사용하여 개인 키로 X509 인증서를 얻었습니다.
X509Certificate2 _serverCertificate = null;
X509Certificate2 serverCertificate{
get
{
if (_serverCertificate == null){
string pass = "Your Export Password Here";
_serverCertificate = new X509Certificate(Convert.FromBase64String(sslKey), pass, X509KeyStorageFlags.Exportable);
}
return _serverCertificate;
}
}
Mac에서 .NET 2.0 및 mono를 사용하고 있기 때문에이 경로로 가고 싶었고 컴파일 된 라이브러리 나 종속성이없는 바닐라 프레임 워크 코드를 사용하고 싶었습니다.
이것에 대한 나의 마지막 사용은 내 앱에 TCP 커뮤니케이션을 보호하기위한 sslstream이었습니다.
SslStream sslStream = new SslStream(serverCertificate, false, SslProtocols.Tls, true);
나는 이것이 다른 사람들을 돕기를 바랍니다.
노트
암호가 없으면 개인 키를 올바르게 잠금 해제 할 수 없었습니다.
확인하다 http://msdn.microsoft.com/en-us/library/dd203099.aspx
암호화 응용 프로그램 블록에서.
당신이 당신의 답을 얻을 것인지 모르겠지만 시도해 볼 가치가 있습니다.
댓글 후 편집.
알겠습니다.이 코드를 확인하십시오.
using System.Security.Cryptography;
public static string DecryptEncryptedData(stringBase64EncryptedData, stringPathToPrivateKeyFile) {
X509Certificate2 myCertificate;
try{
myCertificate = new X509Certificate2(PathToPrivateKeyFile);
} catch{
throw new CryptographicException("Unable to open key file.");
}
RSACryptoServiceProvider rsaObj;
if(myCertificate.HasPrivateKey) {
rsaObj = (RSACryptoServiceProvider)myCertificate.PrivateKey;
} else
throw new CryptographicException("Private key not contained within certificate.");
if(rsaObj == null)
return String.Empty;
byte[] decryptedBytes;
try{
decryptedBytes = rsaObj.Decrypt(Convert.FromBase64String(Base64EncryptedData), false);
} catch {
throw new CryptographicException("Unable to decrypt data.");
}
// Check to make sure we decrpyted the string
if(decryptedBytes.Length == 0)
return String.Empty;
else
return System.Text.Encoding.UTF8.GetString(decryptedBytes);
}
탄력을 사용하고 싶지 않고 다른 답변에 포함 된 코드 중 일부를 시도하는 사람들을 위해 코드가 대부분 작동한다는 것을 알았지 만 I와 같은 RSA 비공개 문자열을 여행합니다. 'VE는 아래에 포함되어 있습니다. 탄력 코드를 살펴보면 WPRL이 제공 한 코드를 조정했습니다.
RSAparams.D = ConvertRSAParametersField(D, MODULUS.Length);
RSAparams.DP = ConvertRSAParametersField(DP, P.Length);
RSAparams.DQ = ConvertRSAParametersField(DQ, Q.Length);
RSAparams.InverseQ = ConvertRSAParametersField(IQ, Q.Length);
private static byte[] ConvertRSAParametersField(byte[] bs, int size)
{
if (bs.Length == size)
return bs;
if (bs.Length > size)
throw new ArgumentException("Specified size too small", "size");
byte[] padded = new byte[size];
Array.Copy(bs, 0, padded, size - bs.Length, bs.Length);
return padded;
}
-----BEGIN RSA PRIVATE KEY-----
MIIEoQIBAAKCAQEAxCgWAYJtfKBVa6Px1Blrj+3Wq7LVXDzx+MiQFrLCHnou2Fvb
fxuDeRmd6ERhDWnsY6dxxm981vTlXukvYKpIZQYpiSzL5pyUutoi3yh0+/dVlsHZ
UHheVGZjSMgUagUCLX1p/augXltAjgblUsj8GFBoKJBr3TMKuR5TwF7lBNYZlaiR
k9MDZTROk6MBGiHEgD5RaPKA/ot02j3CnSGbGNNubN2tyXXAgk8/wBmZ4avT0U4y
5oiO9iwCF/Hj9gK/S/8Q2lRsSppgUSsCioSg1CpdleYzIlCB0li1T0flB51zRIpg
JhWRfmK1uTLklU33xfzR8zO2kkfaXoPTHSdOGQIDAQABAoIBAAkhfzoSwttKRgT8
sgUYKdRJU0oqyO5s59aXf3LkX0+L4HexzvCGbK2hGPihi42poJdYSV4zUlxZ31N2
XKjjRFDE41S/Vmklthv8i3hX1G+Q09XGBZekAsAVrrQfRtP957FhD83/GeKf3MwV
Bhe/GKezwSV3k43NvRy2N1p9EFa+i7eq1e5i7MyDxgKmja5YgADHb8izGLx8Smdd
+v8EhWkFOcaPnQRj/LhSi30v/CjYh9MkxHMdi0pHMMCXleiUK0Du6tnsB8ewoHR3
oBzL4F5WKyNHPvesYplgTlpMiT0uUuN8+9Pq6qsdUiXs0wdFYbs693mUMekLQ4a+
1FOWvQECgYEA7R+uI1r4oP82sTCOCPqPi+fXMTIOGkN0x/1vyMXUVvTH5zbwPp9E
0lG6XmJ95alMRhjvFGMiCONQiSNOQ9Pec5TZfVn3M/w7QTMZ6QcWd6mjghc+dGGE
URmCx8xaJb847vACir7M08AhPEt+s2C7ZokafPCoGe0qw/OD1fLt3NMCgYEA08WK
S+G7dbCvFMrBP8SlmrnK4f5CRE3pV4VGneWp/EqJgNnWwaBCvUTIegDlqS955yVp
q7nVpolAJCmlUVmwDt4gHJsWXSQLMXy3pwQ25vdnoPe97y3xXsi0KQqEuRjD1vmw
K7SXoQqQeSf4z74pFal4CP38U3pivvoE4MQmJeMCfyJFceWqQEUEneL+IYkqrZSK
7Y8urNse5MIC3yUlcose1cWVKyPh4RCEv2rk0U1gKqX29Jb9vO2L7RflAmrLNFuA
J+72EcRxsB68RAJqA9VHr1oeAejQL0+JYF2AK4dJG/FsvvFOokv4eNU+FBHY6Tzo
k+t63NDidkvb5jIF6lsCgYEAlnQ08f5Y8Z9qdCosq8JpKYkwM+kxaVe1HUIJzqpZ
X24RTOL3aa8TW2afy9YRVGbvg6IX9jJcMSo30Llpw2cl5xo21Dv24ot2DF2gGN+s
peFF1Z3Naj1Iy99p5/KaIusOUBAq8pImW/qmc/1LD0T56XLyXekcuK4ts6Lrjkit
FaMCgYAusOLTsRgKdgdDNI8nMQB9iSliwHAG1TqzB56S11pl+fdv9Mkbo8vrx6g0
NM4DluCGNEqLZb3IkasXXdok9e8kmX1en1lb5GjyPbc/zFda6eZrwIqMX9Y68eNR
IWDUM3ckwpw3rcuFXjFfa+w44JZVIsgdoGHiXAdrhtlG/i98Rw==
-----END RSA PRIVATE KEY-----
나는 정확히 그렇게하는 Pemutils 라이브러리를 만들었습니다. 코드는 사용할 수 있습니다 github 그리고 설치할 수 있습니다 너겟:
PM> Install-Package PemUtils
또는 DER 변환기 만 원한다면 :
PM> Install-Package DerConverter
PEM 데이터에서 RSA 키를 읽기위한 사용 :
using (var stream = File.OpenRead(path))
using (var reader = new PemReader(stream))
{
var rsaParameters = reader.ReadRsaKey();
// ...
}