Giter VIP home page Giter VIP logo

Comments (7)

abiusx avatar abiusx commented on August 17, 2024

Keep in mind that randomness comes with entropy, and it is hardly retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In case they are not, we are using openssl function (if available) that has 64 bits, which is definitely enough for any case.

The bits of randomness are not in par with bits of cryptography strength, and don't need to be. They just need to be unguessable!
-A


Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.com

On Sep 17, 2013, at 4:16 PM, SvenRtbg [email protected] wrote:

I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:

Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101

As you can see, there is a call to the function random(32), which promises to deliver 32 random characters.

That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).

Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).

Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min and $max, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.

And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes() would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand() would only issue 31 bits of randomness.

All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).

Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)

What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84

Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(), fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand() with as many calls as there should be bytes in the salt string.


Reply to this email directly or view it on GitHub.

from phpsec.

SvenRtbg avatar SvenRtbg commented on August 17, 2024

If the basic randomness can only generate 31 bits of different values,
the result is very easy to bruteforce.

Even though the hashing hides that very poor randomness, you will still
only generate 4294967295 different values.

Compare that to the possible 1,3407807929942597099574024998206e+154
values of a SHA512...

Another reference, which is talking about the cracking of 56-bit keys
within 250 days in 2006:
http://www.codinghorror.com/blog/2006/07/brute-force-key-attacks-are-for-dummies.html

I am a little bit concerned about your answer here. 31 bits of
randomness is WAY TOO FEW! In fact, it is a worthy target to brute-force
it. Using 100 requests in parallel, each taking 100ms, it will only take
50 days to scan the whole session id space.

Am 17.09.2013 23:29, schrieb AbiusX:

Keep in mind that randomness comes with entropy, and it is hardly retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In case they are not, we are using openssl function (if available) that has 64 bits, which is definitely enough for any case.

The bits of randomness are not in par with bits of cryptography strength, and don't need to be. They just need to be unguessable!
-A


Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.com

On Sep 17, 2013, at 4:16 PM, SvenRtbg [email protected] wrote:

I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:

Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101

As you can see, there is a call to the function random(32), which promises to deliver 32 random characters.

That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).

Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).

Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min and $max, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.

And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes() would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand() would only issue 31 bits of randomness.

All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).

Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)

What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84

Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(), fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand() with as many calls as there should be bytes in the salt string.


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub:
#69 (comment)

from phpsec.

abiusx avatar abiusx commented on August 17, 2024

Well you need to bruteforce a weak randomness on the server, not on your own supercomputer :D That is the difference.
-A


Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.com

On Sep 17, 2013, at 5:43 PM, SvenRtbg [email protected] wrote:

If the basic randomness can only generate 31 bits of different values,
the result is very easy to bruteforce.

Even though the hashing hides that very poor randomness, you will still
only generate 4294967295 different values.

Compare that to the possible 1,3407807929942597099574024998206e+154
values of a SHA512...

Another reference, which is talking about the cracking of 56-bit keys
within 250 days in 2006:
http://www.codinghorror.com/blog/2006/07/brute-force-key-attacks-are-for-dummies.html

I am a little bit concerned about your answer here. 31 bits of
randomness is WAY TOO FEW! In fact, it is a worthy target to brute-force
it. Using 100 requests in parallel, each taking 100ms, it will only take
50 days to scan the whole session id space.

Am 17.09.2013 23:29, schrieb AbiusX:

Keep in mind that randomness comes with entropy, and it is hardly retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In case they are not, we are using openssl function (if available) that has 64 bits, which is definitely enough for any case.

The bits of randomness are not in par with bits of cryptography strength, and don't need to be. They just need to be unguessable!
-A


Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.com

On Sep 17, 2013, at 4:16 PM, SvenRtbg [email protected] wrote:

I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:

Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101

As you can see, there is a call to the function random(32), which promises to deliver 32 random characters.

That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).

Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).

Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min and $max, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.

And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes() would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand() would only issue 31 bits of randomness.

All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).

Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)

What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84

Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(), fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand() with as many calls as there should be bytes in the salt string.


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub:
#69 (comment)


Reply to this email directly or view it on GitHub.

from phpsec.

SvenRtbg avatar SvenRtbg commented on August 17, 2024

So what would be lost if we would actually use some maximum amount of
available random bits (e.g. 64 random bytes) instead of the current
limited randomess of 4 bytes?

Am 17.09.2013 23:44, schrieb AbiusX:

Well you need to bruteforce a weak randomness on the server, not on your own supercomputer :D That is the difference.
-A


Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.com

On Sep 17, 2013, at 5:43 PM, SvenRtbg [email protected] wrote:

If the basic randomness can only generate 31 bits of different values,
the result is very easy to bruteforce.

Even though the hashing hides that very poor randomness, you will still
only generate 4294967295 different values.

Compare that to the possible 1,3407807929942597099574024998206e+154
values of a SHA512...

Another reference, which is talking about the cracking of 56-bit keys
within 250 days in 2006:
http://www.codinghorror.com/blog/2006/07/brute-force-key-attacks-are-for-dummies.html

