在Python中标记数据为敏感数据

24 投票
5 回答
12347 浏览
提问于 2025-04-15 12:11

我需要在内存中暂时存储一个用户的密码。请问我该怎么做才能避免这些信息在程序崩溃时被泄露,或者在调试时被显示出来?有没有办法把这个值标记为“敏感”,这样调试工具就不会把它保存到任何地方?

5 个回答

2

没有办法直接“标记为敏感”,不过你可以把数据在内存中加密,等到需要用的时候再解密。这不是一个完美的解决办法,但这是我能想到的最好方法。

5

... 解决这个问题的唯一办法就是使用可变的数据结构。 也就是说,你必须使用那些可以动态替换元素的数据结构。例如,在Python中,你可以用列表来存储一组字符。不过,每次你在列表中添加或删除元素时,语言可能会在你不知情的情况下复制整个列表,这取决于具体的实现方式。为了安全起见,如果你需要动态调整数据结构的大小,你应该创建一个新的数据结构,复制数据,然后覆盖掉旧的那个。比如:

def paranoid_add_character_to_list(ch, l):
  """Copy l, adding a new character, ch.  Erase l.  Return the result."""
  new_list = []
  for i in range(len(l)):
    new_list.append(0)
  new_list.append(ch)
  for i in range(len(l)):
    new_list[i] = l[i]
    l[i] = 0
  return new_list

来源: http://www.ibm.com/developerworks/library/s-data.html

  • 作者: John Viega (viega@list.org) 是《构建安全软件》(Addison-Wesley, 2001)和《Java企业架构》(O'Reilly and Associates, 2001)的合著者。John发表了超过50篇技术文章,主要集中在软件安全领域。他还编写了Mailman,一个GNU邮件列表管理器,以及ITS4,一个用于查找C和C++代码中安全漏洞的工具。
35

编辑

我找到了一种方法,使用ctypes(它又依赖于C语言)来清空内存。

import sys
import ctypes

def zerome(string):
    location = id(string) + 20
    size     = sys.getsizeof(string) - 20

    memset =  ctypes.cdll.msvcrt.memset
    # For Linux, use the following. Change the 6 to whatever it is on your computer.
    # memset =  ctypes.CDLL("libc.so.6").memset

    print "Clearing 0x%08x size %i bytes" % (location, size)

    memset(location, 0, size)

我不能保证这段代码是安全的。它在x86架构和CPython 2.6.2上经过测试可以正常工作。更详细的说明可以在这里找到。

在Python中进行解密和加密是行不通的。因为字符串和整数会被存储在内存中并保持不变,这就意味着你的密码信息会到处都是,变得很乱。

通常的解决办法是使用哈希(散列),不过最终明文数据还是需要在某个地方处理。

正确的做法是将敏感操作放在C语言模块中进行。

但是如果你的内存总是被攻击,那我建议你重新考虑一下你的安全设置。

撰写回答