首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Flash加密mp3流

Flash加密mp3流
EN

Stack Overflow用户
提问于 2013-01-29 12:17:11
回答 5查看 1.7K关注 0票数 1

我有一个asp.net网站,为客户端Flash (SWF)提供示例MP3文件。

这些文件可以通过大量的下载工具下载。

虽然只有注册成员才能访问高质量的mp3示例,但我的客户端希望防止这些低质量的MP3文件被下载工具下载。

所以我想到了这个解决方案:

  1. 将这些MP3文件转换为服务器端的字节数组(ASP.NET)
  2. 按位执行XOR操作(简单加密)
  3. 将此数组写入aspx的响应流
  4. 修改Flash (.fla)以请求此新文件/页/aspx
  5. 在Flash上执行一些按位的XOR操作,并将其转换为原始的MP3作为字节数组。(简单解密)
  6. 播放MP3

直到第6步,我才能成功。我无法将这个字节数组转换为Flash可以播放的声音对象。我一点一点地比较了flash上的结果数组和ASP.NET上的源数组,它们是相等的

我愿意接受完全不同的方法。但我不能使用Flash媒体服务器。我需要使用Flash as3和ASP.NET。

也非常重要!必须下载/解密并异步播放.mp3 (这是我做不到的)

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-01-30 18:39:17

@walkietokyo,非常感谢你为我指明了正确的方向。我成功地做了我想做的事。这里的关键字是loadCompressedDataFromByteArray函数。

经过几十次试验和错误之后,我发现loadCompressedDataFromByteArray是以一种不同的方式工作的。

它将附加到,将转换为声音对象数据的末尾。

另一个问题:在调用loadCompressedDataFromByteArrayplay函数后,声音对象不再继续播放其附加的部分。

所以我实现了一种双重缓冲。在这里,我交替使用两个声音对象。

下面列出了我的最终(测试)版本。使用我使用的加密(混淆)方法(简单的XOR),我测试的下载管理器、抓取器或嗅探器都不能播放Mp3s。

Flash (客户)侧:

代码语言:javascript
复制
import flash.events.DataEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.OutputProgressEvent;
import flash.events.ProgressEvent;
import flash.net.URLRequest;
import flash.net.URLStream;
import flash.utils.ByteArray;
import flashx.textLayout.formats.Float;

var buffer:ByteArray;
var stream:URLStream;
var bufferReadPosition:uint = 0;
var bufferWritePosition:uint = 0;

var url:String = "http://www.blablabla.com/MusicServer.aspx?" + (new Date());

buffer = new ByteArray();
stream = new URLStream();
stream.addEventListener(ProgressEvent.PROGRESS, onProgress);
stream.load(new URLRequest(url));

var s1:Sound = new Sound();
var s2:Sound = new Sound();

var channel1:SoundChannel;
var channel2:SoundChannel;

var pausePosition:int = 0;

var aSoundIsPlaying:Boolean = false;

var lastLoadedS1:Boolean = false;

var lastS1Length:int = 0;
var lastS2Length:int = 0;

function onProgress(e:ProgressEvent):void {
    var tmpData:ByteArray = new ByteArray();

    stream.readBytes(tmpData, 0, stream.bytesAvailable);

    var decryptedData:ByteArray = decryptData(tmpData); // Decrypt loaded data

    buffer.position = bufferWritePosition;
    buffer.writeBytes(decryptedData, 0, decryptedData.length); // Add decrypted data to buffer
    bufferWritePosition += decryptedData.length;

    if(lastLoadedS1)
    {
        buffer.position = lastS2Length;
        s2.loadCompressedDataFromByteArray(buffer, buffer.length - lastS2Length);
        lastS2Length = buffer.length;
    }
    else
    {
        buffer.position = lastS1Length;
        s1.loadCompressedDataFromByteArray(buffer, buffer.length - lastS1Length);
        lastS1Length = buffer.length;
    }

    if(!aSoundIsPlaying)
    {
        DecidePlay();
    }
}

function channel1Completed(e:Event):void
{
    DecidePlay();
}

function channel2Completed(e:Event):void
{
    DecidePlay();
}

