它是可能的"消灭"串德尔菲?让我解释一下:

我写的应用程序,其中将包括一个DLL到授权的用户。它会读取加密的文件变成一个DOM XML,使用的信息,然后释放DOM。

显而易见的是,未加密的XML仍然是坐在存储器的问题,因此容易受到检查。现在,我不要做得过分保护这样的-将用户可以建立另一个DLL-但我想要取一个基本步骤,以防止用户的名字从坐在存的年龄。然而,我不认为我能轻易擦除的记忆无论如何,因为参考文献。如果我横越我DOM(这是一个TNativeXML类)并找到的每一个字符串的实例,然后让它变成像"aaaaa",然后将它并不实际分配新的串的指针DOM参考,然后留下的老串坐在那儿在存储器等待重新分配?有没有方法可以肯定的是我杀死的唯一原始副本吗?

或是有在D2007一种手段来告诉它来擦拭的所有未使用存储器从堆?所以我可以释放DOM,然后告诉它来擦。

或者我应该只是得到我的下一个任务,忘记这一点,因为它是真的不值得打扰.

有帮助吗?

解决方案

我不认为这是值得与困扰,因为如果一个用户可以读取使用DLL的进程的存储器,同样用户也可以停止在任何给定时间点的执行。停止被擦拭仍会给用户完全访问未加密的数据存储之前执行。

IMO任何用户足够的兴趣和能够做你描述不会被你的DLL擦拭内存严重不便的。

其他提示

两个大点有关这个:

首先,这是一个这些领域里,"如果你要问问,你可能不应该这样做。" 请不要用这种错误的方式;我的意思是没有不尊重您的编程技能。这只是书面的安全、保密性强的软件是什么,你是个专家,或者你不是。很多相同的方式知道"一点点空手道"更加危险的不知道没有空手道在所有。还有一些第三方的工具,用于编写安全软件在德尔斐其中有专家的支持;我强烈鼓励任何人都没有深入的了解的加密服务在窗户、数学基础加密和经验,在战胜边渠道的攻击中使用它们,而不是试图"滚他们自己。"

来回答你的具体问题:Windows API有一定数量的职能是有用的,例如 CryptProtectMemory.然而,这将带来一种虚假的安全感如果你加密你的记忆,但是有一个洞在系统中的其他地方,或者获得一侧的通道。它可以像把一个锁在你的门,但离开窗打开。

怎么样这样呢?

procedure WipeString(const str: String);
var
  i:Integer;
  iSize:Integer;
  pData:PChar;

begin
    iSize := Length(str);
    pData := PChar(str);

    for i := 0 to 7 do
    begin
      ZeroMemory(pData, iSize);
      FillMemory(pData, iSize, $FF); // 1111 1111
      FillMemory(pData, iSize, $AA); // 1010 1010
      FillMemory(pData, iSize, $55); // 0101 0101
      ZeroMemory(pData, iSize);
    end;
end;

的DLL没有自己分配的内存,流程做。通过特定处理中分配的存储器将被丢弃一旦进程终止时,DLL是否挂起周围(因为它是在使用由另一个处理)或不

如何有关该文件的解密到的流,使用SAX处理器,而不是一个XML DOM做你的验证,然后释放它之前覆盖解密流?

如果您使用FastMM内存管理器在完全调试模式,则可以迫使它改写存储器时被释放它。

通常这种行为被用来检测野指针,但它也可以用于你想要的东西。

在另一方面,一定要了解什么克雷格斯顿茨写道:不要写这个身份验证和授权的东西自己,尽可能使用底层操作系统

BTW:Hallvard Vassbotn写一篇好的博客关于FastMM: http://hallvards.blogspot.com/2007/ 05 /使用-全fastmm-考虑-donating.html

此致

的Jeroen Pluimers

凌乱,但你可以记下你已经使用,而你已经有了充满了敏感数据的堆那么当被释放做一个GetMem函数分配你一大块跨越堆大小的(比如说)200%这一点。做对块的填充,并作一个假设,任何碎片unlinkely多大用处给考官。 BRI

如何在XML保持密码的散列值,并验证所述输入密码的哈希与在XML哈希密码进行比较。

