2010-04-20 27 views
2

我试图编写一些通过Url传递的加密代码。为了解决这个问题,我排除了数据的实际加密,并只显示了导致问题的代码。当串联和Url编码字符串时,Base-64字符串中的字符无效

我拿一个盐值,将它转换成一个字节数组,然后将其转换为一个base64字符串。该字符串连接到另一个base64字符串(以前是字节数组)。

这两个的base64字符串然后地址编码。这里是我的代码...

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Security.Cryptography; 
using System.IO; 
using System.Web; 

class RHEncryption 
{ 
    private static readonly Encoding ASCII_ENCODING = new System.Text.ASCIIEncoding(); 
    private static readonly string SECRET_KEY = "akey"; 
    private static string md5(string text) 
    { 
     return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(ASCII_ENCODING.GetBytes(text))).Replace("-", "").ToLower(); 
    } 

    public string UrlEncodedData; 

    public RHEncryption() 
    { 
     // encryption object 
     RijndaelManaged aes192 = new RijndaelManaged(); 
     aes192.KeySize = 192; 
     aes192.BlockSize = 192;    
     aes192.Mode = CipherMode.CBC; 
     aes192.Key = ASCII_ENCODING.GetBytes(md5(SECRET_KEY)); 
     aes192.GenerateIV(); 

     // convert Ivector to base64 for sending    
     string base64IV = Convert.ToBase64String(aes192.IV); 

     // salt value 
     string s = "maryhadalittlelamb"; 
     string salt = s.Substring(0, 8); 
     // convert to byte array 
     // and base64 for sending 
     byte[] saltBytes = ASCII_ENCODING.GetBytes(salt.TrimEnd('\0')); 
     string base64Salt = Convert.ToBase64String(saltBytes); 

     //url encode concatenated base64 strings 
     UrlEncodedData = HttpUtility.UrlEncode(base64Salt + base64IV, ASCII_ENCODING); 
    } 

    public string UrlDecodedData() 
    { 
     // decode the url encode string 
     string s = HttpUtility.UrlDecode(UrlEncodedData, ASCII_ENCODING); 

     // convert back from base64 
     byte[] base64DecodedBytes = null; 
     try 
     { 
      base64DecodedBytes = Convert.FromBase64String(s); 
     } 
     catch (FormatException e) 
     { 
      Console.WriteLine(e.Message.ToString()); 
      Console.ReadLine(); 
     } 
     return s; 
    } 
} 

如果我再调用UrlDecodedData方法我在基地-64串

例外获得

无效字符。这是因为base64Salt变量包含一个无效字符(我在猜测线路终端),但我似乎无法将其剥离。

更新1

的一件事,因为帖子,我发现是,如果我改变串的次序进行编码引发任何异常。 所以从

UrlEncodedData = HttpUtility.UrlEncode(base64Salt + base64IV, ASCII_ENCODING); 

更改下面的代码

UrlEncodedData = HttpUtility.UrlEncode(base64IV + base64Salt, ASCII_ENCODING); 

似乎工作,遗憾的是因为此信息传递给第三方组件,我不能重新排序。

+0

“base64IV + base64Salt”碰巧没有打破那个时间,真是太幸运了。一般来说,连接Base64字符串可能不会给你一个Base64字符串,所以不要这样做。 – 2010-04-20 22:31:31

回答

1

这里是你的问题:

UrlEncodedData = HttpUtility.UrlEncode(base64Salt + base64IV, ASCII_ENCODING); 
... 
string s = HttpUtility.UrlDecode(UrlEncodedData, ASCII_ENCODING); 
base64DecodedBytes = Convert.FromBase64String(s); 

您catenating 2 Base64编码字符串,然后尝试Base64编码解码的组合。这只适用于你的base64Salt是6位的倍数,在你的情况下它不是。不是这样的倍数的数据获得了Base64编码的后缀'='字符,并且它将'='放在字符串的中间,这不是有效的Base64字符串。

您必须在编码之前链接原始数据。这只有在您知道原始数据长度时才有效。如果你不这样做,你将不得不分别编码salt和vector,并将它们链接到URL;例如http://yoursite/yourPage?salt=mcMDaw%20VUsZX&iv=VUsZXyg6n61e6SavmMrtAWa0A

+0

@Dour谢谢你的回复。我应该连接,然后转换为base64? – Rob 2010-04-20 18:10:42

+0

如果您始终知道将解码字节[]分解成盐和向量的位置,则可以这样做。在你的例子中,salt是前8个字节。这永远是真实的,永远不会改变吗?如果是这样,连接,编码,解码,然后再分割出前8个字节。如果有任何可能性发生改变,您将不得不分别对它们进行编码。或者你可以添加一个字节前缀说明有多少字节是盐。例如。字节[] = {32,12,104,74,...}表示前32个字节是盐。 – 2010-04-20 18:19:26

+0

这次我很幸运,字节数组偏移是固定的。 – Rob 2010-04-21 07:14:17