RSAプロバイダーを使用して暗号化および復号化する方法を説明するCodeProject aの記事をしばらく読んでいます。
2009からの古いバージョンはバグがありましたが、(System.Numerics.BigIntegerをサポートする)新しい2012バージョンはより信頼できるようです。このバージョンに欠けているのは、encryptをpublicキーとdecryptprivateキーを使用します。
だから、私はそれを自分で試しましたが、解読するとゴミが出ます。私はRSAプロバイダーに精通していないので、ここでは暗闇の中にいます。これがどのように機能するかについての詳細情報を見つけるのは困難です。
これで何が問題なのか誰にも分かりますか?以下は、公開鍵による暗号化です:
// Add 4 byte padding to the data, and convert to BigInteger struct
BigInteger numData = GetBig( AddPadding( data ) );
RSAParameters rsaParams = rsa.ExportParameters( false );
//BigInteger D = GetBig( rsaParams.D ); //only for private key
BigInteger Exponent = GetBig( rsaParams.Exponent );
BigInteger Modulus = GetBig( rsaParams.Modulus );
BigInteger encData = BigInteger.ModPow( numData, Exponent, Modulus );
return encData.ToByteArray();
これを行うとき、プロバイダーからの大きな「D」を使用しますか? 「D」のない公開鍵だからだろう。
次に、対応するもの(PRIVATEキーを使用した復号化):
BigInteger numEncData = new BigInteger( cipherData );
RSAParameters rsaParams = rsa.ExportParameters( true );
BigInteger D = GetBig( rsaParams.D );
//BigInteger Exponent = GetBig( rsaParams.Exponent );
BigInteger Modulus = GetBig( rsaParams.Modulus );
BigInteger decData = BigInteger.ModPow( numEncData, D, Modulus );
byte[] data = decData.ToByteArray();
byte[] result = new byte[ data.Length - 1 ];
Array.Copy( data, result, result.Length );
result = RemovePadding( result );
Array.Reverse( result );
return result;
ここに「D」または指数が必要ですか?
明らかに、私は暗号がプライベート-パブリック-パブリック-プライベートの両方の方法で機能する必要があります。どんな助けでも大歓迎です!
ここにあなたのための例があります:
public static void rsaPlayground()
{
byte[] data = new byte[] { 1, 2, 3, 4, 5 };
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();//make a new csp with a new keypair
var pub_key = csp.ExportParameters(false); // export public key
var priv_key = csp.ExportParameters(true); // export private key
var encData = csp.Encrypt(data, false); // encrypt with PKCS#1_V1.5 Padding
var decBytes = MyRSAImpl.plainDecryptPriv(encData, priv_key); //decrypt with own BigInteger based implementation
var decData = decBytes.SkipWhile(x => x != 0).Skip(1).ToArray();//strip PKCS#1_V1.5 padding
}
public class MyRSAImpl
{
private static byte[] rsaOperation(byte[] data, BigInteger exp, BigInteger mod)
{
BigInteger bData = new BigInteger(
data //our data block
.Reverse() //BigInteger has another byte order
.Concat(new byte[] { 0 }) // append 0 so we are allways handling positive numbers
.ToArray() // constructor wants an array
);
return
BigInteger.ModPow(bData, exp, mod) // the RSA operation itself
.ToByteArray() //make bytes from BigInteger
.Reverse() // back to "normal" byte order
.ToArray(); // return as byte array
/*
*
* A few words on Padding:
*
* you will want to strip padding after decryption or apply before encryption
*
*/
}
public static byte[] plainEncryptPriv(byte[] data, RSAParameters key)
{
MyRSAParams myKey = MyRSAParams.fromRSAParameters(key);
return rsaOperation(data, myKey.privExponent, myKey.Modulus);
}
public static byte[] plainEncryptPub(byte[] data, RSAParameters key)
{
MyRSAParams myKey = MyRSAParams.fromRSAParameters(key);
return rsaOperation(data, myKey.pubExponent, myKey.Modulus);
}
public static byte[] plainDecryptPriv(byte[] data, RSAParameters key)
{
MyRSAParams myKey = MyRSAParams.fromRSAParameters(key);
return rsaOperation(data, myKey.privExponent, myKey.Modulus);
}
public static byte[] plainDecryptPub(byte[] data, RSAParameters key)
{
MyRSAParams myKey = MyRSAParams.fromRSAParameters(key);
return rsaOperation(data, myKey.pubExponent, myKey.Modulus);
}
}
public class MyRSAParams
{
public static MyRSAParams fromRSAParameters(RSAParameters key)
{
var ret = new MyRSAParams();
ret.Modulus = new BigInteger(key.Modulus.Reverse().Concat(new byte[] { 0 }).ToArray());
ret.privExponent = new BigInteger(key.D.Reverse().Concat(new byte[] { 0 }).ToArray());
ret.pubExponent = new BigInteger(key.Exponent.Reverse().Concat(new byte[] { 0 }).ToArray());
return ret;
}
public BigInteger Modulus;
public BigInteger privExponent;
public BigInteger pubExponent;
}
このエンコード/デコードの例を見てください
byte[] toEncryptData = Encoding.ASCII.GetBytes("hello world");
//Generate keys
RSACryptoServiceProvider rsaGenKeys = new RSACryptoServiceProvider();
string privateXml = rsaGenKeys.ToXmlString(true);
string publicXml = rsaGenKeys.ToXmlString(false);
//Encode with public key
RSACryptoServiceProvider rsaPublic = new RSACryptoServiceProvider();
rsaPublic.FromXmlString(publicXml);
byte[] encryptedRSA = rsaPublic.Encrypt(toEncryptData, false);
string EncryptedResult = Encoding.Default.GetString(encryptedRSA);
//Decode with private key
var rsaPrivate = new RSACryptoServiceProvider();
rsaPrivate.FromXmlString(privateXml);
byte[] decryptedRSA = rsaPrivate.Decrypt(encryptedRSA, false);
string originalResult = Encoding.Default.GetString(decryptedRSA);