编辑:您可以保留所有加密敏感数据,只在最后一刻解密

是否有可能向所解密的XML加载到char或字节的阵列,而不是字符串?然后就没有写入时复制操作,这样你就可以释放之前回填#0的内存?

成为如果指派字符的数组串小心,因为Delphi有一些智能处理这里与传统的压缩数组[1..X]炭的相容性。

此外,您还可以使用ShortString短?

如果您使用XML,即使加密后,交给你的密码,把你的用户存储处于危险之中。更好的方法是存储密码的散列值来代替,然后比较哈希对输入的密码。这种方法的优点是,即使在知道哈希值,你不会知道这使得哈希密码。添加蛮力标识符(计数无效密码尝试,并有一定的次数后锁定帐户)将进一步增加安全性。

有你可以用它来创建一个字符串的哈希几种方法。一个很好的出发点是看的涡轮增压动力的开源项目“密码箱”,我相信它具有产生单向散列密钥的几个例子。

修改

但如何知道如果一个方法帮助的哈希值?如果你真的偏执,你可以通过一些prediticable,只有你会知道修改散列值...比方说,使用特定的种子值加上最新的随机数。然后,您可以储存只够哈希在你的XML,所以你可以使用它作为一个起点比较。关于伪随机数生成器的好处是,他们始终会在同一系列中给出的相同的种子“随机”的数字。

小心点的职能,试图把一串为指针,并且尝试使用 FillCharZeroMemory 擦串的内容。

  • 这既是错误的(串共享;你拧别人的目前使用的字符串)
  • 并且可能导致一个访问违反了(如果串发生已经一个恒定不变的,它是坐在一个只读数据页,在该进程的地址空间;并试图编写,它是一个访问违反了)

 

procedure BurnString(var s: UnicodeString);
begin
    {
        If the string is actually constant (reference count of -1), then any attempt to burn it will be
        an access violation; as the memory is sitting in a read-only data page.

        But Delphi provides no supported way to get the reference count of a string.

        It's also an issue if someone else is currently using the string (i.e. Reference Count > 1).
        If the string were only referenced by the caller (with a reference count of 1), then
        our function here, which received the string through a var reference would also have the string with
        a reference count of one.

        Either way, we can only burn the string if there's no other reference.

        The use of UniqueString, while counter-intuitiave, is the best approach.
        If you pass an unencrypted password to BurnString as a var parameter, and there were another reference,
        the string would still contain the password on exit. You can argue that what's the point of making a *copy*
        of a string only to burn the copy. Two things:

            - if you're debugging it, the string you passed will now be burned (i.e. your local variable will be empty)
            - most of the time the RefCount will be 1. When RefCount is one, UniqueString does nothing, so we *are* burning
                the only string
    }
    if Length(s) > 0 then
    begin
        System.UniqueString(s); //ensure the passed in string has a reference count of one
        ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));

        {
            By not calling UniqueString, we only save on a memory allocation and wipe if RefCnt <> 1
            It's an unsafe micro-optimization because we're using undocumented offsets to reference counts.

            And i'm really uncomfortable using it because it really is undocumented.
            It is absolutely a given that it won't change. And we'd have stopping using Delphi long before
            it changes. But i just can't do it.
        }
        //if PLongInt(PByte(S) - 8)^ = 1 then //RefCnt=1
        //  ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));

        s := ''; //We want the callee to see their passed string come back as empty (even if it was shared with other variables)
    end;
end;

一旦你的 UnicodeString 版本,您可以创建的 AnsiStringWideString 版本:

procedure BurnString(var s: AnsiString); overload;
begin
    if Length(s) > 0 then
    begin
        System.UniqueString(s);
        ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));

        //if PLongInt(PByte(S) - 8)^ = 1 then //RefCount=1
        //  ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));

        s := '';
    end;
end;

procedure BurnString(var s: WideString);
begin
    //WideStrings (i.e. COM BSTRs) are not reference counted, but they are modifiable
    if Length(s) > 0 then
    begin
        ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));

        //if PLongInt(PByte(S) - 8)^ = 1 then //RefCount=1
        //  ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));

        s := '';
    end;
end;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top