Questions about SRP algorithm - security

I trying to use SRP algorithm but I have some questions:
Is that a good choice to use for registration and authorization SRP algorithm with SSL/TLS? And for all other transmission using just SSL/TLS?
I will use C# Sockets for implementation.
How to generate g, k, N? Is it safe to use these like app constants?
Is that SRP algorithm right?
//M-modulus, g-generator, k-multiplier, I-username, p-password, s-salt, v-pass verifier
Registration:
Client: s = randomString(); x = Hash(s, p); v = g^x %N;
sendToServer(I, s, v);
Server: save(I, s, v);
Authorization:
Client: a = random(); A = g^a %N;
sendToServer(I, A);
Server: if(A != 0) { b=random(); B = k*v + g^b %N;}
sendToClient(B, s);
u = Hash(A, B);
if(u == 0) abortConnection();
Client: if(B == 0) abortConnection();
u = Hash(A, B);
if(u == 0) abortConnection();
x = Hash(s, p);
S = ((B - k*(g^x %N)) ^ (a + u*x)) %N;
K = Hash(S);
Mc = Hash( Hash(N) XOR Hash(g), Hash(I), s, A, B, K);
sendToServer(M);
Server: S = ((A*(v^u %N)) ^ B) %N; K = Hash(S);
Ms = Hash( Hash(N) XOR Hash(g), Hash(I), s, A, B, K);
if(Mc == Ms) {Rs = Hash(A, M, K); sendToClient(Rs);}
Client: Rc = Hash(A, M, K);
if(Rc == Rs) ALL_OK();

I would be very careful when implementing any security protocol on your own. It is very hard to get it right and most often by implementing complex secure protocol you actually compromise the security of the system if you don't get it right (e.g. wrong memory management, vulnerabilities to timing attacks, etc).
The general advise is to use audited, trusted (open-source) and maintained library to do crypto stuff. These libraries usually offer better performance as well, as they use specialized HW cryptography instructions (e.g. AES is supported very well in modern hardware, making it fast and not vulnerable to timing attacks).
So in the light of my answer, have a look at the library http://bouncycastle.org/ which should provide implementation of the SRP protocol.
Moreover, you should really consider the use case. Are you developing super secure mail server for millions of users, or do you just want to secure your home server with holiday photos? In the first case it is probably worth having very robust and secure system with state-of-art security algorithms. In the latter case, it isn't - good password and SSL will do :-).

OpenSSL has TLS-SRP.
For the values you are looking for, read RFC 5054.
N, g, and k do not need to be secret.
Poorly chosen N and g can compromise the security of the
cryptographic calculations, so you should either know what you're
doing, or pick the values recommended in the RFC.
k, is calculated from N and g, so once you pick those, you can get k.
If you are interested in implementing the details of SRP, Google has code available in C - Google csrp code.

Related

Generating Hashes using .NET Core

I need to Generate Random Unique hashes to be used in password reset links in .Net Core. In ASP.NET Identity, I found this to be helpful, I am wondering if RNGCryptoServiceProvider still assures the randomness of the hashes generated.
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
{
var data = new byte[4];
for (int i = 0; i < 10; i++)
{
//filled with an array of random numbers
rngCsp.GetBytes(data);
//this is converted into a character from A to Z
var randomchar = Convert.ToChar(
//produce a random number
//between 0 and 25
BitConverter.ToUInt32(data, 0) % 26
//Convert.ToInt32('A')==65
+ 65
);
token.Append(randomchar);
}
}
What is the best way to achieve that using .net core and using which classes?
RNGCryptoServiceProvider is not in .NET Core. Use RandomNumberGenerator.Create() to get an instance of a CSPRNG that will work on the correct platform. Its API is the same as RNGCryptoServiceProvider, except that GetNonZeroBytes is missing (which I'd argue shouldn't have even been there).
On Windows, this will boil down to BCryptGenRandom in CNG, and on Linux it will use OpenSSL.

Is it possible to decrypt SHA1 [duplicate]

