我想清楚“不可变”的字符串内容 [英] I want to clear "immutable" string contents

查看:99
本文介绍了我想清楚“不可变”的字符串内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好!


我想清除敏感信息中的字符串内容

,如密码等。

在某些情况下,密码将始终显示为字符串

或其他情况。而且我感到不安,让它无限期地挂在记忆中

(特别是在字符串被Interned的情况下)。


所以在字符串不是的情况下是leats实习生我建议:


string pass = Console.ReadLine();

if(string.IsInterned(pass)== null)

{

不安全

{

固定(无效* pv =通行证)

{

char * pb =(char *)pv;

for(int i = 0; i< pass.Length; ++ i)

pb [ i] =''0'';

}

}

}

Console.WriteLine(通过) ;


注意:不需要显式的RuntimeHelpers.OffsetToStringData。


你们对此有何看法?

解决方案

用新值覆盖它有什么问题?


pass = new String();


因为这仍然是同一个变量,我不认为应用程序会挂起旧的

值 - 罪那时他们是不可想象的。对?你是否过度思考这个问题?b $ b或者我错过了什么?


" cppdev" < CP ***** @ yahoo.com>在消息中写道

新闻:fc ************************* @ posting.google.co m ... <你好全部!

我想清除敏感信息中的字符串内容,比如密码等等。

它''总是密码在某些时候或其他地方显示为字符串的情况。而且我感到不安,让它无限期地挂在记忆中(特别是在字符串是Interned的情况下)。

所以在字符串未被实习的情况下,我建议:

string pass = Console.ReadLine();
if(string.IsInterned(pass)== null)
{
不安全
{
固定( void * pv = pass)
{*> char * pb =(char *)pv;
for(int i = 0; i< pass.Length; ++ i)
pb [i] =''0'';
}
}
}
Console.WriteLine(传递);

注意:显式的RuntimeHelpers。不需要OffsetToStringData。

您对此有何看法?





" Frank Drebin <无***** @ imsickofspam.com>在留言中写道

news:bJ ********************** @ newssvr28.news.prodi gy.com ...

用新值覆盖它有什么问题?

pass = new String();


那是行不通的。你所做的只是创建一个新的

String对象并替换指针。旧字符串

对象仍在内存中,标记为垃圾回收。

但是,垃圾收集器可能无法运行一对

分钟在发生这种情况之前,一个饼干可能会扫描并看到




字符串是不可变的,期间。

无法在字符串创建后替换字符串中的内容。


唯一的选择可能是使用值类型

仅在方法的生命周期内将其保留在堆栈中

使用它。您可以编写自己的基本

字符串类,它与char []一起使用(也是

a值类型)。


这样就没有分配堆内存,因此很难追踪到
。但是,当密码在堆栈上可见
时,总有几秒钟就会有
。也许用于处理

char []的值类型中的一些聪明(和丑陋)

编码会在预定义的

空格中插入随机字符抛弃一个随意的观察者。

因为这仍然是同一个变量,我不认为应用程序挂起
到旧值 - 因为它们在那时是不可想象的。对?你是否过度思考这个问题?或者我错过了什么?


内存尚未被覆盖。堆内存仍然是
仍然分配,CLR仍然有对这个

内存插槽的引用。该参考文件将被标记为垃圾

收集并在下一个可用的
GC插槽中收集/免费提供。但是,目前尚不清楚.NET是否会将内存零容纳出来,或者只是留在那里被覆盖

之后。我的猜测是它不会将内存清零。


或者,您可能会在C#中使用不安全的代码来获取

a内存块,其中你工作时存储密码

(当然你必须使用旧式的

C字符串逻辑很难看)然后把它归零

完成后你自己。


-c

" cppdev" < CP ***** @ yahoo.com>在消息中写道
新闻:fc ************************* @ posting.google.co m ...

大家好!

我想从密码等敏感信息中清除字符串内容。

这总是一个案例该密码将在某些时候显示为字符串
或其他。并且我感到不安,让它无限期地挂在内存
中(特别是在字符串被Interned的情况下)。

所以在字符串未被实习的情况下,我建议:

string pass = Console.ReadLine();
if(string.IsInterned(pass)== null)
{
不安全
{
固定( void * pv = pass)
{*> char * pb =(char *)pv;
for(int i = 0; i< pass.Length; ++ i)
pb [i] =''0'';
}
}
}
Console.WriteLine(传递);

注意:显式的RuntimeHelpers。不需要OffsetToStringData。

您对此有何看法?






" Frank Drebin" <无***** @ imsickofspam.com>在消息中写道

