解决“Base-64字符数组的无效长度” 的问题

举报
清雨小竹 发表于 2022/10/09 14:34:28 2022/10/09
【摘要】 这两天做一个视频分享的模块,有一个功能是解析地址栏中的加密字符串.实际使用过程中发现了"Base-64字符数组的无效长度"的问题。后来分析才知道是由于地址栏中的字符"+"没有正确解析导致的。 using System;using System.Data;using System.Configuration;using System.Collections;using System.Web;u...

这两天做一个视频分享的模块,有一个功能是解析地址栏中的加密字符串.实际使用过程中发现了"Base-64字符数组的无效长度"的问题。

后来分析才知道是由于地址栏中的字符"+"没有正确解析导致的。

 

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace EtahTeachVideo.Media
{
    public partial class SharedVideo : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
               
                if (Request.QueryString["IDTM"] != null)
                {
                    string strRequest = Request.QueryString["IDTM"];
                    strRequest = strRequest.Replace(' ', '+'); //注意,IDTM=JI7W/IZIoZadVU+dCqd4WSLFVJb3mK3i 中的"+"通过地址栏传过来时,后台会解析为空格. 最好的做法是 使用String.Replace("+", "%2B")先将空格编码,然后再作为参数传给另一页面传递,这样页面在提取参数时才会将“%2B”解码为加号.但这儿为了简化,将空格直接还原为"+"。
                    Encrypt enr = new Encrypt ();
                    string strEncryptCharacter = enr.DecryptString(strRequest);
                    if (strEncryptCharacter != null && strEncryptCharacter.IndexOf("|") > 1)
                    {

                        string strMediaID = strEncryptCharacter.Split('|')[0];
                        string strGenerateTime = strEncryptCharacter.Split('|')[1];                       
                        DateTime dtGeneateTime = DateTime.Parse(strGenerateTime);
                        TimeSpan spn = DateTime.Now.Subtract(dtGeneateTime);
                        if (spn.TotalSeconds > 24 * 60 * 60)
                        {
                            //超过一天的情况
                            Response.Write("您请求的视频已经过期,请联系管理员获取新的地址.");
                            return;
                        }
                        int nMediaID = int.Parse(strMediaID);
                        string strJs = @"<script type='text/javascript'> " +
                                           "window.moveTo((window.screen.width-1010)/2,(window.screen.height-685)/2);" +
                                           "window.resizeTo(1010,685);" +
                                           "window.showModalDialog('PlayerVod.htm?Query=" + strMediaID + "','','dialogWidth=1010px;dialogHeight=685px;status=no;scroll=no;');" +
                                           "window.opener= null;window.open('','_self'); window.close();" + //解决关闭窗口的提示ie7下必须加window.open('','_self')才有效.
                                        "</script>";
                        ClientScript.RegisterClientScriptBlock(this.GetType(), "key", strJs);
                    }
                    else
                    {
                        Response.Write("请求的地址有误.");
                        return;
                    }                  
                }
                else
                {
                    Response.Write("您无权查看该网页.");     
                }
        }      
    }

    /// <summary>
    /// 本类完成对字符串的加密和解密。
    /// 通过DES对称加密算法,完成对字符串的加密和解密操作。
    /// </summary>
    public class Encrypt
    {
        private SymmetricAlgorithm mCSP;
        private const string CIV = "kXwL7X2+fgM=";//密钥
        private const string CKEY = "FwGQWRRgKCI=";//初始化向量

        public Encrypt()
        {
            mCSP = new DESCryptoServiceProvider();
        }

        public string EncryptString(string Value)
        {
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;

            ct = mCSP.CreateEncryptor(Convert.FromBase64String(CKEY), Convert.FromBase64String(CIV));

            byt = Encoding.UTF8.GetBytes(Value);

            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            cs.Write(byt, 0, byt.Length);
            cs.FlushFinalBlock();

            cs.Close();

            return Convert.ToBase64String(ms.ToArray());
        }

        public string DecryptString(string Value)
        {
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;

            try
            {
                ct = mCSP.CreateDecryptor(Convert.FromBase64String(CKEY), Convert.FromBase64String(CIV));


                byt = Convert.FromBase64String(Value);

                ms = new MemoryStream();
                cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
                cs.Write(byt, 0, byt.Length);
                cs.FlushFinalBlock();

                cs.Close();

                return Encoding.UTF8.GetString(ms.ToArray());
            }
            catch(Exception ex)
            {
                return null;
            }
        }

    }

 


}

 

 

//参考 

DES解密时“Base-64字符数组的无效长度”
问题是 在页面传送的时候加密了 ,然后解密出来就抛出异常  跟踪发现是 ++ 在解析REQUEST的时候变成了空格

解决办法

使用String.Replace("+", "%2B")先将空格编码,然后再作为参数传给另一页面传递,这样页面在提取参数时才会将“%2B”解码为加号

下面是一个相关的知识

在使用Convert.ToBase64String()对字符串进行Base64编码时,注意的几点:
   例:string s = "Hello";
      byte[] bytes = Convert.FromBase64String(s);
以上代码在运行时会抛出FormatException异常.提示为:Base-64字符数组的无效长度

原因:
当Convert.FromBase64String方法的参数s的长度小于4或不是4的偶数倍时,将会抛出FormatException。
  

   例:
       Convert.FromBase64String("Hell");      // Normal.
       Convert.FromBase64String("Hell ");     // Normal.(忽略空格)
       Convert.FromBase64String("Hello!");     // throw FormatException.
       Convert.FromBase64String("Hello Net"); // Normal.(忽略空格)
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。