This question already has answers here:
Is it possible to reverse a SHA-1 hash?
(11 answers)
Closed 8 years ago.
Is it possible to decrypt(retain the actual string) the password which is saved in db using SHA1 algorithm.
Example:If password is "password" and it is stored in db as "sha1$4fb4c$2bc693f8a86e2d87f757c382a32e3d50fc945b24",is any chance to retain the same "password"(string) from "sha1$4fb4c$2bc693f8a86e2d87f757c382a32e3d50fc945b24"
SHA1 is a cryptographic hash function, so the intention of the design was to avoid what you are trying to do.
However, breaking a SHA1 hash is technically possible. You can do so by just trying to guess what was hashed. This brute-force approach is of course not efficient, but that's pretty much the only way.
So to answer your question: yes, it is possible, but you need significant computing power. Some researchers estimate that it costs $70k - $120k.
As far as we can tell today, there is also no other way but to guess the hashed input. This is because operations such as mod eliminate information from your input. Suppose you calculate mod 5 and you get 0. What was the input? Was it 0, 5 or 500? You see, you can't really 'go back' in this case.
SHA1 is a one way hash. So you can not really revert it.
That's why applications use it to store the hash of the password and not the password itself.
Like every hash function SHA-1 maps a large input set (the keys) to a smaller target set (the hash values). Thus collisions can occur. This means that two values of the input set map to the same hash value.
Obviously the collision probability increases when the target set is getting smaller. But vice versa this also means that the collision probability decreases when the target set is getting larger and SHA-1's target set is 160 bit.
Jeff Preshing, wrote a very good blog about Hash Collision Probabilities that can help you to decide which hash algorithm to use. Thanks Jeff.
In his blog he shows a table that tells us the probability of collisions for a given input set.
As you can see the probability of a 32-bit hash is 1 in 2 if you have 77163 input values.
A simple java program will show us what his table shows:
public class Main {
public static void main(String[] args) {
char[] inputValue = new char[10];
Map<Integer, String> hashValues = new HashMap<Integer, String>();
int collisionCount = 0;
for (int i = 0; i < 77163; i++) {
String asString = nextValue(inputValue);
int hashCode = asString.hashCode();
String collisionString = hashValues.put(hashCode, asString);
if (collisionString != null) {
collisionCount++;
System.out.println("Collision: " + asString + " <-> " + collisionString);
}
}
System.out.println("Collision count: " + collisionCount);
}
private static String nextValue(char[] inputValue) {
nextValue(inputValue, 0);
int endIndex = 0;
for (int i = 0; i < inputValue.length; i++) {
if (inputValue[i] == 0) {
endIndex = i;
break;
}
}
return new String(inputValue, 0, endIndex);
}
private static void nextValue(char[] inputValue, int index) {
boolean increaseNextIndex = inputValue[index] == 'z';
if (inputValue[index] == 0 || increaseNextIndex) {
inputValue[index] = 'A';
} else {
inputValue[index] += 1;
}
if (increaseNextIndex) {
nextValue(inputValue, index + 1);
}
}
}
My output end with:
Collision: RvV <-> SWV
Collision: SvV <-> TWV
Collision: TvV <-> UWV
Collision: UvV <-> VWV
Collision: VvV <-> WWV
Collision: WvV <-> XWV
Collision count: 35135
It produced 35135 collsions and that's the nearly the half of 77163. And if I ran the program with 30084 input values the collision count is 13606. This is not exactly 1 in 10, but it is only a probability and the example program is not perfect, because it only uses the ascii chars between A and z.
Let's take the last reported collision and check
System.out.println("VvV".hashCode());
System.out.println("WWV".hashCode());
My output is
86390
86390
Conclusion:
If you have a SHA-1 value and you want to get the input value back you can try a brute force attack. This means that you have to generate all possible input values, hash them and compare them with the SHA-1 you have. But that will consume a lot of time and computing power. Some people created so called rainbow tables for some input sets. But these do only exist for some small input sets.
And remember that many input values map to a single target hash value. So even if you would know all mappings (which is impossible, because the input set is unbounded) you still can't say which input value it was.
Since SHA-1 maps several byte sequences to one, you can't "decrypt" a hash, but in theory you can find collisions: strings that have the same hash.
It seems that breaking a single hash would cost about 2.7 million dollars worth of computer time currently, so your efforts are probably better spent somewhere else.

Can I programmatically log into a website without storing the password in plaintext?