I am a little bit concerned about your answer here. 31 bits of
randomness is WAY TOO FEW! In fact, it is a worthy target to brute-force
it. Using 100 requests in parallel, each taking 100ms, it will only take
50 days to scan the whole session id space.

Am 17.09.2013 23:29, schrieb AbiusX:

Keep in mind that randomness comes with entropy, and it is hardly retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In case they are not, we are using openssl function (if available) that has 64 bits, which is definitely enough for any case.

The bits of randomness are not in par with bits of cryptography strength, and don't need to be. They just need to be unguessable!
-A


Notice: This message is digitally signed, its source and integrity are verifiable.
If you mail client does not support S/MIME verification, it will display a file (smime.p7s), which includes the X.509 certificate and the signature body. Read more at Certified E-Mail with Comodo and Thunderbird in AbiusX.com

On Sep 17, 2013, at 4:16 PM, SvenRtbg [email protected] wrote:

I think the was that session ids are generated is not very random. And this is concealed because of a layer of function calls that all look very good. Please follow me on the code path:

Let's start at Session::newSession https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101

As you can see, there is a call to the function random(32), which promises to deliver 32 random characters.

That function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is only a simple proxy and forwards the call to Rand::randStr(32).

Now that function https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109 actually does something: It grabs some randomness, hashes it into a string of finite length (which would lead to the whole functions so far to NOT deliver e.g. a random string of 2048 characters without hint or error - bad in itself, but not my point).

Ok, randomness... We do see a call to Rand::randRange() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with default parameters. This function does some checks, probably reverses $min and $max, grabs some randomness and then simply scales that into the range given. The range for default parameters is $min=0, $max = 2^31. So whatever the random generator delivers, it will here be reduced to 31 bits of randomness.

And the random number generator is in Rand::random() https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47 itself has no parameters. In an ideal situation, the very good random function openssl_random_pseudo_bytes() would be asked for FOUR bytes of randomness, which equals 32 bits. In absence of this function, the very bad random generator mt_rand() would only issue 31 bits of randomness.

All in all, the session ids generated by this code will only contain 31 bits of randomness, packed into a nice looking substring of SHA512, suggesting much more randomness being included (SHA512 itself is 128 hex chars long, leaving room for 64 bytes of randomness instead of only 4 bytes).

