Giter VIP home page Giter VIP logo

simple-crypt's Introduction

simple-crypt

Simple, secure encryption and decryption for Python 2.7 and 3.

Now on pypi: pip install simple-crypt (note that the pypi name includes a hyphen).

This provides two functions, which encrypt and decrypt data, delegating all the hard work to the pycrypto library (which must also be installed).

Examples

The API

The two calls:

from simplecrypt import encrypt, decrypt

ciphertext = encrypt(password, 'my secret message')
plaintext = decrypt(password, ciphertext)

Interactive Use

A simple Python 3 program:

from binascii import hexlify
from getpass import getpass
from sys import stdin

from simplecrypt import encrypt, decrypt

# read the password from the user (without displaying it)
password = getpass("password: ")

# read the (single line) plaintext we will encrypt
print("message: ")
message = stdin.readline()

# encrypt the plaintext.  we explicitly convert to bytes first (optional)
ciphertext = encrypt(password, message.encode('utf8'))

# the ciphertext plaintext is bytes, so we display it as a hex string
print("ciphertext: %s" % hexlify(ciphertext))

# now decrypt the plaintext (using the same salt and password)
plaintext = decrypt(password, ciphertext)

# the decrypted plaintext is bytes, but we can convert it back to a string
print("plaintext: %s" % plaintext)
print("plaintext as string: %s" % plaintext.decode('utf8'))

Which, when run, produces something like the following (the actual encrypted message will be different each time, as a random salt is used for each message):

password: ******

message:
hello world
ciphertext: b'73630001b1c39575390d5720f2a80e7a06fbddbf2c844d6b8eaf845d4a9e140d46a54c6729e74b0ddeb1cb82dee81691123faf8f41900c5a6c5b755ed8ae195ff2410290bcb8dc2ee3a2126c594b711d'
plaintext: b'hello world\n'
plaintext as string: hello world

Also, it's perhaps worth noting that the overhead (the extra length of the encrypted data, compared to the message) is constant. It looks a lot here, because the message is very small, but for most practical uses should not be an issue.

Using Files

When the following program is run, if the file "encrypted.txt" does not exist, then it is created with the contents "10 green bottles".

If the file does exist, it is read, and the number of green bottles is reduced. If there are no green bottles left, then the file is deleted, otherwise it is written with the new number.

from simplecrypt import encrypt, decrypt
from os.path import exists
from os import unlink

PASSWORD = "secret"
FILENAME = "encrypted.txt"

def main():
    # read or create the file
    if exists(FILENAME):
        print("reading...")
        data = read_encrypted(PASSWORD, FILENAME)
        print("read %s from %s" % (data, FILENAME))
        n_bottles = int(data.split(" ")[0]) - 1
    else:
        n_bottles = 10
    # write the file
    if n_bottles > 0:
        data = "%d green bottles" % n_bottles
        print("writing...")
        write_encrypted(PASSWORD, FILENAME, data)
        print("wrote %s to %s" % (data, FILENAME))
    else:
        unlink(FILENAME)
        print("deleted %s" % FILENAME)

def read_encrypted(password, filename, string=True):
    with open(filename, 'rb') as input:
        ciphertext = input.read()
        plaintext = decrypt(password, ciphertext)
        if string:
            return plaintext.decode('utf8')
        else:
            return plaintext

def write_encrypted(password, filename, plaintext):
    with open(filename, 'wb') as output:
        ciphertext = encrypt(password, plaintext)
        output.write(ciphertext)

if __name__ == '__main__':
    main()

This program is included in src/simplecrypt/example-file.py and we can run it as follows:

> python3 src/simplecrypt/example-file.py
writing...
wrote 10 green bottles to encrypted.txt
> python3 src/simplecrypt/example-file.py
reading...
read 10 green bottles from encrypted.txt
writing...
wrote 9 green bottles to encrypted.txt
> 
...
> python3 src/simplecrypt/example-file.py
reading...
read 1 green bottles from encrypted.txt
deleted encrypted.txt
>

Speed

Both encryption and decryption are relatively slow. This is because the library is designed to make the key (the password) hard to guess (it uses a PBKDF, which can take a couple of seconds to run).

In simple terms, if an attacker tries to decrypt the data by guessing passwords, then they also have to wait for a couple of seconds for each guess. This stops an attacker from trying "thousands" of different passwords every second.