I do a number of projects that involve automatically submitting forms and/or retrieving data from websites. Some of these sites require username/password authentication. (These sites do not have APIs, so I am relying on screen scraping.)
Most of the tutorials I've seen store the username and password in the source code like any other POST data, e.g.:
string username = "someUserName";
string password = "somePassword";
// submit POST data...
But I know storing passwords in plain text is generally frowned upon. Is there an alternative method I should use?
The common way of storing a password is by hashing it. As most algorithms for hashing passwords are destructive, that is they can't be reversed, this wouldn't work for you.
An option would be to use a reversible hash, such as to base64 encode the password, but it isn't really a lot safer than storing it in plain text.
The best solution as far as I can see, would be to store the passwords in a database. If you are really worried about someone getting the usernames and passwords, you could encrypt them in the DB with encryption functions, or you could use a SQLite database which you would encrypt directly on the disk.
This way your code and login credentials are separated, and you can safely share your code with others without worrying about security.
A pattern we use is:
In your database table you have an encrypted column. This column contains data encrypted with a system-wide, long (128 bit), random secret key (usually stored in a configuration file).
The data in this encrypted column contains a separate (random) secret key used for each thirdparty service. With this password we encrypt the authentication details related to this thirdparty service.
Why this double encrypting?
You reduce the amount of passwords in plain text to a single one (the system-wide password). Because of this, key management is easier.
We create a long random secret key for each thirdparty service so that we can selectively decrypt the credentials for each thirdparty service and transfer them between systems if necessary. Having one of our secret keys stored outside the database also reduces the risk associated with both SQL-injection attacks (they 'only' get the database data) and with backups (configuration files are not included in the regular backup data).
The weakness is obviously the system-wide password. It needs to be in memory somewhere.
I'm no cryptographer, and I'm pretty sure the above is sub-optimal. However, it works, is manageable and lot safer than just storing the thirdparty service credentials in plain text.
I have a scraping project that needed this problem solved. My setup includes two separate servers. The first is the user front end web app. the second is a nodejs server that handles the scraping.
I handle encryption with openssl key pair encryption. I generate a key pair for the nodejs machine and give the public key to the front end web app. When a user registers their 3rd party credentials those credentials are encrypted with the public key and stored in a database.
The web app regularly selects a user's encrypted credentials and sends them to the node server where they are decrypted with the private key and used with the 3rd party for scraping.
After a quick search I found this article about using openssl and encrypting strings.
I realize this is a very old post but hopefully it helps the next person that stumbles onto this problem.
A very simple way to encrypt and decrypt is extended tiny encription algorithm (XTEA). I'm pasting the C++ code from wikipedia here, but keep in mind anyone could have changed it there.
#include <stdint.h>
/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
for (i=0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
}
v[0]=v0; v[1]=v1;
}
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}
You have to do two things:
1. Use HTTPS for login pages (if necessary)
2. Use password Encryption right after receiving it. An encoder is something like this:
private static String passwordEncryption(String oldPass){
String newPass = "";
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(oldPass.getBytes(), 0, oldPass.length());
newPass = new BigInteger(1,messageDigest.digest()).toString(16);
if (newPass.length() < 32) {
newPass = "0" + newPass;
}
return newPass;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return newPass;
}
And use MD5() function of MySql to compare the received password with the stored one.
There's no way to do it. it will need to be available to the script somewhere as plain text (or "reversible encryption").
Many Apis (including Amazon Web Services for example) will recommend setting credentials in a environment variable and this is probably as much safety as you can hope for.
Put it in your .bash_profile, double check perrmissions, and at least you can be sure it won't end up on github in a public repo.

Haskell: How does 'atomicModifyIORef' work?

