Giter Site home page Giter Site logo

cryptoguard's People

Contributors

cryptoguardorg avatar dependabot[bot] avatar franceme avatar kelloggm avatar lordamit avatar rigority avatar sazzad114 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

cryptoguard's Issues

Small keysize RSA not detected

Hi, I'm conducting academic research on Java Cryptography API based misuse using your tool. After reading the paper and source codes, I believe that your team have implemented the rules to detect the RSA cipher with keysize < 2048 bits. I tried my test codes using 512-bit RSA , however, with no warnings. I also tried to use a default keysize (2048 bits) RSA to encrypt messages. Strangely, this time cryptoguard reported an issue saying : "Cause: Used default key size". I'm confused ,since by far, 2048-bit RSA is a secure cipher and cryptoguard arises a warning. Some improval in InsecureAssymCryptoFinder.java may help to solve this issue. I'm also trying to find ways to solve this missed-detection problem.

The test codes :

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import javax.xml.bind.DatatypeConverter;

public class RSA {
    /**
     * @param publicKey
     * @param srcBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public static byte[] encrypt(RSAPublicKey publicKey, byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        if(publicKey!=null){
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] resultBytes = cipher.doFinal(srcBytes);
            return resultBytes;
        }
        return null;
    }

    /**
     * @param privateKey
     * @param srcBytes
     * @return
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     */
    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] srcBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
        if(privateKey!=null){
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] resultBytes = cipher.doFinal(srcBytes);
            return resultBytes;
        }
        return null;
    }

    /**
     * @param args
     * @throws NoSuchAlgorithmException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws IOException
     */
    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException {
        String msg ="Super super secret message.Please keep it in mind.";
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // keyPairGen.initialize(512,new SecureRandom());
        keyPairGen.initialize(512);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
        RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();

        Cipher cipher = Cipher.getInstance("RSA");
        byte[] srcBytes = msg.getBytes();
        // byte[] resultBytes = encrypt(publicKey, srcBytes);

        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] resultBytes = cipher.doFinal(srcBytes);
        byte[] decBytes = decrypt(privateKey, resultBytes);

        System.out.println(publicKey.toString());
        System.out.println(privateKey.getPrivateExponent());
        System.out.println("paintext is:" + msg);
        System.out.println("encrypted message is: " + DatatypeConverter.printBase64Binary(resultBytes));
        System.out.println("decrypted message is: " + new String(decBytes));
    }
}

Updated : 3.25.
I've debugged the source code. Finally , I find that for some codes, cryptoguard can correctly identify the RSA small size key misuse , but for the above codes, it can't. The bug is from this line : java/rule/ExportGradeKeyInitializationFinder.java: 88.
The two strings here may seem like this:

<RSA: void main(java.lang.String[])>[70]
[<RSA: void main(java.lang.String[70]]

It's strange but I'm not going to figure out the deeper reason causing strings like this. Logically speaking, the two strings indicate the same line in the source code, so the checking should be passed to do more slicing analysis. I simply parse the line number in the original strings and compare them to determine whether we should analyze more or return right here.
A simple demo here :

 if (!(initializationCallsites.toString().contains(keyInitializationSite))) {
      String regEx = "[^0-9]";
      Pattern p = Pattern.compile(regEx);
      Matcher m1 = p.matcher(initializationCallsites.toString());
      Matcher m2 = p.matcher(keyInitializationSite);
      try {
        int i1 = Integer.valueOf(m1.replaceAll("").trim());
        int i2 = Integer.valueOf(m2.replaceAll("").trim());
        if (i1 != i2) {
          return;
        }
      } catch (NumberFormatException e) {
        return;
      }
    }

Hopefully, you may have better ways to solve this issue.

Bad Implementations of TrustManager/HostnameVerifier not getting detected

Hi,

My team is conducting academic research on Java Cryptography API based misuse using your tool. We found that we could not detect some potential cryptographic misuses.
We believe this may be due to underlying implementation or design gaps. Each cryptographic vulnerability was generated as a barebone Java project that only contained a single vulnerability in the main function and used up to two java source files. A jar was made which was then scanned using CryptoGuard.
Additionally, all cryptographic API calls were from Java Cryptographic Architecture (JCA).

Environment

Component Version
Java Runtime OpenJDK version 1.8.0_232 64 bit
CG Commit Used 42197b0

Problem

Complex Inheritance based cryptography API misuses are not reported

Code

Attempting to use a vulnerable SSL verification with an empty checkClientTrusted, checkServerTrusted, and/or getAcceptedIssuers is created in anonymous inner class objects created from theX509ExtendedTrustManagerclass from JCA:

public class BareBone_X509ExtendedTrustManagerCanBypass {
    
    public static void main(String[] args) {
        new X509ExtendedTrustManager(){

			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				// TODO Auto-generated method stub
				return null;
			}

			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket)
					throws CertificateException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket)
					throws CertificateException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
					throws CertificateException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine)
					throws CertificateException {
				// TODO Auto-generated method stub
				
			}

        };
        System.out.println("Hello World");
    }
}