So the pause on encryption and decryption is actually a sign that the library is protecting you. If this is unacceptable for your program then you may need to look for a different solution. I'm sorry, but this is the trade-off I chose when writing simple-crypt.

Alternatives

This code is intended to be "easy to use" and "hard to use wrong". An alternative for more experienced users (who might, for example, want to use more rounds in the PBKDF, or an explicit key) is python-aead.

As far as I can tell, python-aead uses very similar algorithms to those found here.

Algorithms

The algorithms used follow the recommendations at http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html and http://www.daemonology.net/blog/2009-06-24-encrypt-then-mac.html, as far as I can tell:

  • The password is expanded to two 256 bit keys using PBKDF2 with a 256 bit random salt (increased from 128 bits in release 3.0.0), SHA256, and 100,000 iterations (increased from 10,000 in release 4.0.0).

  • AES256 CTR mode is used to encrypt the data with one key. The first 64 bits of the salt are used as a message nonce (of half the block size); the incremental part of the counter uses the remaining 64 bits (see section B.2 of http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf).

  • An encrypted messages starts with a 4 byte header ("sc" in ASCII followed by two bytes containing version data).

  • An SHA256 HMAC (of header, salt, and encrypted message) is calculated using the other key.

  • The final message consists of the header, salt, encrypted data, and HMAC, concatenated in that order.

  • On decryption, the header is checked and the HMAC validated before decryption.

The entire implementation is here.

Discussion and criticism of the design can be found on HN (also), codereview.stackexchange and crypto.stackexchange. Grateful thanks to all commentators (particularly marshray); mistakes remain mine.

Please note that the general design, based on the cryptographic right answers, is intended to give 128 bits of security - any attack would require around 2^128 guesses. This comes from birthday collisions on the 256 bit HMAC and random numbers (since release 3.0). AES256 is used because it provides additional security if, for example, some key bits are revealed through timing attacks (see link above or chapter 7 of Practical Cryptography).

Latest News

Release 4.1 obscures the output of the random number generator. This should not be necessary, but guards against a possible attack if the random number generator is compromised in some way. Functionality and interoperability are otherwise unchanged.

Release 4.0 increases the number of iterations used in the PBKDF (this will make encryption and decryption noticeably slower) and adds a reference to python-aead.

Release 3.0 increases the size of the salt used from 128 to 256 bits.

The header changes with each major version release (after 2.0), so data encrypted by previous releases can be detected and decrypted correctly. However, data encrypted by later major releases (after 2.0) cannot be decrypted by earlier releases (instead, an error with a helpful message is generated).

Release 2.0 was fully compatible with 1.0 on Python 3 (same API and identical results). However, thanks to d10n it also supported Python 2.7 (tested with Python 2.7.5, 3.0.1 and 3.3.2).

I (Andrew Cooke) am not sure Python 2.7 support is such a good idea. You should really use something like keyczar. But there seems to be a demand for this, so better the devil you know...

Warnings

  1. The whole idea of encrypting with a password is not so smart these days. If you think you need to do this, try reading about Google's keyczar which instead uses a keystore (unfortunately, at the time of writing, keyczar does not support Python 3, as far as I can tell, but that should change soon).

  2. When you call these routines the password is stored in memory as a Python string. This means that malicious code running on the same machine might be able to read the password (or even that the password could be written to swap space on disk). One way to reduce the risk is to have the crypto part of your code run as a separate process that exists for a limited time.

  3. All encrypted messages start with a 4 byte header (ASCII "sc", followed by the version number). So an adversary is able to recognize that the data are encrypted (and not simply random). You can avoid this by discarding the first 4 bytes of the encrypted data, but you must of course replace them before decrypting, and the code will not inter-operate between versions.

  4. I have considered extending the code to handle inputs larger than can be held in memory. While this is possible, the HMAC is not validated until decrypted data are returned. Which is asking for trouble - people are going to use the data as they are decrypted - and shows that the current design is inappropriate for such use. Someone needs to design a better solution (eg. with HMAC checks for each "block" - but even that allows data to be silently truncated at the end of a block).

(c) 2012-2015 Andrew Cooke, [email protected]; 2013 d10n, [email protected]. Released into the public domain for any use, but with absolutely no warranty.

simple-crypt's People

Contributors

andrewcooke avatar d10n avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simple-crypt's Issues

ImportError: No module named 'winrandom'

