bc-csharp icon indicating copy to clipboard operation
bc-csharp copied to clipboard

Securly overwrite BigInteger

Open schoenbornl opened this issue 6 years ago • 8 comments

I wanted to do some crypto with BigIntegers, but the it doesn't seem to be possible to delete them or securely overwrite them. Could you add such a method?

schoenbornl avatar Dec 05 '18 11:12 schoenbornl

Wouldn't assigning null to the BigInteger after operations be enough?

Xor-el avatar Dec 17 '18 12:12 Xor-el

I am using BigInteger to store key material and other sensitive data (so is bc-sharp). If I just derefernce the BigIntegers the garbage collector will mark the memory as free, but wont zero/overwrite it until it is allocated again ( if I understand that correctly). This means in theory it could be there indefinitely and since memory leaks exist, I would be a lot happier if I could just zero the underlying byte array

schoenbornl avatar Jan 16 '19 10:01 schoenbornl

@schoenbornl you are right. Setting a reference type to null means that it will be overwritten sometime in the future. However, BigInteger is a struct, which means that setting it to a value overwrites the memory right away. You can just set it to 0. (Unless you're using the nullable version, i.e. BigInteger?). What I am not sure about is whether all the underlying reference types get overwritten as well (the BigInteger implementation uses an uint[] to store data).

If you think about it, the sensitive data must be revealed in memory at some point in time in order to be used. An attacker would have the opportunity to read it anyways. The promise by GC that the data would be overwritten sometime in the future is enough, at least for my purposes.

sorashi avatar Jan 21 '19 23:01 sorashi

@sorashi, bouncycastle big integer implementation (which I feel the issue author is referring to) is a class not a struct.

Xor-el avatar Jan 22 '19 08:01 Xor-el

@sorashi, bouncycastle big integer implementation (which I feel the issue author is referring to) is a class not a struct.

ok, my fault

sorashi avatar Jan 22 '19 10:01 sorashi

Interesting quote on the RSAParameters documentation

RSAParameters is not encrypted in any way, so you must be careful when you use it with the private key information. In fact, none of the fields that contain private key information can be serialized. If you try to serialize an RSAParameters structure with a remoting call or by using one of the serializers, you will receive only public key information. If you want to pass private key information, you will have to manually send that data. In all cases, if anyone can derive the parameters, the key that you transmit becomes useless.

The purpose of RSA is to secure information during transmit, therefore the key privacy at the end-points is not so strict in most cases (there's usually symmetric encryption, but the key must get revealed when it's being used).

sorashi avatar Jan 22 '19 15:01 sorashi

Just faced the same problem. Generally, .NET apps must store secrets in System.SecureString or their own implementations of a similar concept.

Secrets should be stored in an unmanaged memory (because GC does not have to zero out the data during mark-sweep phase), and cleared out using SecureZeroMemory or a similar platform-specific function before being deallocated. Also, there should be a way to explicitly deallocate a secret as soon, as it is not needed anymore.

lostmsu avatar Nov 05 '19 22:11 lostmsu

SecureString doesn't really work and is probably being deprecated (https://github.com/dotnet/runtime/issues/30612) but netcore should be getting support for safely zeroing secrets without pinning/unmanaged memory (https://github.com/dotnet/runtime/issues/10480)

Frassle avatar Mar 24 '20 10:03 Frassle