C# 来自Flex客户端的RSA加密和来自Web服务的相应解密
在flex客户端和用c#编写的web服务之间设置RSA加密/解密机制时遇到问题。想法是这样的:我将对flex中的一些文本进行加密,然后从web服务对其进行解密。我正在使用谷歌的as3crypto库。它正在正确加密/解密文本。我在web服务端也有正确加密/解密的代码。我的问题是同步它们——基本上是将公钥共享到flex,并将私钥保留到web服务 我的flex“encrypt”函数使用RSA的模和指数来进行文本加密,那么我如何从web服务的RSACryptServiceProvider获取这些模和指数属性,以便它们使用相同的标准。 我试过了 RSAKeyInfo.模数 RSAKeyInfo.指数 从web服务中获取并将它们提供给flex客户端。 在flex上进行加密之后,我获取密码文本并将其提供给web服务上的解密方法,但它给了我“坏数据”错误消息C# 来自Flex客户端的RSA加密和来自Web服务的相应解密,c#,wcf,apache-flex,actionscript-3,public-key-encryption,C#,Wcf,Apache Flex,Actionscript 3,Public Key Encryption,在flex客户端和用c#编写的web服务之间设置RSA加密/解密机制时遇到问题。想法是这样的:我将对flex中的一些文本进行加密,然后从web服务对其进行解密。我正在使用谷歌的as3crypto库。它正在正确加密/解密文本。我在web服务端也有正确加密/解密的代码。我的问题是同步它们——基本上是将公钥共享到flex,并将私钥保留到web服务 我的flex“encrypt”函数使用RSA的模和指数来进行文本加密,那么我如何从web服务的RSACryptServiceProvider获取这些模和指数
System.Security.Cryptography.CryptographicException: Bad Data.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.Utils._DecryptKey(SafeKeyHandle hPubKey, Byte[] key, Int32 dwFlags)
at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
at Microsoft.Samples.Security.PublicKey.App.RSADecrypt(Byte[] DataToDecrypt, RSAParameters RSAKeyInfo, Boolean DoOAEPPadding) in C:\Users
\Me\Desktop\After Release\5-24-2011-webServiceCrypto\publickeycryptography\CS\PublicKeyCryptography\PublicKey.cs:line 219
Encryption failed.
如何确保它们都使用相同的字节64或128加密。ie来自flex的输入应该符合web服务提供者的解密方法的期望。
(我想尺寸可能是个问题,可能不是-我迷路了)
下面是代码,首先是flex客户端,然后是web服务c代码
web服务部分如下所示:
try
{
//Create a UnicodeEncoder to convert between byte array and string.
UnicodeEncoding ByteConverter = new UnicodeEncoding();
//Create byte arrays to hold original, encrypted, and decrypted data.
byte[] dataToEncrypt = ByteConverter.GetBytes("Data to Encrypt");
byte[] encryptedData;
byte[] decryptedData;
//Create a new instance of RSACryptoServiceProvider to generate
//public and private key data.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
//Pass the data to ENCRYPT, the public key information
//(using RSACryptoServiceProvider.ExportParameters(false),
//and a boolean flag specifying no OAEP padding.
encryptedData = RSAEncrypt(dataToEncrypt, RSA.ExportParameters(false), false);
//Pass the data to DECRYPT, the private key information
//(using RSACryptoServiceProvider.ExportParameters(true),
//and a boolean flag specifying no OAEP padding.
decryptedData = RSADecrypt(encryptedData, RSA.ExportParameters(true), false);
//Display the decrypted plaintext to the console.
Console.WriteLine("\n\nDecrypted plaintext: {0}", ByteConverter.GetString(decryptedData));
}
}
static public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{
try
{
byte[] encryptedData;
//Create a new instance of RSACryptoServiceProvider.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
//Import the RSA Key information. This only needs
//toinclude the public key information.
RSA.ImportParameters(RSAKeyInfo);
//Encrypt the passed byte array and specify OAEP padding.
//OAEP padding is only available on Microsoft Windows XP or
//later.
encryptedData = RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
}
return encryptedData;
}
//Catch and display a CryptographicException
//to the console.
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return null;
}
}
static public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
{
try
{
Console.WriteLine("Modulus Lenghth :" + RSAKeyInfo.Modulus.Length);
Console.WriteLine("Exponent Length :" + RSAKeyInfo.Exponent.Length);
byte[] decryptedData;
//Create a new instance of RSACryptoServiceProvider.
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
//Import the RSA Key information. This needs
//to include the private key information.
RSA.ImportParameters(RSAKeyInfo);
//Decrypt the passed byte array and specify OAEP padding.
//OAEP padding is only available on Microsoft Windows XP or
//later.
decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
}
return decryptedData;
}
//Catch and display a CryptographicException
//to the console.
catch (CryptographicException e)
{
Console.WriteLine(e.ToString());
return null;
}
}
我不太确定这个RSA设置是否可行。。。
欢迎任何意见/建议/或建议的解决方案,
谢谢大家我使用as3crypto和javaweb服务。以下是一些想法: a。我通过openssl生成了我的公共和私有RSA密钥 b。我的客户机在应用程序启动时加载public.cer文件(如果您只是从生成的密钥中硬编码了它们,那么它也可以工作) c。通过
var inputByteArray : ByteArray = Hex.toArray(Hex.fromString(inputString));
var outputByteArray : ByteArray = new ByteArray();
appSettingsModel.publicRSAKey.encrypt(inputByteArray, outputByteArray, inputByteArray.length);
d。我没有写JAVA方面的东西,但你也没有用JAVA。我知道as3crypto默认使用PKCS1填充:
RSAKEY.as
private function _encrypt(op:Function, src:ByteArray, dst:ByteArray, length:uint, pad:Function, padType:int):void {
// adjust pad if needed
if (pad==null) pad = pkcs1pad;
这是可以改变的,但我还没有尝试过。根据您的代码,看起来您可能正在尝试使用OAEP方案解密,但我无法告诉您如何设置该bool。您可能想看看bool使用的填充方案是什么,并尝试改变一边或另一边以匹配填充策略。似乎过于复杂。我以前在一些高安全系统上工作过,但这太可笑了。除非你不想让用户知道他刚刚输入的文本,否则为什么在发送的文本中需要这种加密级别
只需使用一个强SSL密钥(IE6的最大值为256bit,您可以使用512,但只能与较新的浏览器兼容)作为具有二进制数据格式(AMF)的实际传输协议(我想象HTTP),一切都应该很好。我怀疑你的系统对于利用加密文本的使用是否如此重要。Eureka!尤里卡!我明白了 问题是在从web服务解密后,加密的字节数组缺少0,因此当更改为字符串时,它将无法读取“??”文本。所以我只需要使用paddWithZeros()函数,将解密后的字节数组在字节之间填充0,就可以了 感谢凯文,你的解决方案让我洞察了我应该考虑的事情。因此,在解密过程中,我将参数fOAEP指定为false,因此它将使用PKCS#1进行填充(使两个库使用相同的标准) 我得到的另一个错误是坏数据异常。当我将RSA cryptoServiceProvider的参数(模数和指数)共享给actionScript方法时,这个问题得到了解决 我还将c#RSA属性(如模n、指数e、私有d…等)的byte[]数组更改为hexa string,以便能够与as3crypto库共享 我很乐意与大家分享对我有用的东西;节省别人一些时间
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import com.hurlant.crypto.Crypto;
import com.hurlant.crypto.rsa.RSAKey;
import com.hurlant.crypto.symmetric.ICipher;
import com.hurlant.crypto.symmetric.IPad;
import com.hurlant.util.Hex;
private var currentResult:String;
private var encryptedText:String;
private var decryptedText:String;
private function encrypt(plainText:String):String {
var rsa:RSAKey = RSAKey.parsePublicKey(getModulus(), getExponent());
var data:ByteArray = Hex.toArray(Hex.fromString(plainText)); //returns byteArray of plainText
var dst:ByteArray = new ByteArray;
rsa.encrypt(data, dst, data.length);
currentResult = Hex.fromArray(dst);
encryptedText = currentResult;
trace ("Cipher: " + currentResult);
return currentResult;
}
private function getInput():ByteArray {
return null;
}
private function getModulus():String {
return "b6a7ca9002b4df39af1ed39251a5d"; //read this value from web service.
}
private function getExponent():String {
return "011"; //read this value from web service.
}
//For debugging and testing purposes
// private function decrypt(cipherText:String):String {
// var rsa:RSAKey = RSAKey.parsePrivateKey(getModulus(), getExponent(), getPrivate(), getP(), getQ(), getDMP1(), getDMQ1(), getCoeff());
// var data:ByteArray = Hex.toArray(cipherText);
// var dst:ByteArray = new ByteArray;
// rsa.decrypt(data, dst, data.length);
// decryptedText = Hex.fromArray(dst);
//trace('decrypted : ' + decryptedText);
// return Hex.toString(decryptedText);
// }
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:VBox >
<s:Button label="Encrypt Text" click="encrypt('my plain text')" />
<s:Button label="Decrypt Text" click="decrypt({encryptedText})" />
</mx:VBox>
</s:Application>
我将阅读一些有关RSA填充方案的书籍,看看是否有任何误解
谢谢我删除了Webservices标签,并用公钥加密替换了它;因为这似乎是标记这个问题的更重要的方式。当用户有权访问密钥时,加密是无用的。您永远无法实现比SSL更安全的解决方案,因此您也可以使用它……感谢flextras@drkstr-用户拥有公钥,但不知道私钥,那么它怎么会毫无用处呢?我的web服务是通过https公开的,所以通过https可以实现一定程度的安全性。。。这是需要加密的监管把戏吗?我可以想象这样一种情况:客户机按照您想要的方式加密数据并发送到web服务器。但是web服务器没有解密密钥。其他一些机器偶尔会抓取数据并对其解密。这是没有用的,因为客户端加密只会对已经拥有数据的人隐藏数据@即使如此,运行加密服务器端也会更好。客户端加密唯一有意义的时间是当SSL不可用时,或者如果数据在发送到服务器之前需要本地存储(如离线模式)。由于客户机上已经存在未加密的数据,并且SSL将加密通过线路发送的任何内容,因此根本不需要运行任何类型的加密client-side.Jax,但是我是否提到我正在加密用户给定的输入?正在加密的数据不是用户的输入。某些信息应该进行端到端-客户端到服务器的加密。这个概念并不太复杂。在公钥密码学中,只要使用我的公钥进行加密,使用什么库/框架并不重要。我的问题是,如何在flex中加密,在c#中解密?我知道flex存在一些相关的安全问题,但我们不要深入讨论这些问题。@Rose没有实际需要在客户端加密数据。如果数据未加密地存在于客户端,那么它已经被泄露给whoe
private function _encrypt(op:Function, src:ByteArray, dst:ByteArray, length:uint, pad:Function, padType:int):void {
// adjust pad if needed
if (pad==null) pad = pkcs1pad;
RSA.Decrypt(DataToDecrypt, DoOAEPPadding); // DoOAEPPadding = false
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import com.hurlant.crypto.Crypto;
import com.hurlant.crypto.rsa.RSAKey;
import com.hurlant.crypto.symmetric.ICipher;
import com.hurlant.crypto.symmetric.IPad;
import com.hurlant.util.Hex;
private var currentResult:String;
private var encryptedText:String;
private var decryptedText:String;
private function encrypt(plainText:String):String {
var rsa:RSAKey = RSAKey.parsePublicKey(getModulus(), getExponent());
var data:ByteArray = Hex.toArray(Hex.fromString(plainText)); //returns byteArray of plainText
var dst:ByteArray = new ByteArray;
rsa.encrypt(data, dst, data.length);
currentResult = Hex.fromArray(dst);
encryptedText = currentResult;
trace ("Cipher: " + currentResult);
return currentResult;
}
private function getInput():ByteArray {
return null;
}
private function getModulus():String {
return "b6a7ca9002b4df39af1ed39251a5d"; //read this value from web service.
}
private function getExponent():String {
return "011"; //read this value from web service.
}
//For debugging and testing purposes
// private function decrypt(cipherText:String):String {
// var rsa:RSAKey = RSAKey.parsePrivateKey(getModulus(), getExponent(), getPrivate(), getP(), getQ(), getDMP1(), getDMQ1(), getCoeff());
// var data:ByteArray = Hex.toArray(cipherText);
// var dst:ByteArray = new ByteArray;
// rsa.decrypt(data, dst, data.length);
// decryptedText = Hex.fromArray(dst);
//trace('decrypted : ' + decryptedText);
// return Hex.toString(decryptedText);
// }
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:VBox >
<s:Button label="Encrypt Text" click="encrypt('my plain text')" />
<s:Button label="Decrypt Text" click="decrypt({encryptedText})" />
</mx:VBox>
</s:Application>
static public string RSADecrypt(string cipherText)
{
UnicodeEncoding ByteConverter = new UnicodeEncoding();
byte[] DataToDecrypt = StringToByteArray(cipherText);
bool DoOAEPPadding = false;
try
{
byte[] decryptedData;
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
KeyInfo keyInfo = new KeyInfo();
RSAParameters RSAKeyInfo = keyInfo.getKey();
RSA.ImportParameters(RSAKeyInfo);
decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
}
byte[] paddedOutput = paddWithZeros(decryptedData); //to sync with as3crypto
return (ByteConverter.GetString(paddedOutput));
}catch (CryptographicException e)
{
//handle error
return null;
}
}