Had problem on Windows 7 and Python 3.5.2 (64bit) when importing simplecrypt the system complained:
ImportError: No module named 'winrandom'
Seems to be coming from Crypto.Random.random import getrandbits

Anyway as suggested here by @neRok00 following solved situation for me:

Problem is solved by editing string in crypto\Random\OSRNG\nt.py:
import winrandom
to
from . import winrandom

Encryption/Decryption is very slow

I use an alphanumeric key of size 8 to encrypt a 120 char long base64 encoded string. The encryption and decryption take 3-5 seconds. This is too slow for any real time application.

pycrypto depdency security vulnerability

Just a heads up, this was picked up by our automated scanning.

There is a security vulnerabiltiy in the pycrypto depdency: pycrypto/pycrypto#176
Tracked under a CVE: https://security-tracker.debian.org/tracker/CVE-2013-7459

Apparently they've fixed this on master, but no release (and I think that package is no longer maintained).

I see there are other issues (#20) relating to this lib - I don't have any concrete suggestions, but we'll be looking to move away from pycrpto in the near future.

Corrupted file after decrypt file using simplecrypt in python

I'm trying to encrypt and decrypt video using simplecrypt and everthing works perfectlly but the problem is after program decrypt the video Myvideo.mp4.enc to example-decrypt.mp4 the example-decrypt.mp4 not working "Corrupted file"

My code:

from simplecrypt import encrypt, decrypt


def encrypt_file(file_name, key):
    with open(file_name, 'rb') as fo:
        plaintext = fo.read()
    enc = encrypt(key, plaintext)
    with open(file_name + ".enc", 'wb') as fo:
        fo.write(enc)


def decrypt_file(file_name, dec_file, key):
    with open(file_name, 'rb') as fo:
        ciphertext = fo.read()
    dec = decrypt(key, ciphertext)
    with open(dec_file, 'wb') as fo:
        fo.write(dec)

encrypt_file('Myvideo.mp4', '29B9A1C18678C68B')
decrypt_file('Myvideo.mp4.enc', 'example-decrypt.mp4', '29B9A1C18678C68B')

How i can fix this please.

pycrypto dependency issues

it looks like pycrypto is hosted on not-pypi, and so there are a couple of problems.

  1. the version of setuptools in ubuntu precise apparently does not support SNI:
error: https://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.7a1.tar.gz hostname 'ftp.dlitz.net' doesn't match either of 'www.dlitz.net', ‘dlitz.net```
  1. pycrypto-2.7a1.tar.gz does not build:
    gcc -bundle -undefined dynamic_lookup -g -O2 -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -DHAVE_CONFIG_H build/temp.macosx-10.10-x86_64-3.4/src/AES.o -o build/lib.macosx-10.10-x86_64-3.4/Crypto/Cipher/_AES.so
    building 'Crypto.Cipher._AESNI' extension
    gcc -g -fwrapv -O3 -Wall -Wstrict-prototypes -g -O2 -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -DHAVE_CONFIG_H -Isrc/ -I/usr/local/Cellar/python3/3.4.3_2/Frameworks/Python.framework/Versions/3.4/include/python3.4m -c src/AESNI.c -o build/temp.macosx-10.10-x86_64-3.4/src/AESNI.o -maes
    src/AESNI.c:51:16: error: index for __builtin_shufflevector must be a constant integer
        keygened = _mm_shuffle_epi32(keygened, shuf);
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Library/Developer/CommandLineTools/usr/bin/../lib/clang/6.1.0/include/emmintrin.h:1290:12: note: expanded from macro '_mm_shuffle_epi32'
      (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si) _mm_set1_epi32(0), \
               ^
    src/AESNI.c:51:14: error: assigning to '__m128i' (vector of 2 'long long' values) from incompatible type 'void'
        keygened = _mm_shuffle_epi32(keygened, shuf);
                 ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from src/AESNI.c:225:
    src/block_template.c:779:79: warning: comparison of constant 0 with boolean expression is always false [-Wtautological-constant-out-of-range-compare]
            if (PCT_CounterBEType == NULL || PyType_Check((PyObject *)PCT_CounterBEType) < 0 ||
                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~
    src/block_template.c:780:77: warning: comparison of constant 0 with boolean expression is always false [-Wtautological-constant-out-of-range-compare]
                     PCT_CounterLEType == NULL || PyType_Check((PyObject *)PCT_CounterLEType) < 0 ||
                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~
    src/block_template.c:781:47: warning: comparison of constant 0 with boolean expression is always false [-Wtautological-constant-out-of-range-compare]
                     abiver == NULL || PyInt_CheckExact(abiver) < 0 || PyInt_AS_LONG(abiver) != PCT_CTR_ABI_VERSION)
                                                                ^ ~
    3 warnings and 2 errors generated.
    warning: GMP or MPIR library not found; Not building Crypto.PublicKey._fastmath.
    error: command 'gcc' failed with exit status 1

    ----------------------------------------
    Command "/Users/jchen/.venvs/simplecrypt/bin/python3.4 -c "import setuptools, tokenize;__file__='/var/folders/qd/0tb2zcxn6xj09fxm8cjv3ppr0000gn/T/pip-ib3bwjnh-build/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /var/folders/qd/0tb2zcxn6xj09fxm8cjv3ppr0000gn/T/pip-me6w9o4r-record/install-record.txt --single-version-externally-managed --compile --install-headers /Users/jchen/.venvs/simplecrypt/bin/../include/site/python3.4/pycrypto" failed with error code 1 in /var/folders/qd/0tb2zcxn6xj09fxm8cjv3ppr0000gn/T/pip-ib3bwjnh-build

A possible solution is using dependency_links in setup.py to pin to https://www.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.6.tar.gz.

Unable to install simple-crypt

Hi,
while installing on simplecrypt, I am getting below error;

warning: GMP or MPIR library not found; Not building Crypto.PublicKey._fastmat

building 'Crypto.Random.OSRNG.winrandom' extension
error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsof
C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/

Has anyone faced this issue and found any solution?

thanks in advance.

simplecrypt.DecryptionException: Bad password or corrupt / modified data.

I'm writing a simple remote shell as a client/server application in python 3.

I'm getting this error, when I'm trying to send a 'ps uax'. Other shell commands are fine, even 'ps' without the extra arguments.

I was wondering what could cause this:

decrypted = decrypt(KEY, data)
File "/usr/lib/python3.3/site-packages/simple_crypt-1.0.0-py3.3.egg/simplecrypt/__init__.py", line 65, in decrypt
File "/usr/lib/python3.3/site-packages/simple_crypt-1.0.0-py3.3.egg/simplecrypt/__init__.py", line 102, in _assert_hmac
simplecrypt.DecryptionException: Bad password or corrupt / modified data.

Bad performance?

While benchmarking unrelated code, I noticed that decrypt() is surprisingly slow (for me, at least). Decrypting a simple encrypted string takes over 3 seconds on a new MacBook Pro. Here's my test:

timeit.timeit("simplecrypt.decrypt('salt', binascii.unhexlify(b'73630002e80f352a44c78bd87d3b0715fed6f8e5b338f066bcd5ddecb4f0e7b5ac96fffff090c6cff365d26c0d80651bc48c3eda7f85828d021d319be2ca11029c08c0b543188517e37168e6'))", setup="import simplecrypt, binascii;", number=10)

Is this to be expected?

Doesn't work on Python 2.7.2+

Traceback (most recent call last):
File "crypto.py", line 46, in
plaintext = decrypt(password, ciphertext)
File "/home/david/workspace/cartouche/apps/utils/simplecrypt.py", line 56, in decrypt
_assert_not_string(data)
File "/home/david/workspace/cartouche/apps/utils/simplecrypt.py", line 79, in _assert_not_string
'you cannot use a string because no string encoding will accept all possible characters.')
utils.simplecrypt.DecryptionException: Data to decrypt must be bytes; you cannot use a string because no string encoding will accept all possible characters.

