package com.love.util.qcloud; import net.sf.json.JSONObject; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import java.io.CharArrayReader; import java.io.IOException; import java.io.Reader; import java.nio.charset.Charset; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Security; import java.security.Signature; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.zip.Deflater; import java.util.zip.Inflater; /** * Created by liping.sang on 2017/1/18 0018. */ public class QChatUtils { private static final long EXPIRE_SECOND = Long.valueOf(60 * 60 * 24 * 180); private static final String BC = "BC"; private static final String SHA256withECDSA = "SHA256withECDSA"; private static final String UTF8 = "UTF-8"; private static final String QC_ACCOUNT_TYPE="10209"; private static final String QC_SDK_APP_ID="1400023855"; private static final String QC_PRIVATE_KEY="自己的私钥"; private static final String QC_PUBLIC_KEY="自己的公钥"; private QChatUtils() {} private static Signature getSignatureWithPrivateKey(PrivateKey privateKey, String content) throws Exception { Signature signature = Signature.getInstance(SHA256withECDSA, BC); signature.initSign(privateKey); signature.update(content.getBytes(Charset.forName(UTF8))); return signature; } private static Signature getSignatureWithPublicKey(PublicKey publicKey, String content) throws Exception { Signature signature = Signature.getInstance(SHA256withECDSA, BC); signature.initVerify(publicKey); signature.update(content.getBytes(Charset.forName(UTF8))); return signature; } private static PrivateKey getPrivateKey(String privateKeyStr) throws IOException { Security.addProvider(new BouncyCastleProvider()); Reader reader = new CharArrayReader(privateKeyStr.toCharArray()); JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); PEMParser parser = new PEMParser(reader); PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) parser.readObject(); parser.close(); PrivateKey privateKey = converter.getPrivateKey(privateKeyInfo); return privateKey; } private static PublicKey getPublicKey(String publicKeyStr) throws IOException { Reader reader = new CharArrayReader(publicKeyStr.toCharArray()); PEMParser parser = new PEMParser(reader); JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); SubjectPublicKeyInfo subjectPublicKeyInfo = (SubjectPublicKeyInfo) parser.readObject(); parser.close(); PublicKey publicKey = converter.getPublicKey(subjectPublicKeyInfo); return publicKey; } private static String getContent(String identifier, String time) { StringBuffer sb = new StringBuffer(); sb.append("TLS.appid_at_3rd:").append(0).append(" ").append("TLS.account_type:").append(QC_ACCOUNT_TYPE).append(" ").append("TLS.identifier:") .append(identifier).append(" ").append("TLS.sdk_appid:").append(QC_SDK_APP_ID).append(" ").append("TLS.time:").append(time).append(" ") .append("TLS.expire_after:").append(EXPIRE_SECOND).append(" "); return sb.toString(); } /** * 生成UserSig * * @param identifier 用户ID * @return * @throws Exception */ public static String getUserSig(String identifier) throws Exception { String time = String.valueOf(System.currentTimeMillis() / 1000); Signature signature = getSignatureWithPrivateKey(getPrivateKey(QC_PRIVATE_KEY), getContent(identifier, time)); byte[] signatureBytes = signature.sign(); String sigTLS = Base64.encodeBase64String(signatureBytes); Map<String, Object> map = new HashMap<String, Object>(); map.put("TLS.account_type", 0); map.put("TLS.identifier", identifier); map.put("TLS.appid_at_3rd", 0); map.put("TLS.sdk_appid", QC_SDK_APP_ID); map.put("TLS.expire_after", EXPIRE_SECOND); map.put("TLS.version", "201512300000"); map.put("TLS.sig", sigTLS); map.put("TLS.time", time); JSONObject jsonObject = JSONObject.fromObject(map); String jsonString = jsonObject.toString(); Deflater deflater = new Deflater(); deflater.setInput(jsonString.getBytes(Charset.forName(UTF8))); deflater.finish(); byte[] compressBytes = new byte[512]; int compressBytesLength = deflater.deflate(compressBytes); deflater.end(); return new String(Base64.encodeBase64(Arrays.copyOfRange(compressBytes, 0, compressBytesLength))); } /** * 验证签名 * * @param userSig 签名 * @param identifier 用户ID * @return * @throws Exception */ public static boolean checkUserSig(String userSig, String identifier) throws Exception { Security.addProvider(new BouncyCastleProvider()); Base64 decoder = new Base64(); byte[] compressBytes = Base64.decodeBase64(userSig.getBytes(Charset.forName(UTF8))); Inflater inflater = new Inflater(); inflater.setInput(compressBytes, 0, compressBytes.length); byte[] decompressBytes = new byte[1024]; int decompressLength = inflater.inflate(decompressBytes); inflater.end(); String jsonString = new String(Arrays.copyOfRange(decompressBytes, 0, decompressLength)); JSONObject jsonObject = JSONObject.fromObject(jsonString); String sigTLS = jsonObject.getString("TLS.sig"); byte[] signatureBytes = decoder.decode(sigTLS.getBytes(Charset.forName(UTF8))); String sigTime = jsonObject.getString("TLS.time"); Signature signature = getSignatureWithPublicKey(QChatUtils.getPublicKey(QC_PUBLIC_KEY), getContent(identifier, sigTime)); return signature.verify(signatureBytes); } public static void main(String[] args) { try { String userSig = QChatUtils.getUserSig("xxx@foxmail.com"); System.out.println("UserSig: " + userSig); boolean checkResult = QChatUtils.checkUserSig(userSig, "xxx@foxmail.com"); System.out.println("Check UserSig Result: " + checkResult); } catch (Exception e) { e.printStackTrace(); } } }
以上为第一种使用的时候直接String usrsig=QChatUtils.getUserSig("用户名");
package com.love.util.qcloud.qcim; import com.tls.tls_sigature.tls_sigature; import com.tls.tls_sigature.tls_sigature.GenTLSSignatureResult; import java.io.IOException; public class SigUtil { private static String privatekey = ""; private static String usersig = ""; private static long usersig_gentime = 0; public static String GetSignature(String identifier) throws SigException{ boolean needGenSig = false; do { if(usersig == "" || usersig_gentime == 0) { needGenSig = true; break; } long expect_expire_time = usersig_gentime + SigConfig.expire; long nowtime = System.currentTimeMillis(); if(expect_expire_time < nowtime)//这里会有一些问题,如果不同账户请求有时会出现生成相同的签名 { needGenSig = true; break; } }while(false); if(needGenSig) { GenSignature(identifier); } if(usersig == "") { throw new SigException("invalid signature"); } return usersig; } private static void GenSignature(String identifier) throws SigException { if(privatekey == "") { privatekey="-----BEGIN PRIVATE KEY-----私钥 -----END PRIVATE KEY-----"; } GenTLSSignatureResult result = null; try { /** * @brief 生成 tls 票据,精简参数列表 * @param skdAppid 应用的 sdkappid * @param identifier 用户 id * @param privStr 私钥文件内容 * @param expire 有效期,以秒为单位,推荐时长一个月 * @return * @throws IOException */ result = tls_sigature.GenTLSSignatureEx( SigConfig.sdkappid, identifier, privatekey, SigConfig.expire ); } catch (IOException e) { throw new SigException("tls_sigature.GenTLSSignatureEx failed: " + e.getMessage()); } if (0 == result.urlSig.length()) { usersig = ""; throw new SigException("tls_sigature.GenTLSSignatureEx failed: " + result.errMessage); } else { usersig = result.urlSig; usersig_gentime = System.currentTimeMillis(); } } }
package com.love.util.qcloud.qcim; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class SigConfig { public static String identifier; public static long sdkappid; public static long expire; public static String privateKey; private SigConfig() { } public static void loadConfig(String config) throws ConfigFileException { Properties prop = new Properties(); try { FileInputStream in = new FileInputStream(config); prop.load(in); } catch (IOException e) { throw new ConfigFileException("invalid config file path"); } //identifier = prop.getProperty( "identifier" ).trim(); privateKey = prop.getProperty( "privateKey" ).trim(); try { sdkappid = Long.parseLong(prop.getProperty( "sdkappid" ).trim()); } catch (NumberFormatException e) { throw new ConfigFileException("invalid sdkappid"); } try { expire = Long.parseLong(prop.getProperty( "expire" ).trim()); } catch (NumberFormatException e) { throw new ConfigFileException("invalid expire time"); } } }
package com.love.util.qcloud.qcim; public class SigException extends Exception { private static final long serialVersionUID = 1L; public SigException(String msg) { super(msg); } }
package com.love.util.qcloud.qcim; public class ConfigFileException extends Exception { private static final long serialVersionUID = 8602127640556152351L; public ConfigFileException(String msg) { super(msg); } }
这个是官网demo的一个方式