Attempting to use a vulnerable SSL verification with an empty checkClientTrusted, checkServerTrusted, and/or getAcceptedIssuers that is created in anonymous inner class object created from an empty abstract class which implements the X509TrustManager interface from JCA:

public abstract class BareBone_X509TrustManagerCanBypassExt implements X509TrustManager {
}

public class BareBone_X509TrustManagerCanBypass {
    static X509TrustManager getTrustManager(){	
		return new BareBone_X509TrustManagerCanBypassExt(){
			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				// TODO Auto-generated method stub
				
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				// TODO Auto-generated method stub
				return null;
			}

        };
	}
    public static void main(String[] args) {
                getTrustManager();
    }
}

Attempting to use a vulnerable hostname verification that is created in an anonymous inner class object that is created from an abstract class that extends the HostnameVerifier interface from JCA:

public abstract class ABadHostNameVerifier implements HostnameVerifier {}

public class BadHostName{
    public static void main(String[] args) {
        new ABadHostNameVerifier(){
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
    }
}

Attempting to use a vulnerable hostname verification in an anonymous inner class object that is created from an empty interface that implements the HostnameVerifier interface from JCA:

public interface ABadHostNameVerifier extends HostnameVerifier {    
    public boolean verify(String hostname, SSLSession session);
}

public class BadHostName{
    public static void main(String[] args) {
        new ABadHostNameVerifier(){
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
    }
}

Please let me know if you need any additional information (e.g., logs from our side) in fixing these issues.

Thanks! :)

Bad Implementations of TrustManager/HostnameVerifier not getting detected with Specific conditions

Hi,

My team is conducting academic research on Java Cryptography API based misuse using your tool. We found that we could not detect some potential cryptographic misuses.

We believe this may be due to underlying implementation or design gaps. Each cryptographic vulnerability was generated as a barebone Java project that only contained a single vulnerability in the main function and used up to two java source files. A jar was made which was then scanned using CryptoGuard.
Additionally, all cryptographic API calls were from Java Cryptographic Architecture (JCA).

Environment

Component Version
Java Runtime OpenJDK version 1.8.0_232 64 bit
CG Commit Used 42197b0

Problem

Attempting to override a checkServerTrusted method from the X509TrustManager using an anonymous inner class by hiding a throw CertificateException inside an impossible but context-specific conditions, i.e., conditions that seem to be relevant due to specific variable use, but are actually not, e.g,
if (!(null != s || s.equalsIgnoreCase(“RSA”) || certs.length >= 314)) throw new CertificateException(“not RSA”);

public class BareboneTrustManagerConditional {
	static final X509Certificate[] EMPTY_X509CERTIFICATE_ARRAY = new X509Certificate[] {};

	public static void main(String[] args) {
		System.out.println("Hello World");
		TrustManager[] trustAll = new TrustManager[] {

				new X509TrustManager() {
					@Override
					public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
							throws CertificateException {
						if (!(null != s || s.equalsIgnoreCase("RSA") || x509Certificates.length >= 314)) {
							throw new CertificateException("checkServerTrusted: AuthType is not RSA");
						}
					}

					@Override
					public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
							throws CertificateException {
						if (!(null != s || s.equalsIgnoreCase("RSA") || x509Certificates.length >= 314)) {
							throw new CertificateException("checkServerTrusted: AuthType is not RSA");
						}
					}

					@Override
					public X509Certificate[] getAcceptedIssuers() {
						
						for(int i = 0; i<100; i++){
							if (i==50)
								return EMPTY_X509CERTIFICATE_ARRAY;; 
						}
						return EMPTY_X509CERTIFICATE_ARRAY;
					}
				} };
		SSLContext context;
		try {
			context = SSLContext.getInstance("TLS");
			context.init(null, trustAll, new SecureRandom());

		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
		} catch (KeyManagementException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
		}

	}
}

Attempting to accept all Hostnames by returning true, which we believe to be due to developers being able to hide it in context-specific always-true condition block that returns true;, e.g.,
if(true || session.getCipherSuite().length()>=0) return true; return false;

public interface ABadHostNameVerifier extends HostnameVerifier {
    public boolean verify(String hostname, SSLSession session);
}

public class BadHostName{
    public static void main(String[] args) {
        new ABadHostNameVerifier(){
            @Override
            public boolean verify(String hostname, SSLSession session) {
                if(true || session.getCipherSuite().length()>=0){
                    return true;
                }
                return false;
            }
        };
    }
}

Attempting to use an insecure analysis of vulnerable hostname verification, i.e.,the verify() method within an anonymous inner class, which we believe to be due to the failure to detect a context-specific always-true condition block that returns true; e.g.,
if(true || session.getCipherSuite().length()>=0) return true; return false;

public abstract class ABadHostNameVerifier implements HostnameVerifier {
}

public class BadHostName{
    public static void main(String[] args) {
        new ABadHostNameVerifier(){
            @Override
            public boolean verify(String hostname, SSLSession session) {
                if(true || session.getCipherSuite().length()>=0){
                    return true;
                }
                return false;
            }
        };
    }
}

Please let me know if you need any additional information (e.g., logs from our side) in fixing these issues.

Thanks! :)