Can someone explain how atomicModifyIORef works? In particular:
(1) Does it wait for a lock, or optimistically try and retry if there's contention (like TVar).
(2) Why is the signature of atomicModifyIORef different to the signature of modifyIORef? In particular, what is this extra variable b?
Edit: I think I've figured out the answer to (2), in that b is a value to be extracted (this can be empty if not needed). In a single threaded program, knowing the value is trivial, but in a multithreaded program, one may want to know what the previous value was at the time of the function being applied. I assume this is why modifyIORef doesn't have this extra return value (as such usages of modifyIORef with this return value probably should use atomicModifyIORef anyway. I'm still interested in the answer to (1) though.
Does it wait for a lock, or optimistically try and retry if there's contention (like TVar).
atomicModifyIORef uses an locking instruction on the underlying hardware architecture you're on, to swap the pointer to an allocated Haskell object in an atomic fashion.
On x86 it uses the cas intruction, exposed as a primitive to the language via atomicModifyMutVar#, which is implemented as a runtime service in Cmm as:
stg_atomicModifyMutVarzh
{
...
retry:
x = StgMutVar_var(mv);
StgThunk_payload(z,1) = x;
#ifdef THREADED_RTS
(h) = foreign "C" cas(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var, x, y) [];
if (h != x) { goto retry; }
#else
StgMutVar_var(mv) = y;
#endif
...
}
That is, it will try to do the swap, and retry otherwise.
The implementation of cas as a primitive shows how we get down to the metal:
/*
* Compare-and-swap. Atomically does this:
*/
EXTERN_INLINE StgWord cas(StgVolatilePtr p, StgWord o, StgWord n);
/*
* CMPXCHG - the single-word atomic compare-and-exchange instruction. Used
* in the STM implementation.
*/
EXTERN_INLINE StgWord
cas(StgVolatilePtr p, StgWord o, StgWord n)
{
#if i386_HOST_ARCH || x86_64_HOST_ARCH
__asm__ __volatile__ (
"lock\ncmpxchg %3,%1"
:"=a"(o), "=m" (*(volatile unsigned int *)p)
:"0" (o), "r" (n));
return o;
#elif arm_HOST_ARCH && defined(arm_HOST_ARCH_PRE_ARMv6)
StgWord r;
arm_atomic_spin_lock();
r = *p;
if (r == o) { *p = n; }
arm_atomic_spin_unlock();
return r;
#elif !defined(WITHSMP)
StgWord result;
result = *p;
if (result == o) {
*p = n;
}
return result;
So you can see that it is able to use an atomic instruction in Intel, on other architectures different mechanisms will be used. The runtime will retry.
atomicModifyIORef takes a r :: IORef a and a function f :: a -> (a, b) and does the following:
It reads the value of r and applies f to this value, yielding (a',b). Then the r is updated with the new value a' while b is the return value. This read and write access is done atomically.
Of course this atomicity only works if all accesses to r are done via atomicModifyIORef.
Note that you can find this information by looking at the source [1].
[1] https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-IORef.html#v:atomicModifyIORef

Adding a simple MAC to url parameters?

I want to add a simple kind of MAC to some of my URL parameters. This is only intended as an additional line of defense against application bugs and caching related problems/bugs, and not intended as any form of replacement of the actual login security in the application. A given business-object-id is already protected by backends to be limited to a single user.
So basically I'd like to add a short authentication code to my url parameters, on the size of 2-4 characters. I think I'd like to have a reversible function along the lines of f(business-data-id + logged-on-user-id + ??) = hash, but I am open to suggestions.
The primary intention is to stop id guessing, and to make sure that url's are fairly distinct per logged on user. I also don't want something big and clunky like an MD5.
Since you aren't looking for cryptographic quality, maybe a 24-bit CRC would fit your needs. While MD5 is "fast" in absolute terms, CRC is, relatively, "blindingly fast". Then the 3-byte CRC could be text-encoded into four characters with Base-64 encoding.
Here's a Java implementation of the check used for OpenPGP ASCII-armor checksums:
private static byte[] crc(byte[] data)
{
int crc = 0xB704CE;
for (int octets = 0; octets < data.length; ++octets) {
crc ^= (data[octets] & 0xFF) << 16;
for (int i = 0; i < 8; ++i) {
crc <<= 1;
if ((crc & 0x1000000) != 0)
crc ^= 0x1864CFB;
}
}
byte[] b = new byte[3];
for (int shift = 16, idx = 0; shift >= 0; shift -= 8) {
b[idx++] = (byte) (crc >>> shift);
}
return b;
}
I would hash a secret key (which is known only by the server), together with whatever you want to protect—probably the combination of object identifier and user identifier.
If what you want is basically MD5 but smaller, why not just use MD5 but just the last 4 characters? This doesn't add a huge blob to your urls, it's always 4 nice hex digits.
A quick question for which I'm sure there's a good answer for, but why not store this information in a cookie?
Then you could use something big and clunky like MD5 and your URLs would still be pretty.

Resources