Ability to derive keys only once for multiple decrypts

Right now the keys are derived from scratch every single time decrypt is called. I have a lot of values that have been encrypted with the same password that I want to decrypt in bulk (config files with individual values encrypted). Right now it takes over a minute to decrypt about 20 secrets and it appears most of the time is spent here:

  File "/usr/local/lib/python2.7/site-packages/simplecrypt/__init__.py", line 127, in _expand_keys
    keys = _pbkdf2(_str_to_bytes(password), salt, 2*key_len, expansion_count)

Is this something you could add? Or like your description says should I just use something else if I want this feature?

Multiple exception types must be parenthesized error

When I run import simplecrypt in my python file. It encounters an error saying:

File "/home/codespace/.python/current/lib/python3.10/site-packages/simplecrypt/__init__.py", line 5, in <module>
    from Crypto.Random.random import getrandbits
File "/home/codespace/.python/current/lib/python3.10/site-packages/Crypto/Random/__init__.py", line 28, in <module>
    from Crypto.Random import OSRNG
File "/home/codespace/.python/current/lib/python3.10/site-packages/Crypto/Random/OSRNG/__init__.py", line 32, in <module>
    from Crypto.Random.OSRNG.posix import new
File "/home/codespace/.python/current/lib/python3.10/site-packages/Crypto/Random/OSRNG/posix.py", line 66
    except IOError, e:
           ^^^^^^^^^^