Weak Algorithm Name as String Parameter not detected after Transformation

Hi,

My team is conducting academic research on Java Cryptography API based misuse using your tool. We found that we could not detect some potential cryptographic misuses.
We believe this may be due to underlying implementation or design gaps. Each cryptographic vulnerability was generated as a barebone Java project that only contained a single vulnerability in the main function and used up to two java source files. A jar was made which was then scanned using CryptoGuard.
Additionally, all cryptographic API calls were from Java Cryptographic Architecture (JCA).

Environment

Component Version
Java Runtime OpenJDK version 1.8.0_232 64 bit
CG Commit Used 42197b0

Even though the commit is different from the current version, I don't think much has changed in between these commits.

Problem

Weak algorithm names are not detected when they go through various types of transformations. We noticed this for both MessageDigest and Cipher.

Code

Replacing a Secure Parameter with an Insecure Parameter:

MessageDigest.getInstance("SHA-256".replace("SHA-256", "MD5"));

Replacing an Insecure Parameter with an Insecure Parameter:

Cipher.getInstance("AES".replace("A", "D"));

where "AES" by itself is insecure as it defaults to using ECB.

Transforming string case, e.g., from lower to upper case:

Cipher.getInstance("des".toUpperCase(Locale.English));

Replacing a noisy version of insecure parameters:

Cipher.getInstance("DE$S".replace("$", ""));

Inserting an Insecure Parameter via method chaining calls:

	public class CipherExample {
    private String cipherName = "AES/GCM/NoPadding";

    public CipherExample methodA() {
        cipherName = "AES/GCM/NoPadding";
        return this;
    }

    public CipherExample methodB() {
        cipherName = "DES";
        return this;
    }

    public String getCipherName(){
        return cipherName;
    }

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException {
        Cipher c = Cipher.getInstance(new CipherExample().methodA().methodB().getCipherName());

        System.out.println(c.getAlgorithm());
    }
}
	

Please let me know if you need any additional information (e.g., logs from our side) in fixing these issues.

Thanks! :)

Bad Implementations of TrustManager/HostnameVerifier not getting detected with generic conditions

Hi,

My team is conducting academic research on Java Cryptography API based misuse using your tool. We found that we could not detect some potential cryptographic misuses.

We believe this may be due to underlying implementation or design gaps. Each cryptographic vulnerability was generated as a barebone Java project that only contained a single vulnerability in the main function and used up to two java source files. A jar was made which was then scanned using CryptoGuard.
Additionally, all cryptographic API calls were from Java Cryptographic Architecture (JCA).

Environment

Component Version
Java Runtime OpenJDK version 1.8.0_232 64 bit
CG Commit Used 42197b0

Problem

Attempting to use an insecure validation of an overridden checkServerTrusted method that is created within an anonymous inner class object created from an empty abstract class which implements the X509TrustManager interface from JCA, which we believe is due to not detecting security exceptions thrown under impossible conditions; e.g.,
if(!(true || arg0== null || arg1 == null)) throw new CertificateException();

public abstract class BareboneTrustManagerExt implements javax.net.ssl.X509TrustManager{

}

public class BareboneTrustManagerConditional {
	static final X509Certificate[] EMPTY_X509CERTIFICATE_ARRAY = new X509Certificate[] {};

	public static void main(String[] args) {
		
		TrustManager[] trustAll = new TrustManager[] {

				new BareboneTrustManagerExt() {
					@java.lang.Override
					public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, java.lang.String arg1)
						throws java.security.cert.CertificateException {
				  
					  if(!(true||arg0 == null||arg1 == null)){ 
						  throw new java.security.cert.CertificateException();
					  }
					}
				  
					@java.lang.Override
					public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, java.lang.String arg1)
						throws java.security.cert.CertificateException {
				  
					  if(!(true||arg0 == null||arg1 == null)){
						  throw new java.security.cert.CertificateException();
					  }
					}

					@Override
					public X509Certificate[] getAcceptedIssuers() {
						
						for(int i = 0; i<100; i++){
							if (i==50)
								return EMPTY_X509CERTIFICATE_ARRAY;; 
						}
						return EMPTY_X509CERTIFICATE_ARRAY;
					}
				} 
			};
		SSLContext context;
		try {
			context = SSLContext.getInstance("TLS");
			context.init(null, trustAll, new SecureRandom());

		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
		} catch (KeyManagementException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
		}
		System.out.println("Hello World 8.6");
	}
}