新闻:KC ********************** @ newssvr28.news.prodi gy.com ...

理解..

如果你这样做:

pass = new String();
pass =" mypassword";
pass =" ;

你是否建议同样的事情发生?在上面的
示例中,有pass的当前版本。和两个旧版本的
标记为gc?由于内存已经分配 - 为什么它只是
改变实际的内存数据?


通过变量只是一个参考。


新 .NET中的operator返回一个REFERENCE到堆上新创建的对象。


在C ++中,例子是:


String * pass = new System :: String(" 1");

pass = new System :: String(" 2,mypassword");

pass = new System :: String(" 3,");


所以你看,字符串1和2仍在那里,你只是

摆脱了你的参考。


[转述,这不一定是100%准确]

[是的,我知道.NET不做引用计数,但

这只是为了说明]

在幕后,当调用新运算符时,

它在堆上分配内存并创建

a新的Reference对象来存储指针。


它有一些类型的Referers集合和它

给你一个Referers令牌。


所以通过值实际上只包含一个

referer令牌到实际参考。


当变量/令牌超出范围时,或者你

为你的变量/令牌指定null,.NET将

删除你的令牌。


这很方便因为.NET可以移动内存

随时随地更新

实际指针而不会影响你的代码




当没有更多的引用时,.NET标记

垃圾收集指针。


所以你看,只因为你不再拥有

a指向字符串1和2,它并不意味着

没有人指向它。


1,2,和3所有都是在堆上的不同

部分中的唯一对象并且通过在所有3个案例中都有一个完全

不同的值。


仍然分配1和2的内存,

甚至收集垃圾之后,它可能会实际上没有被清零或覆盖,直到

a稍晚。

其次,是什么密码所需的最终形式以及为什么
不能尽快将其隐藏起来。例如,如果密码是来自文本框的
- sha1将密码哈希到字符串中 - 那么你不需要b $ b来担心它..


不幸的是,这是一个非常复杂的问题。 TextBox

有一个String类型的Text属性,它有一个

密码的副本。


当你得到一个参考从中生成

哈希的字符串,可能会创建另一个副本。


