将敏感数据从 C 传递到 Java
Posted
技术标签:
【中文标题】将敏感数据从 C 传递到 Java【英文标题】:Passing sensitive data from C to Java 【发布时间】:2013-09-05 05:25:26 【问题描述】:我正在开发一个 C 程序,它必须通过 popen()
调用 Java
main()
并将一些数据作为命令行参数发送给它。但是,还有一些数据需要从C
发送到Java
,这在本质上有些敏感(但不是密码类型)。
我正在尝试查看除了加密之外是否还有其他选项可以将这些额外数据从 C 发送到 Java。我试图避免开销,因为数据并不像加密那样敏感,但我愿意接受这方面的任何建议。
我无法通过 popen() 发送这些额外数据,因为它可以通过 ps -f
看到。
同样,使用套接字似乎也不可行,因为tcpdump
也可以泄露这些信息。
我考虑使用共享mem (/dev/shm)
,但也可以查看或使用隐藏文件。因为,这也带来了为每次调用创建文件的开销,我并不完全赞成。
我查看了ANON
文件映射,但我想,我不能在 Java 端使用它。
同样,通过 Java 似乎无法使用 fmemopen()
引用。
FIFO
管道会是更好的选择吗?或者它们也可以轻松阅读?
如果我只是诉诸普通的 mmap()
并向其写入数据(不在磁盘上创建它 - 在公开调用中没有 O_CREAT),并且不执行 msynch
它将完全保留在内存中?然后我可以从中读取 Java 吗?
加密是我唯一的选择还是我缺少一些基本的东西?
link 讨论从 C 向 Java 发送纯数据。
【问题讨论】:
如果不受信任的用户具有特权(即 root),则只能通过tcpdump
看到数据。如果您试图阻止 root 访问信息,那么您就真正遇到麻烦了。
建议加密。
标准输入/标准输出呢?
任何技术的问题是,您要保护自己免受已经可以访问机器并已登录的特权用户的侵害。如果您不打算信任现有的审核机制来阻止用户窥探套接字连接,然后你就卡住了,超级用户可以使用适当的工具(例如,gdb
附加到你的进程)窥探任何解决方案。
@jxh - 我同意 tcpdump。我将套接字和隐藏文件方法视为相似。两者都会产生类似的间接费用。
【参考方案1】:
如果用户可以使用 tcpdump,则该用户具有 root 访问权限。该用户还可以在您的 Java 程序上安装一个调试器,并在数据加密之前查看它的确切功能。实现您想要的唯一方法是采用全面的混淆技术和加密技术,就像 Skype 客户端所做的那样1。
但既然你同时说,数据不是那么敏感,这似乎有点矫枉过正。也许一个简单的混淆技术,这样的输出对不经意的观察者是不可见的就足够了? (就像Rocker 建议的那样。)要么,要么确保“不受信任”的用户在您的系统(Java + C 程序)运行的服务器上没有 root 访问权限。
一个不错的2混淆和可能是一个很好的权衡,将使用 mmap()(或 System V shared mem)进行通信。
如果您使用MAP_LOCKED 选项和MAP_ANONYMOUS,内存区域将不会在磁盘上结束。 MAP_LOCKED 阻止它进行交换,MAP_ANONYMOUS 告诉操作系统不要使用备份文件。
另外,您是否考虑过使用 JNI 来访问您的 C 代码?这样,您的 C 代码将成为 Java 进程的一部分,而不受信任的用户将需要一个调试器来监视正在发生的事情。
1 Skype 客户端并非不可能被窥探,但非常困难。虽然这是有代价的,但在保持混淆技术完好无损的同时维护代码必须付出额外的代价。这也是 Skype 编码人员和研究人员之间的军备竞赛,他们试图弄清楚它是如何工作的。
2 这会让我停止很长时间,我会在弄清楚到底发生了什么之前,我必须阅读大量有关调试技术的内容,然后进行大量工作以弄清楚两个程序之间“谈论”了什么。一个更有才华的人可能最多在一个下午就能破译一切。
【讨论】:
所以,类似 int prot = (PROT_READ | PROT_WRITE);会足够好吗?不确定我是否理解如何确保没有文件也支持它。你能详细说明一下吗? @Sumit,我更新了提到 MAP_ANONYMOUS 的答案。为了 MAP_LOCKED 成功,我想内存区域不应该太大。 是的,但我认为 Java 无法读取匿名映射文件。这是我之前考虑的一个选项。如果可以用 Java 读取 ANON 映射文件,我想更正一下。 @Sumit,如果您使用 C 从 JNI 中执行 Java“可以”。 @Sumit,在这种情况下,我的意思是做足够的 Java -> JNI 来读/写 C 程序也可以访问的内存区域。没什么特别的。【参考方案2】:避免用户过度使用数据的最佳方法是 encr。如果您仍然想要其他机制而不是一种方式是 - 如果您的数据包含多种数据类型的混合,即 int float char* 等,则将数据转换为二进制格式。用户不能直接读取二进制数据。但是如果他愿意,强烈的用户可以转换回原始格式。它的那种 encr 只有用户可以根据需要对其进行解密。
但不建议这样做。使用一些标准编码。
【讨论】:
加密密钥将存储在哪里? 标准 encr 机制包含编码器和解码器。在 sendind 编码数据之前发送它。 recver 结束recv,解码并使用它。如果您使用自己的 encr 和 decr,则发送和接收部分在您手中。您可以在该传递密钥之后拥有自己的字符串格式,因此只要该特定字符串出现在该字符串之后,则在 recv 结束时,该字符串就是您要解密的密钥。我希望这能解答您的疑问 不,它没有。首先,编码和加密是两个完全不同的东西。在答案中,您在谈论编码的 cmets 中提到了加密(我假设 encr 表示加密)。第二件事,“标准encr机制”到底是什么意思。不管是什么,加密密钥存储在哪里。此外,如果密钥与加密数据一起发送,那么任何获得加密数据的人都可以解密它。 是的,我的意思是加密。通常,enc 密钥仅与数据一起发送,但在侧包中的特定位置发送。只有您知道该位置。 只要检查几个数据包,任何真正想要破解的人都可以在 5 分钟内破解该位置。使用混淆比使用这种不安全的加密要好得多。以上是关于将敏感数据从 C 传递到 Java的主要内容,如果未能解决你的问题,请参考以下文章