Attempting to use an insecure analysis of vulnerable hostname verification, i.e., the verify() method within an anonymous inner class object that is created from an empty interface that implements the HostnameVerifier interface from JCA, which we believe is due to the failure to detect an always true condition block that returns true; e.g.,
if(true || session == null) return true; return false;

public interface ABadHostNameVerifier extends HostnameVerifier {
    public boolean verify(String hostname, SSLSession session);
}

public class BadHostName{
    public static void main(String[] args) {
        new ABadHostNameVerifier(){
            @Override
            public boolean verify(String hostname, SSLSession session) {
                if(true || session == null){
                    return true;
                }
                return false;
            }
        };
    }
}

Attempting to use a vulnerable hostname verification, i.e., the verify() method within an anonymous inner class object that is created from an abstract class that extends the HostnameVerifier interface from JCA, which we believe is due to the failure to detect an always true condition block that returns true; e.g.,
if(true || session == null) return true; return false;

public abstract class ABadHostNameVerifier implements HostnameVerifier {
}

public class BadHostName{
    public static void main(String[] args) {
        new ABadHostNameVerifier(){
            @Override
            public boolean verify(String hostname, SSLSession session) {
                if(true || session == null){
                    return true;
                }
                return false;
            }
        };
    }
}

Please let me know if you need any additional information (e.g., logs from our side) in fixing these issues.

Thanks! :)

Detecting Predictable IVs / Constant IVs

Hi,

My team is conducting academic research on Java Cryptography API based misuse using your tool. We found that we could not detect some potential cryptographic misuses.

We believe this may be due to underlying implementation or design gaps. Each cryptographic vulnerability was generated as a barebone Java project that only contained a single vulnerability in the main function and used up to two java source files. A jar was made which was then scanned using CryptoGuard.

Additionally, all cryptographic API calls were from Java Cryptographic Architecture (JCA).

Environment

Component Version
Java Runtime OpenJDK version 1.8.0_232 64 bit
CG Commit Used 42197b0

Problem

Predictable / Constant IVs should be detected.

Code

String val="";

for(int i = 65; i < 75; i++){
            val += (char) i;
}
IvParameterSpec ivSpec = new IvParameterSpec(val.getBytes());
String val="";
SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
Date date = new Date(System.currentTimeMillis());
val = formatter.format(date);
IvParameterSpec ivSpec = new IvParameterSpec(val.getBytes());

Please let me know if you need any additional information (e.g., logs from our side) in fixing these issues.

Thanks! :)

Failing test

Hi, When I was previously running cryptoguard on android apk's it was running properly. But recently some test seems to be failing. Complete log of the error can be found below.

cryptoguardError.txt

Thanks!

Other crypto rules maybe

Hi, I'm tl2cents. I'm now researching the crypto misuses in the real world and conducting academic research on Java Cryptography API based misuse using your tool. I'd like to list several rules for reference that might be implemented in your tool.

  • DSA

    Nowadays, DSA might be an insecure signature algorithm. Attackers can use the randomness of nonce to implement a side-channel attack to get server's private key. For more details, refer to this paper: Timing and Lattice Attacks on a Remote ECDSA OpenSSL Server: How Practical Are They Really?. It's hard to avoid oracles in real application.

    OpenSSH 7.0 and above versions disabled the ssh-dss (DSA) public key algorithm by default. The official did not give a specific explanation, but there may be reasons for the generation of OpenSSH and DSA key digits. At the same time, the randomness of the nonce when generating the signature is poor, and the private key may be leaked. With the computing power of the current computer, DSA 1024-bit is actually crackable, so it is not recommended to use it.

    Maybe we can add it to the broken cipher list. Or at least , we should check the key size of DSA. In java, the DSA key size is upper bounded by 1024.

  • Poodle Attack

    This rule is mainly concerned with the leakage of the validity of padding and checksum. A typical attack is Poodle Attack. A malicious attacker can decrypt any message by sending well-constructed messages to the server which can reveal the correctness of the message to the attacker. Thus, we should check whether the java program throws an exception or explicit notion after padding or unpadding. Implementation of this rule might be complicated.

  • RSA/ECB/PKCS1Padding && RSA public exponent too small

    I find that java uses RSA/ECB/PKCS1Padding by default. This padding is not secure when the RSA public exponent is small. Generally, e is 65537 in java program. (I'm not clear whether we can select the public exponent of RSA in javax.crypto, I'll research it later.) Bleichenbacher's attack : attackers can forge RSA signatures with PKCS1Padding when e is small . Actually, small RSA public exponent causes many security issues.

Hope CryptoGuard be greater in the future!

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.