function DecidePlay():void
{
    aSoundIsPlaying = false;

    if(lastLoadedS1)
    {
        channel1.stop();

        if(s2.length - s1.length > 10000)
        {
            //At least a 10 second buffer
            channel2 = s2.play(s1.length);
            channel2.addEventListener(Event.SOUND_COMPLETE, channel2Completed);
            lastLoadedS1 = false;
            aSoundIsPlaying = true;
        }
    }
    else
    {
        if(channel2 != null)
        {
            channel2.stop();
        }

        if(s1.length - s2.length > 10000)
        {
            //At least a 10 second buffer
            channel1 = s1.play(s2.length);
            channel1.addEventListener(Event.SOUND_COMPLETE, channel1Completed);
            lastLoadedS1 = true;
            aSoundIsPlaying = true;
        }
    }
}

function decryptData(data:ByteArray):ByteArray {
    for(var i:int = 0;i<data.length;i++)
    {
        //Here put in your bitwise decryption code
    }
    return data;
}

ASP.NET服务器端(MusicServer.aspx):

代码语言:javascript
复制
    protected void Page_Load(object sender, EventArgs e)
    {
        CopyStream(Mp3ToStream(Server.MapPath("blabla.mp3")), Response.OutputStream);

        this.Response.AddHeader("Content-Disposition", "blabla.mp3");
        this.Response.ContentType = "audio/mpeg";
        this.Response.End();
    }

    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[32768];
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            for (int i = 0; i < read; i++)
            {
                //Here put in your bitwise encryption code
            }

            output.Write(buffer, 0, read);
        }
    }

    public Stream Mp3ToStream(string filePath)
    {
        using (FileStream fileStream = File.OpenRead(filePath))
        {
            MemoryStream memStream = new MemoryStream();
            memStream.SetLength(fileStream.Length);
            fileStream.Read(memStream.GetBuffer(), 0, (int)fileStream.Length);
            return memStream;
        }
    }
票数 2
EN

Stack Overflow用户

发布于 2013-01-30 00:09:17

我同意Peter的观点,身份验证可能是限制文件访问的最简单方法。但是,如果您仍然需要探索加密文件的方法,我想我会对Alex的答案做一些扩展。

为了能够流音频文件,动态解密音频文件,并异步播放音频文件,您需要做的是结合使用URLStream类(文档)和Sound类(文档),并为部分下载的内容保留一个缓冲区。

一些伪码来说明:

代码语言:javascript
复制
class AsyncEncryptedSoundPlayer extends Sound {
    var buffer:ByteArray;
    var stream:URLStream;
    var currSoundPosition:uint = 0;

    public function AsyncEncryptedSoundPlayer(url:String) {
        buffer = new ByteArray();
        stream = new URLStream();
        stream.addEventListener(ProgressEvent.PROGRESS, onProgress);
        stream.load(new URLRequest(url));

        addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleDataRequested);
    }

    function onProgress(e:ProgressEvent):void {
        var tmpData:ByteArray;
        stream.readBytes(tmpData, buffer.length, stream.bytesAvailable - buffer.length);
        var decryptedData:ByteArray = decryptData(tmpData); // Decrypt loaded data
        buffer.writeBytes(decryptedData, buffer.length, decryptedData.length); // Add decrypted data to buffer
    }

    function onSampleDataRequested(e:ProgressEvent):void {
        // Feed samples from the buffer to the Sound instance
        // You may have to pause the audio to increase the buffer it the download speed isn't high enough
        event.data.writeBytes(buffer, currSoundPosition, 2048);
        currSoundPosition += 2048;
    }

    function decryptedData(data:ByteArray):void {
        // Returns decrypted data
    }
}

这显然是一个很粗略的课程大纲,但我希望它能为你指明正确的方向。

票数 3
EN

Stack Overflow用户

发布于 2013-01-29 14:40:04

与加密服务返回的数据相比,可能更简单的是对请求进行身份验证,这样只有swf才能请求文件。

您可以以与Amazon相同的方式来完成这一任务:构建一个包含多个参数的请求,包括一个时间戳。散列所有这些参数在HMAC中(HMAC 256在as3crypto库中可用),以及嵌入在swf中的私钥。服务器端对此请求进行身份验证,确保散列是有效的,并且它足够接近时间戳。任何具有错误散列的请求,或者使用带有时间戳的请求(重播攻击)都会被拒绝。

这肯定不是完美的安全措施。任何有足够动力的用户都可以拆卸swf并取出您的auth密钥,或者从他们的浏览器缓存中获取mp3。但话又说回来,你将要使用的任何机制都会有这些问题。这消除了必须加密和解密所有文件的开销,而将工作转移到请求生成阶段。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14582684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档