SyntaxError: multiple exception types must be parenthesized

Any help would be appreciated 👍🏻

getting incorrect password when im typing the same thing

File "/usr/local/lib/python2.7/dist-packages/simplecrypt/init.py", line 72, in decrypt
_assert_hmac(hmac_key, hmac, hmac2)
File "/usr/local/lib/python2.7/dist-packages/simplecrypt/init.py", line 116, in _assert_hmac
raise DecryptionException('Bad password or corrupt / modified data.')
simplecrypt.DecryptionException: Bad password or corrupt / modified data.

Add a license

I would like to port this to nixpkgs, however since no license is provided, it would have to be marked as non-free. I would appreciate it if you added a license to this project, so I can use it properly with nix.

Encryption for a UUID1 string is slow

I used a short salt (3 characters) to encrypt a UUID string (34 characters). It takes about 500ms. That's not acceptable if I apply this library in a web route handler.

Support large file encryption?

Hello,

May I ask how can I use simple-crypt to encrypt large file (like 2G, 3G) ?
Will it get error about RAM for such big file?

Thank you.

How can I encrypt a folder?

Encryption with Python is very interesting. I would like to encrypt and decrypt the EBeispielordner1 folder. It would also be interesting to have several
Can encrypt folders in a single slide, e.g.

E/Beispielordner1

E/Beispielordner2

E/Beispielordner3

I would like to start this program from the console without GUI.

How can I customize your code?

Of course there are many encryption programs, but it would be interesting to be able to use a Python encryption program without backdoor.

How to import?

I have tried pip install simplecrypt a couple times now and i haven't been able to find this package. How can I import it into my python scripts? I'll submit a PR with the instructions for others if you want, Thanks!!!

Code audits and security

Hello,

I have project where I would like to use simple-crypt, and I am wondering how safe to use it is, and if there has been any code security audits before.

Thanks

Python3.8 AttributeError: module 'time' has no attribute 'clock'

Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/simplecrypt/__init__.py", line 42, in encrypt salt = bytes(_random_bytes(SALT_LEN[LATEST]//8)) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/simplecrypt/__init__.py", line 137, in _random_bytes return _hide(bytearray(getrandbits(8) for _ in range(n))) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/simplecrypt/__init__.py", line 137, in <genexpr> return _hide(bytearray(getrandbits(8) for _ in range(n))) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/Crypto/Random/random.py", line 51, in getrandbits return mask & bytes_to_long(self._randfunc(ceil_div(k, 8))) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 202, in read return self._singleton.read(bytes) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 178, in read return _UserFriendlyRNG.read(self, bytes) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 129, in read self._ec.collect() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/Crypto/Random/_UserFriendlyRNG.py", line 77, in collect t = time.clock() AttributeError: module 'time' has no attribute 'clock'

Do not remove old versions from PyPi

With release 4.0 the old releases 3.x.x have been deleted from the PyPi index.
Old releases should not be removed from the index.

  • Every other PyPi package using the 3.x.x version is now incompatible if another endpoint already upgraded to 4.0.0.
  • If a user had a package installed which had the requirement "simple-crypt>=3.0.2" and installed the same package today with the given requirement string, both sides are unable to communicate because 4.0 is not compatible with 3.x

If the old releases were still present, a requirement string "simple-crypt=3.0.2" could be used and everything would be fine. But now the users of packages with the simple-crypt requirement are forced to upgrade.
Please don't remove the old releases.

ImportError: No module named KDF

I tried to import encrypt and decrypt:

from simplecrypt import encrypt, decrypt

I get the following error:

Traceback (most recent call last):
File "<pyshell#1>", line 1, in
from simplecrypt import encrypt, decrypt
File "/usr/local/lib/python2.7/dist-packages/simplecrypt/init.py", line 4, in
from Crypto.Protocol.KDF import PBKDF2
ImportError: No module named KDF

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.