Even the PHP default session id hash has /* maximum 15+19+19+10 bytes */ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information - and this is criticized as "attackable" by some. (see https://github.com/php/php-src/blob/master/ext/session/session.c#L309)

What are good sources of randomness? I think a good example is given in the random salt generation of the password_hash library: https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84

Plenty of sources are being asked, in the hope to find some good randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(), fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand() with as many calls as there should be bytes in the salt string.


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub:
#69 (comment)


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub:
#69 (comment)

from phpsec.

rash805115 avatar rash805115 commented on August 17, 2024

Hello Sven,
I get your point... (though I did not understood all of it ... like "SHA512
itself is 128 hex chars long, leaving room for 64 bytes of randomness
instead of only 4 bytes"...what does this means ? )..

Now the test cases you sent obviously fails and proves the point...so
here's what we can do (any one of them):

  1. we can remove all the codes from the random library and replace it
    with mcrypt_create_iv()
    OR openssl_random_pseudo_bytes()...

  2. we can remove the capping of 31 bits and increase it to say 64
    bits...then we can increase the random bits needed in openssl function from
    4 to say 46...and then replace the call to mt_rand with as
    many occurrences as bytes needed.

  3. I dont know if this will work, but for a given length, if the length is
    greater than 32, then we can call the random function as many times until
    we get the whole string as required by the developer. i.e if the
    requirement is of 1024 bytes, then we can call the random function 1024/32
    times and then concatenate each of the result to produce a 1024 character
    random string.

On Tue, Sep 17, 2013 at 5:46 PM, SvenRtbg [email protected] wrote:

So what would be lost if we would actually use some maximum amount of
available random bits (e.g. 64 random bytes) instead of the current
limited randomess of 4 bytes?

Am 17.09.2013 23:44, schrieb AbiusX:

Well you need to bruteforce a weak randomness on the server, not on your
own supercomputer :D That is the difference.
-A


Notice: This message is digitally signed, its source and integrity are
verifiable.
If you mail client does not support S/MIME verification, it will display
a file (smime.p7s), which includes the X.509 certificate and the signature
body. Read more at Certified E-Mail with Comodo and Thunderbird in
AbiusX.com

On Sep 17, 2013, at 5:43 PM, SvenRtbg [email protected] wrote:

If the basic randomness can only generate 31 bits of different values,
the result is very easy to bruteforce.

Even though the hashing hides that very poor randomness, you will still
only generate 4294967295 different values.

Compare that to the possible 1,3407807929942597099574024998206e+154
values of a SHA512...

Another reference, which is talking about the cracking of 56-bit keys
within 250 days in 2006:

http://www.codinghorror.com/blog/2006/07/brute-force-key-attacks-are-for-dummies.html

I am a little bit concerned about your answer here. 31 bits of
randomness is WAY TOO FEW! In fact, it is a worthy target to brute-force
it. Using 100 requests in parallel, each taking 100ms, it will only take
50 days to scan the whole session id space.

Am 17.09.2013 23:29, schrieb AbiusX:

Keep in mind that randomness comes with entropy, and it is hardly
retrived in a computer system.
SHA512 does not have 64 bytes of randomness, it has as many bytes of
randomness as its input has, which can be just a few bits.
32 bits of randomness (even 31 bits) are in most scenarios enough. In
case they are not, we are using openssl function (if available) that has 64
bits, which is definitely enough for any case.

The bits of randomness are not in par with bits of cryptography
strength, and don't need to be. They just need to be unguessable!
-A


Notice: This message is digitally signed, its source and integrity are
verifiable.
If you mail client does not support S/MIME verification, it will
display a file (smime.p7s), which includes the X.509 certificate and the
signature body. Read more at Certified E-Mail with Comodo and Thunderbird
in AbiusX.com

On Sep 17, 2013, at 4:16 PM, SvenRtbg [email protected]
wrote:

I think the was that session ids are generated is not very random.
And this is concealed because of a layer of function calls that all look
very good. Please follow me on the code path:

Let's start at Session::newSession
https://github.com/OWASP/phpsec/blob/master/libs/session/session.php#L101

As you can see, there is a call to the function random(32), which
promises to deliver 32 random characters.

That function
https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L25 is
only a simple proxy and forwards the call to Rand::randStr(32).

Now that function
https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L109actually does something: It grabs some randomness, hashes it into a string
of finite length (which would lead to the whole functions so far to NOT
deliver e.g. a random string of 2048 characters without hint or error - bad
in itself, but not my point).

Ok, randomness... We do see a call to Rand::randRange()
https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L87 with
default parameters. This function does some checks, probably reverses $min
and $max, grabs some randomness and then simply scales that into the range
given. The range for default parameters is $min=0, $max = 2^31. So whatever
the random generator delivers, it will here be reduced to 31 bits of
randomness.

And the random number generator is in Rand::random()
https://github.com/OWASP/phpsec/blob/master/libs/core/random.php#L47itself has no parameters. In an ideal situation, the very good random
function openssl_random_pseudo_bytes() would be asked for FOUR bytes of
randomness, which equals 32 bits. In absence of this function, the very bad
random generator mt_rand() would only issue 31 bits of randomness.

All in all, the session ids generated by this code will only contain
31 bits of randomness, packed into a nice looking substring of SHA512,
suggesting much more randomness being included (SHA512 itself is 128 hex
chars long, leaving room for 64 bytes of randomness instead of only 4
bytes).

Even the PHP default session id hash has /* maximum 15+19+19+10 bytes
*/ = 63 bytes of pseudo-randomness and not-that-easy-to-guess information -
and this is criticized as "attackable" by some. (see
https://github.com/php/php-src/blob/master/ext/session/session.c#L309)

What are good sources of randomness? I think a good example is given
in the random salt generation of the password_hash library:
https://github.com/ircmaxell/password_compat/blob/master/lib/password.php#L84

Plenty of sources are being asked, in the hope to find some good
randomness:
mcrypt_create_iv(), openssl_random_pseudo_bytes(),
fopen('/dev/urandom', 'r') - and only then, as a last resort, mt_rand()
with as many calls as there should be bytes in the salt string.


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub:
#69 (comment)


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub:
#69 (comment)


Reply to this email directly or view it on GitHubhttps://github.com//issues/69#issuecomment-24625266
.

Regards,
Rahul Chaudhary
Ph - 412-519-9634

from phpsec.

SvenRtbg avatar SvenRtbg commented on August 17, 2024

SHA512 produces a hash string of 128 hex characters. On hex character represents 4 bits, so 128 hex characters are 64 bytes. So SHA512 can have the whole range of 64 bytes of different values - which is about 2^(64*8) or 2^512.

What to do? First, get a clear picture of what this function should return: Rand::randstr($length)

It sounds like "random string of length X" - what does this include?

  1. String length must be of the requested length. If I ask for one million characters, I must get them - or I must get an error stating that I was asking for too much, if there is a technical limit and I am only allowed to ask for a maximum of 1000 characters for example.
  2. How many different characters do I get at best? Technically, there are some options: a) Any byte from 0..255 b) only printable character bytes from 32..255 (excluding some at around 128..160) c) only hexadecimal characters "0".."9" + "a".."f"

For optimal randomness, the return string should contain as many different characters as possible. But it should also return a feasible selection of characters for a purpose like random password generation. But even if it will only output hex, this is fine, but should be taken into account by the developer using it, because he must then ask for more characters to get the same amount of possible different values.

Now the random generation: I'd really just copy the approach from the password API I linked. That part will actually produce any number of random characters - and if used directly by Rand::randstr, would also eliminate the problem there, with the output being "any byte in the range 0..255".

from phpsec.

islamoc avatar islamoc commented on August 17, 2024

Those links maybe useful
https://www.grc.com/js/uheprng.js
https://www.grc.com/otg/uheprng.htm

from phpsec.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.