Comments (9)
java签名类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.nmgjc.dwzj.sdk.util.sign;
import com.alipay.api.internal.util.codec.Base64;
import com.nmgjc.dwzj.sdk.exception.BusinessException;
import com.nmgjc.dwzj.sdk.model.CheckSignParam;
import com.nmgjc.dwzj.sdk.model.CommReq;
import com.nmgjc.dwzj.sdk.model.CommRsp;
import com.nmgjc.dwzj.sdk.model.SignParam;
import com.nmgjc.dwzj.sdk.util.sign.inter.ISign;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GM2Util implements ISign {
private static final Logger LOGGER = LoggerFactory.getLogger(GM2Util.class);
private static final BouncyCastleProvider bc = new BouncyCastleProvider();
private static final String KEY_ALGORITHM = "EC";
private static final String SIGNATURE_ALGORITHM = "SM3withSm2";
public GM2Util() {
}
public String sign(CommReq reqData) {
String srcData = reqData.getSrcSignData();
LOGGER.info("srcData:" + srcData);
return sign(srcData.getBytes(StandardCharsets.UTF_8), reqData.getKey());
}
public String getSign(SignParam signParam) {
String srcData = signParam.getSrcSignData();
LOGGER.info("srcData:" + srcData);
return sign(srcData.getBytes(StandardCharsets.UTF_8), signParam.getKey());
}
public boolean checkSign(CheckSignParam checkSignParam) {
String srcData = checkSignParam.getSrcSignData();
LOGGER.info("srcData:" + srcData);
return verify(srcData.getBytes(StandardCharsets.UTF_8), checkSignParam.getPubKey(), checkSignParam.getSign());
}
public boolean check(CommReq reqData, CommRsp rspData) {
String srcData = rspData.getSrcSignData(reqData.getVersion());
LOGGER.info("srcData:" + srcData);
return verify(srcData.getBytes(StandardCharsets.UTF_8), reqData.getPubKey(), rspData.getSign());
}
private static String sign(byte[] data, String privateKeyStr) {
try {
byte[] keyBytes = Base64.decodeBase64(privateKeyStr.getBytes(StandardCharsets.UTF_8));
KeyFactory keyFactory = KeyFactory.getInstance("EC", bc);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance("SM3withSm2", bc);
signature.initSign(priKey);
signature.update(data);
return Base64.encodeBase64String(signature.sign());
} catch (Exception var7) {
LOGGER.error("sign异常", var7);
return null;
}
}
private static boolean verify(byte[] data, String publicKeyStr, String sign) {
try {
byte[] keyBytes = Base64.decodeBase64(publicKeyStr.getBytes(StandardCharsets.UTF_8));
KeyFactory keyFactory = KeyFactory.getInstance("EC", bc);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("SM3withSm2", bc);
signature.initVerify(pubKey);
signature.update(data);
return signature.verify(Base64.decodeBase64(sign.getBytes(StandardCharsets.UTF_8)));
} catch (Exception var8) {
LOGGER.error("verify异常", var8);
return false;
}
}
public static KeyPair generateSm2KeyPair() {
try {
ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
SecureRandom random = new SecureRandom();
kpg.initialize(sm2Spec, random);
KeyPair keyPair = kpg.generateKeyPair();
return keyPair;
} catch (Exception var4) {
var4.printStackTrace();
throw new BusinessException("生成密钥对失败");
}
}
public static void main(String[] args) throws Exception {
KeyPair keyPair = generateSm2KeyPair();
String priPath = Base64.encodeBase64String(keyPair.getPrivate().getEncoded());
String pubPath = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
String data = "123213";
String sign = sign(data.getBytes(), priPath);
LOGGER.info(sign);
boolean verify = verify(data.getBytes(), pubPath, sign);
LOGGER.info(String.valueOf(verify));
}
}
from phpsm2sm3sm4.
你这签名的公钥是是pkcs封装过的,需要解开为明文,解开后为: 043525E5FA884D41C089D87D6DA7B28A26306750CF9FD2C3500381DA48CC51B7FC7B1B58F9AF4339F3338DF464FBE028CB5B0B38FB107170FABC17B98197499E09
或者 把它存成 .pem文件格式的文件,有一个函数是去读密码文件的
你用这个去明文签名试试对方认不认
PS: 我把你的私钥隐去一部分了,如果是正式的放网上就不好了,能更新的话就换一个新的,如果只是测试用的,请忽略
from phpsm2sm3sm4.
用这个明文签名去试了,验签失败
from phpsm2sm3sm4.
哦,那你用 字符串为你例子中: ”appid=app1&data=ewogI&method=query&noise=ibuaiVcKdpRxkhJA&version=V1.0“
分别用PHp与JAVA 签名一次,我看一下签名完的结果
from phpsm2sm3sm4.
java:
{"data":"eyJtZXJjaGFudF9ubyI6IjE1MDAwMDIwMjQwNTMwMDEiLCJ3aWRnZXRfY29udGVudCI6IntcIm1lcmNoYW50X25vXCI6XCIxNTAwMDAyMDI0MDUzMDAxXCIsXCJtZXJjaGFudF9vcmRlcl9ub1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJhbW91bnRcIjoxLFwid2lkZ2V0X3BhcmFtXCI6e1wiYnVzaW5lc3NOb1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJyZWdDb2RlXCI6XCIxNTAyOTVcIixcImJ1c2luZXNzVHlwZVwiOlwiMDAxXCIsXCJhZ2VuY3lDb2RlXCI6XCIyMTQwMDFcIixcImRhdGVcIjpcIjIwMjQtMDYtMDVcIixcInBheWVyTmFtZVwiOlwibGljXCIsXCJwYXllclRlbFwiOlwiMTMzODQ4ODIwNTJcIixcInBheWVlQWNjQXNzaWduVHlwZVwiOlwiMVwiLFwidG90YWxBbXRcIjoxLFwiYXV0aG9yXCI6XCJBQkNcIixcInBsYWNlQ29kZVwiOlwiMDAxXCIsXCJiaWxsQ29kZVwiOlwiMDAwNFwiLFwiaXRlbURldGFpbHNcIjpbe1wiaXRlbUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiaXRlbU5hbWVcIjpcIuaIkOS6uuaVmeiCsuWtpui0uVwiLFwidW5pdFwiOlwi5Lq6L+asoVwiLFwibnVtYmVyXCI6MSxcInN0ZFwiOjEsXCJhbXRcIjoxfV19LFwic3ViamVjdFwiOlwi5rWL6K+V5ZWG5ZOBXCIsXCJib2R5XCI6XCLkuIvljZXmtYvor5VcIixcImRldmljZV90eXBlXCI6XCJwY1wiLFwiZWZmZWN0aXZlX3RpbWVcIjpcIjFkXCIsXCJ2ZXJzaW9uX25vXCI6XCIxLjFcIn0iLCJiYWNrX3VybCI6Imh0dHA6Ly96aHVvZmFuLnBpY3AuaW8vcGF5bWVudC92Mi93d3cvaW5kZXgucGhwL29yZGVyL29yZGVyTm90aWZ5IiwiZWJpbGxfaW5mbyI6IntcImJhY2tfdXJsXCI6XCJodHRwOi8vd3d3LmJhaWR1LmNvbS9cIixcImJ1c05vXCI6XCIxNTAyOTUwMDAwMlwiLFwicGF5ZXJcIjpcImxpY1wiLFwicGF5ZXJUeXBlXCI6XCIxXCIsXCJjYXJkVHlwZVwiOlwiXCIsXCJjcmVkaXRDb2RlXCI6XCJcIixcImJ1c0RhdGVUaW1lXCI6XCIyMDI0MDYwMzE3MzkwMTAwMVwiLFwicmV2aWV3ZXJcIjpcIlwiLFwicGF5ZWVcIjpcIkFCQ1wiLFwiYXV0aG9yXCI6XCJBQkNcIixcInRvdGFsQW10XCI6MC4wMSxcInJlbWFya1wiOlwiXCIsXCJ0ZWxcIjpcIlwiLFwiZW1haWxcIjpcIlwiLFwiaWRDYXJkTm9cIjpcIlwiLFwiY2hhcmdlRGV0YWlsXCI6W3tcImNoYXJnZUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiY2hhcmdlTmFtZVwiOlwi5oiQ5Lq65pWZ6IKy5a2m6LS5XCIsXCJpdGVtU3RkQ29kZVwiOlwiXCIsXCJ1bml0XCI6XCLkurov5qyhXCIsXCJzdGRcIjowLjAxLFwibnVtYmVyXCI6MSxcImFtdFwiOjAuMDEsXCJyZW1hcmtcIjpcIua1i+ivlVwifV19In0=","method":"query","appid":"app1","noise":"ibuaiVcKdpRxkhJA","sign":"MEUCIQDJLdeHuN8Ef/0Q7xLPpDr1W/WJwkoG9c9WQ9N9OLuF3wIgE98oDSq96auYbwTPi0X51vGXFLiTPOxfs9GPI1SnqFg=","version":"V1.0"}
php:
{"data":"eyJtZXJjaGFudF9ubyI6IjE1MDAwMDIwMjQwNTMwMDEiLCJ3aWRnZXRfY29udGVudCI6IntcIm1lcmNoYW50X25vXCI6XCIxNTAwMDAyMDI0MDUzMDAxXCIsXCJtZXJjaGFudF9vcmRlcl9ub1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJhbW91bnRcIjoxLFwid2lkZ2V0X3BhcmFtXCI6e1wiYnVzaW5lc3NOb1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJyZWdDb2RlXCI6XCIxNTAyOTVcIixcImJ1c2luZXNzVHlwZVwiOlwiMDAxXCIsXCJhZ2VuY3lDb2RlXCI6XCIyMTQwMDFcIixcImRhdGVcIjpcIjIwMjQtMDYtMDVcIixcInBheWVyTmFtZVwiOlwibGljXCIsXCJwYXllclRlbFwiOlwiMTMzODQ4ODIwNTJcIixcInBheWVlQWNjQXNzaWduVHlwZVwiOlwiMVwiLFwidG90YWxBbXRcIjoxLFwiYXV0aG9yXCI6XCJBQkNcIixcInBsYWNlQ29kZVwiOlwiMDAxXCIsXCJiaWxsQ29kZVwiOlwiMDAwNFwiLFwiaXRlbURldGFpbHNcIjpbe1wiaXRlbUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiaXRlbU5hbWVcIjpcIuaIkOS6uuaVmeiCsuWtpui0uVwiLFwidW5pdFwiOlwi5Lq6L+asoVwiLFwibnVtYmVyXCI6MSxcInN0ZFwiOjEsXCJhbXRcIjoxfV19LFwic3ViamVjdFwiOlwi5rWL6K+V5ZWG5ZOBXCIsXCJib2R5XCI6XCLkuIvljZXmtYvor5VcIixcImRldmljZV90eXBlXCI6XCJwY1wiLFwiZWZmZWN0aXZlX3RpbWVcIjpcIjFkXCIsXCJ2ZXJzaW9uX25vXCI6XCIxLjFcIn0iLCJiYWNrX3VybCI6Imh0dHA6Ly96aHVvZmFuLnBpY3AuaW8vcGF5bWVudC92Mi93d3cvaW5kZXgucGhwL29yZGVyL29yZGVyTm90aWZ5IiwiZWJpbGxfaW5mbyI6IntcImJhY2tfdXJsXCI6XCJodHRwOi8vd3d3LmJhaWR1LmNvbS9cIixcImJ1c05vXCI6XCIxNTAyOTUwMDAwMlwiLFwicGF5ZXJcIjpcImxpY1wiLFwicGF5ZXJUeXBlXCI6XCIxXCIsXCJjYXJkVHlwZVwiOlwiXCIsXCJjcmVkaXRDb2RlXCI6XCJcIixcImJ1c0RhdGVUaW1lXCI6XCIyMDI0MDYwMzE3MzkwMTAwMVwiLFwicmV2aWV3ZXJcIjpcIlwiLFwicGF5ZWVcIjpcIkFCQ1wiLFwiYXV0aG9yXCI6XCJBQkNcIixcInRvdGFsQW10XCI6MC4wMSxcInJlbWFya1wiOlwiXCIsXCJ0ZWxcIjpcIlwiLFwiZW1haWxcIjpcIlwiLFwiaWRDYXJkTm9cIjpcIlwiLFwiY2hhcmdlRGV0YWlsXCI6W3tcImNoYXJnZUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiY2hhcmdlTmFtZVwiOlwi5oiQ5Lq65pWZ6IKy5a2m6LS5XCIsXCJpdGVtU3RkQ29kZVwiOlwiXCIsXCJ1bml0XCI6XCLkurov5qyhXCIsXCJzdGRcIjowLjAxLFwibnVtYmVyXCI6MSxcImFtdFwiOjAuMDEsXCJyZW1hcmtcIjpcIua1i+ivlVwifV19In0=","method":"query","appid":"app1","noise":"ibuaiVcKdpRxkhJA","version":"V1.0","sign":"MEYCIQDxoQeo778i8fg7ZJHVC5TwrsC/onyodbeIgl2DvfzGhQIhAJBYJ9l18KaBnmQBGHo4sc6yuegJGLNmF5Xwk5sTyve8"}
php签名用的公钥是:043525E5FA884D41C089D87D6DA7B28A26306750CF9FD2C3500381DA48CC51B7FC7B1B58F9AF4339F3338DF464FBE028CB5B0B38FB107170FABC17B98197499E09
from phpsm2sm3sm4.
<?php
require_once '../vendor/autoload.php';
use Rtgm\sm\RtSm2;
$publicKey = '043525E5FA884D41C089D87D6DA7B28A26306750CF9FD2C3500381DA48CC51B7FC7B1B58F9AF4339F3338DF464FBE028CB5B0B38FB107170FABC17B98197499E09'; // 公钥
$privateKey = 'DFBAC8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxE7C0AC2E10704'; // 私钥
$userId = '1234567812345678';
$str = '{"data":"eyJtZXJjaGFudF9ubyI6IjE1MDAwMDIwMjQwNTMwMDEiLCJ3aWRnZXRfY29udGVudCI6IntcIm1lcmNoYW50X25vXCI6XCIxNTAwMDAyMDI0MDUzMDAxXCIsXCJtZXJjaGFudF9vcmRlcl9ub1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJhbW91bnRcIjoxLFwid2lkZ2V0X3BhcmFtXCI6e1wiYnVzaW5lc3NOb1wiOlwiMjAyNDA2MDZfMTE1ODU0XCIsXCJyZWdDb2RlXCI6XCIxNTAyOTVcIixcImJ1c2luZXNzVHlwZVwiOlwiMDAxXCIsXCJhZ2VuY3lDb2RlXCI6XCIyMTQwMDFcIixcImRhdGVcIjpcIjIwMjQtMDYtMDVcIixcInBheWVyTmFtZVwiOlwibGljXCIsXCJwYXllclRlbFwiOlwiMTMzODQ4ODIwNTJcIixcInBheWVlQWNjQXNzaWduVHlwZVwiOlwiMVwiLFwidG90YWxBbXRcIjoxLFwiYXV0aG9yXCI6XCJBQkNcIixcInBsYWNlQ29kZVwiOlwiMDAxXCIsXCJiaWxsQ29kZVwiOlwiMDAwNFwiLFwiaXRlbURldGFpbHNcIjpbe1wiaXRlbUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiaXRlbU5hbWVcIjpcIuaIkOS6uuaVmeiCsuWtpui0uVwiLFwidW5pdFwiOlwi5Lq6L+asoVwiLFwibnVtYmVyXCI6MSxcInN0ZFwiOjEsXCJhbXRcIjoxfV19LFwic3ViamVjdFwiOlwi5rWL6K+V5ZWG5ZOBXCIsXCJib2R5XCI6XCLkuIvljZXmtYvor5VcIixcImRldmljZV90eXBlXCI6XCJwY1wiLFwiZWZmZWN0aXZlX3RpbWVcIjpcIjFkXCIsXCJ2ZXJzaW9uX25vXCI6XCIxLjFcIn0iLCJiYWNrX3VybCI6Imh0dHA6Ly96aHVvZmFuLnBpY3AuaW8vcGF5bWVudC92Mi93d3cvaW5kZXgucGhwL29yZGVyL29yZGVyTm90aWZ5IiwiZWJpbGxfaW5mbyI6IntcImJhY2tfdXJsXCI6XCJodHRwOi8vd3d3LmJhaWR1LmNvbS9cIixcImJ1c05vXCI6XCIxNTAyOTUwMDAwMlwiLFwicGF5ZXJcIjpcImxpY1wiLFwicGF5ZXJUeXBlXCI6XCIxXCIsXCJjYXJkVHlwZVwiOlwiXCIsXCJjcmVkaXRDb2RlXCI6XCJcIixcImJ1c0RhdGVUaW1lXCI6XCIyMDI0MDYwMzE3MzkwMTAwMVwiLFwicmV2aWV3ZXJcIjpcIlwiLFwicGF5ZWVcIjpcIkFCQ1wiLFwiYXV0aG9yXCI6XCJBQkNcIixcInRvdGFsQW10XCI6MC4wMSxcInJlbWFya1wiOlwiXCIsXCJ0ZWxcIjpcIlwiLFwiZW1haWxcIjpcIlwiLFwiaWRDYXJkTm9cIjpcIlwiLFwiY2hhcmdlRGV0YWlsXCI6W3tcImNoYXJnZUNvZGVcIjpcIjEwMzA0Mjc4OVwiLFwiY2hhcmdlTmFtZVwiOlwi5oiQ5Lq65pWZ6IKy5a2m6LS5XCIsXCJpdGVtU3RkQ29kZVwiOlwiXCIsXCJ1bml0XCI6XCLkurov5qyhXCIsXCJzdGRcIjowLjAxLFwibnVtYmVyXCI6MSxcImFtdFwiOjAuMDEsXCJyZW1hcmtcIjpcIua1i+ivlVwifV19In0=","method":"query","appid":"app1","noise":"ibuaiVcKdpRxkhJA","version":"V1.0","sign":"MEYCIQDxoQeo778i8fg7ZJHVC5TwrsC/onyodbeIgl2DvfzGhQIhAJBYJ9l18KaBnmQBGHo4sc6yuegJGLNmF5Xwk5sTyve8"}';
$json = json_decode($str,1);
$document="appid=$json[appid]&data=$json[data]&method=$json[method]&noise=$json[noise]&version=$json[version]";
//返回的签名16进制还是base64, 目前可选hex,与base64两种
// __construct($formatSign='hex', $randFixed = true)
$sm2 = new RtSm2('base64',false);
echo "\n---------明文密钥签名---------------------------\n";
$sign = $sm2->doSign( $document, $privateKey, $userId);
print_r($sign);
var_dump($sm2->verifySign( $document, $sign, $publicKey, $userId ));
$sign = 'MEUCIQDJLdeHuN8Ef/0Q7xLPpDr1W/WJwkoG9c9WQ9N9OLuF3wIgE98oDSq96auYbwTPi0X51vGXFLiTPOxfs9GPI1SnqFg=';
echo "\n---------验证java---------------------------\n";
var_dump($sm2->verifySign( $document, $sign, $publicKey, $userId )); // true
$sign = 'MEYCIQDxoQeo778i8fg7ZJHVC5TwrsC/onyodbeIgl2DvfzGhQIhAJBYJ9l18KaBnmQBGHo4sc6yuegJGLNmF5Xwk5sTyve8';
echo "\n---------验证 PHP---------------------------\n";
var_dump($sm2->verifySign( $document, $sign, $publicKey, $userId )); // false
用你的数据测试了下,验证了三次,1 次是程序生成,验证 true, 2是用给的java签名验证也通过,3 用给的PHP生成的验证 不通过, 说明你使用PHP代码时出错了, 可能性有二, 1 使用的私钥不正确,代码显示了你那个公钥对应的私钥的一部分,请确认你用的私钥(该私钥从最开始的给的base64的私钥里解出来的明文) 2 中间有一个userId的参数是否使用正确
from phpsm2sm3sm4.
大佬,能不能把如何获得公私玥明文的方式给一下?
from phpsm2sm3sm4.
$private = '私钥的base64的值xxxxxxxxxxxxxxxxxxxx';
$private = "-----BEGIN EC PRIVATE KEY-----\n".chunk_split($private,64,"\n")."-----END EC PRIVATE KEY-----";
file_put_contents('private.pem',$private);
openssl ec -in private.pem -noout -text
如果你有私钥文件的话,直接 openssl ec -in private.pem -noout -text 就可以了
from phpsm2sm3sm4.
解出私钥的明文后验签就可以了,感谢大佬
from phpsm2sm3sm4.
Related Issues (20)
- HMAC-SM3 请问这个能否实现呢 HOT 3
- 求大佬帮看看sm2签名,java的可以通过,但是php的签名就没有办法通过,对接国家医保支付 HOT 1
- 大神你好,请问 hmac-sm3 具体怎么做呢? HOT 1
- SM4 golang 版和 php 版本加密后数据不一致,求指点 HOT 6
- 使用sm4-ecb提示Uncaught Exception: 秘钥长度为16位 HOT 2
- 求助SM2解密问题 HOT 7
- 对接招行付款码收款支付,需要对终端数据进行加密,并且在要对随机私钥进行数字信封加密,进行测试时信封加密和招行不一致,加密结果也不一致 HOT 9
- sm2 缺少文件 HOT 4
- 调用CBS8 总提示致命错误 HOT 3
- 对接招行时,对招行的数据返回进行验签时,偶现错误 ASN.1 Parser Exception at offset XX: Integer not minimally encoded HOT 2
- does not comply with psr-4 autoloading standard HOT 8
- Uncaught FG\ASN1\Exception\ParserException: ASN.1 Parser Exception HOT 5
- 对接国家医保平台的sm2withsm3的时候发现,这个签名的结果和java的签名不一致 HOT 7
- 加密无法解密 HOT 1
- java代码生成的签名用php代码验签不通过 HOT 3
- java代码生成的sm2解密与php不一致, HOT 3
- 密钥 base64 转 hex 问题 HOT 8
- 对接招行使用sm3withsm2加密,按照示例写的加签方法在招行验证失败。 HOT 12
- 对接招行需要使用SM3withSM2,sm2加密需要用sm2p256v1。 HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from phpsm2sm3sm4.