在 Java 中,存储密码(例如密码)的旧方法是使用 char[],因为您可以在完成后覆盖其数据。然而,这已被证明是不安全的,因为垃圾收集器会在重组堆时复制东西。在某些架构上,当其他程序分配同一页面时,可能会释放一个页面,而 secret 将保留。
这非常难看,但是如果 secret 存储在线程的 run 方法的堆栈中怎么办?仍然需要注意优雅地终止线程,以便它可以将其数据清零,但这个问题也以旧方式存在。
我立即看到的一个主要问题是,我想不出一种安全的方法来将数据输入和输出容器。您可以通过使用具有非常小的内部缓冲区的流来最小化泄露 secret 的可能性,但最终您会遇到与 char[] 相同的问题。 [编辑:单个 private static byte 成员和标志是否有效?尽管这会将您限制为每个 ClassLoader 一个 secret 。这增加了更多的丑陋,但隐藏在编写良好的界面后面可能很容易。]
所以我有很多问题,真的。
堆栈在这些类型的攻击中是否比堆更安全?是否有任何纯 Java 机制以对这个问题有用的方式在两个不同的堆栈帧之间执行堆栈到堆栈的复制?如果没有,JVM 会支持字节码中的这种类型的操作吗?
[编辑:在人们过分担心之前,这更像是一个思想实验。我绝对无意“在生产中测试”或在任何当前项目中使用它。我意识到我正在谈论的内容非常丑陋,可能非常庞大,并且与整个 JVM 结构相悖。我只关心它是否可能,它是否真的实现了我的目标,以及实现它需要什么样的英雄主义。]
最佳答案
我会使用直接的 ByteBuffer。它使用的内存不会被复制,并且在 ByteBuffer 的生命周期内只在一个地方。顺便说一句,不要使用 clear() ,因为这只会重置位置。你可以用
覆盖它bb.clear();
while(bb.remaining() >= 8) bb.putLong(0);
while(bb.remaining() > 0) bb.put((byte) 0);
Is the stack any more secure from these types of attacks than the heap?
我不这么认为。
Are there any pure Java mechanisms to perform a stack-to-stack copy between two different stack frames in a manner that would be useful to this problem?
您可以将 secret 存储为一两个 long。
If not, would the JVM even support this type of operation in bytecode?
字节码是为支持 Java 而设计的,其功能与您在 Java 中的功能相比几乎没有。
I'm just interested in whether it's possible, whether it actually accomplishes my goals, and what kinds of heroics it would take to make it happen
按照我的建议使用直接的 ByteBuffer。 ;)
关于java - 是否可以在java中将 secret 存储在堆栈上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16697117/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案