最终可能会有1-3份副本内存中的字符串:(


< snip>


" Chad Myers" < cm **** @ N0.SP.4M.austin.rr.com>在消息中写道
新闻:8r ******************* @ twister.austin.rr.com ..


Frank Drebin< no ***** @ imsickofspam.com>写在消息中
新闻:bJ **********************@newssvr28.news.prodi gy.com ...

什么是麻烦只是用新值覆盖它?

pass = new String();



那是行不通的。你所做的只是创造一个新的
String对象并替换指针。旧的字符串
对象仍然在内存中,标记为垃圾收集。
然而,垃圾收集器可能无法运行几分钟,并且有可能一个黑客可以在此之前扫描并查看它发生。

字符串是不可变的,期间。创建字符串后无法替换字符串中的内容。

唯一的选择可能是使用一种值类型,仅将其保留在堆栈中其使用方法的生命。您可以编写自己的基本
字符串类,它与char [](也是值类型)一起使用。

这样就不会分配堆内存并且 char []的Value类型中的一些聪明(和丑陋)
编码会在预定义的空格中插入随机字符以抛弃一个不经意的观察者。
< blockquote class =post_quotes>由于这仍然是同一个变量,我不认为应用程序在

上挂起
到旧的

值 - 因为它们在那时是不可想象的。对?是



你是否过度思考问题?或者我错过了什么?



内存尚未被覆盖。堆内存仍然已分配,CLR仍然具有对该内存插槽的引用。该参考文件将被标记为垃圾收集,并在下一个可用的GC插槽中收集/免费提供。然而,目前还不清楚.NET是否会将内存归零,或者只是将其留在那里以便稍后覆盖。我的猜测是它不会将内存清零。

或者,您可能会在C#中使用不安全的代码来获取存储密码的内存块
当你工作的时候(当然你必须使用丑陋的旧式的C字符串逻辑),然后在你完成时把它归零。

-c


" cppdev" < CP ***** @ yahoo.com>在消息中写道
新闻:fc ************************* @ posting.google.co m ...
> ;大家好!
>
>我想从敏感信息中清除字符串内容
>如密码等。
>
>密码将在某个
点>处显示为字符串。或其他。我感到不安,把它挂在记忆中


无限期地

> (特别是在字符串被Interned的情况下)。
>
>因此,对于字符串未被实习的情况,我建议:
>
> string pass = Console.ReadLine();
> if(string.IsInterned(pass)== null)
> {
>不安全
> {
> fixed(void * pv = pass)
> {
> char * pb =(char *)pv;
> for(int i = 0; i< pass.Length; ++ i)
> pb [i] =''0'';
> }
> }
> }
> Console.WriteLine(pass);
>
>注意:不需要显式的RuntimeHelpers.OffsetToStringData。
>
>您对此有何看法?





Hi All!

I want to clear the string contents from sensitive information
such as passwords, and etc.

It''s always a case that password will appear as string at some point
or another. And i feel uneasy leaving it hanging in memory indefinitely
(especially in case when string is Interned).

So at leats for the case when string is not interned i propose:

string pass = Console.ReadLine();
if (string.IsInterned(pass) == null)
{
unsafe
{
fixed(void* pv = pass)
{
char* pb = (char*)pv;
for(int i =0; i<pass.Length; ++i)
pb[i] = ''0'';
}
}
}
Console.WriteLine(pass);

Note: explicit RuntimeHelpers.OffsetToStringData is not needed.

What do you all think about this?

解决方案

What''s the trouble with just overwriting it with a new value?

pass = new String();

Since this is still the same variable, I don''t think the app hangs on to old
values - since they are unretreivable at that point. Right? Are you
overthinking the problem? Or am I missing something?

"cppdev" <cp*****@yahoo.com> wrote in message
news:fc*************************@posting.google.co m...

Hi All!

I want to clear the string contents from sensitive information
such as passwords, and etc.

It''s always a case that password will appear as string at some point
or another. And i feel uneasy leaving it hanging in memory indefinitely
(especially in case when string is Interned).

So at leats for the case when string is not interned i propose:

string pass = Console.ReadLine();
if (string.IsInterned(pass) == null)
{
unsafe
{
fixed(void* pv = pass)
{
char* pb = (char*)pv;
for(int i =0; i<pass.Length; ++i)
pb[i] = ''0'';
}
}
}
Console.WriteLine(pass);

Note: explicit RuntimeHelpers.OffsetToStringData is not needed.

What do you all think about this?




"Frank Drebin" <no*****@imsickofspam.com> wrote in message
news:bJ**********************@newssvr28.news.prodi gy.com...

What''s the trouble with just overwriting it with a new value?

pass = new String();
That doesn''t work. All you''re doing is creating a new
String object and replacing the pointer. The old string
object is still in memory, flagged for garbage collection.
However, the garbage collector may not run for a couple
minutes and it''s possible a cracker could scan and see
it before that happens.

Strings are immutable, period. There is no way to
replace the contents in a string once it is created.

The only option might be to use a value type which
keeps it on the stack only for the life of the method
in which its used. You might write your own basic
string class which works with char[] (which is also
a value type).

That way no heap memory is ever allocated and
therefore harder to track down. However, there is
always that few seconds when the password is
visible on the stack. Perhaps some clever (and ugly)
coding in the Value type for working with the
char[] would insert random characters at predefined
spaces to throw off a casual observer.
Since this is still the same variable, I don''t think the app hangs on to old values - since they are unretreivable at that point. Right? Are you
overthinking the problem? Or am I missing something?
The memory has not yet been overwritten. The heap memory is
still allocated and the CLR still has a reference to that
memory slot. The reference will be flagged for garbage
collection and collected/free''d at the next available
GC slot. However, it''s not clear whether .NET will zero-out
the memory, or just leave it there to be overwritten
later. My guess is that it DOES NOT zero-out the memory.

Alternatively, you might use unsafe code in C# to get
a block of memory in which to store the password
while you work with (of course you have to use old-style
C string logic which is ugly) and then zero it out
yourself when you''re done.

-c

"cppdev" <cp*****@yahoo.com> wrote in message
news:fc*************************@posting.google.co m...

Hi All!

I want to clear the string contents from sensitive information
such as passwords, and etc.

It''s always a case that password will appear as string at some point
or another. And i feel uneasy leaving it hanging in memory indefinitely (especially in case when string is Interned).

So at leats for the case when string is not interned i propose:

string pass = Console.ReadLine();
if (string.IsInterned(pass) == null)
{
unsafe
{
fixed(void* pv = pass)
{
char* pb = (char*)pv;
for(int i =0; i<pass.Length; ++i)
pb[i] = ''0'';
}
}
}
Console.WriteLine(pass);

Note: explicit RuntimeHelpers.OffsetToStringData is not needed.

What do you all think about this?





"Frank Drebin" <no*****@imsickofspam.com> wrote in message
news:KC**********************@newssvr28.news.prodi gy.com...

Understood..

And if you did this:

pass = new String();
pass = "mypassword";
pass = " ";

Are you suggesting the same thing happens? In that in the above example, there is the current version of "pass" and two old versions that are flagged for gc? Since the memory is already allocated - why wouldn''t it just change the actual memory data??
The "pass" variable is just a reference.

The "new" operator in .NET returns a REFERENCE to the
newly-created object on the heap.

In C++, the example would be:

String* pass = new System::String("1");
pass = new System::String("2, mypassword");
pass = new System::String("3, ");

So you see, string 1 and 2 are still there, you just
got rid of your reference them.

[paraphrased, this isn''t necessarily 100% accurate]
[yes, I know .NET doesn''t do reference counting, but
this is just for illustration]
Behind the scenes, when the new operator is called,
it allocates the memory on the heap and creates
a new Reference object to store the pointer in.

It has some type of collection of Referers and it
gives you a Referers token.

So the "pass" value actually just contains a
referer token to the actual reference.

When the variable/token goes out of scope, or you
assign null to your variable/token, .NET will
remove your token.

This is handy because .NET can move the memory
around whenever it wants and updates the
actual pointer without affecting your code
in any way.

When there are no more referers, .NET flags
the pointer for garbage collection.

So you see, just because you no longer have
a pointer to Strings 1 and 2, it doesn''t mean
no one has a pointer to it.

1, 2, and 3 all are unique objects in different
parts onthe heap and "pass" has a completely
different value in all 3 cases.

The memory of 1 and 2 is still allocated,
and even after it''s garbage collected, it might
not actually get zeroed out or overwritten until
a little later.
Secondly, what is the ultimate form you need for the password and why not get it coverted as soon as possible. For example, if the password is coming from a textbox - sha1 hash the password into a string - then you don''t have to worry about it..
Unfortunately, this is a very complicated problem. TextBox
has a Text property of type String which has a copy of the
password.

When you get a ref of the string from which to generate
the hash, it''s possible that another copy might get created.

You might end up with 1-3 copies of the string in memory :(

<snip>

-c

"Chad Myers" <cm****@N0.SP.4M.austin.rr.com> wrote in message
news:8r*******************@twister.austin.rr.com.. .


"Frank Drebin" <no*****@imsickofspam.com> wrote in message
news:bJ**********************@newssvr28.news.prodi gy.com...

What''s the trouble with just overwriting it with a new value?

pass = new String();



That doesn''t work. All you''re doing is creating a new
String object and replacing the pointer. The old string
object is still in memory, flagged for garbage collection.
However, the garbage collector may not run for a couple
minutes and it''s possible a cracker could scan and see
it before that happens.

Strings are immutable, period. There is no way to
replace the contents in a string once it is created.

The only option might be to use a value type which
keeps it on the stack only for the life of the method
in which its used. You might write your own basic
string class which works with char[] (which is also
a value type).

That way no heap memory is ever allocated and
therefore harder to track down. However, there is
always that few seconds when the password is
visible on the stack. Perhaps some clever (and ugly)
coding in the Value type for working with the
char[] would insert random characters at predefined
spaces to throw off a casual observer.

Since this is still the same variable, I don''t think the app hangs on

to old

values - since they are unretreivable at that point. Right? Are


you overthinking the problem? Or am I missing something?



The memory has not yet been overwritten. The heap memory is
still allocated and the CLR still has a reference to that
memory slot. The reference will be flagged for garbage
collection and collected/free''d at the next available
GC slot. However, it''s not clear whether .NET will zero-out
the memory, or just leave it there to be overwritten
later. My guess is that it DOES NOT zero-out the memory.

Alternatively, you might use unsafe code in C# to get
a block of memory in which to store the password
while you work with (of course you have to use old-style
C string logic which is ugly) and then zero it out
yourself when you''re done.

-c


"cppdev" <cp*****@yahoo.com> wrote in message
news:fc*************************@posting.google.co m...
> Hi All!
>
> I want to clear the string contents from sensitive information
> such as passwords, and etc.
>
> It''s always a case that password will appear as string at some point > or another. And i feel uneasy leaving it hanging in memory


indefinitely

> (especially in case when string is Interned).
>
> So at leats for the case when string is not interned i propose:
>
> string pass = Console.ReadLine();
> if (string.IsInterned(pass) == null)
> {
> unsafe
> {
> fixed(void* pv = pass)
> {
> char* pb = (char*)pv;
> for(int i =0; i<pass.Length; ++i)
> pb[i] = ''0'';
> }
> }
> }
> Console.WriteLine(pass);
>
> Note: explicit RuntimeHelpers.OffsetToStringData is not needed.
>
> What do you all think about this?





这篇关于我想清楚“不可变”的字符串内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