天天看點

java RSA加密生成license,用CPU序列号生成機器碼

license裡就是一些注冊資訊,鍵值對組成的字元串

對稱加密:

DES,AES,加密解密都用一個秘鑰,速度快

非對稱機密

RSA,可以私鑰加密公鑰解密,也可以公鑰機密私鑰解密,速度慢

注意:

RSA加密明文最大長度117位元組,解密要求密文最大長度為128位元組,是以在加密和解密的過程中需要分塊進行。

RSA加密對明文的長度是有限制的,如果加密資料過大會抛出異常:

常見加密算法

DES 

    DES是Data Encryption Standard(資料加密标準)的縮寫,DES算法為密碼體制中的對稱密碼體制。它是由IBM公司研制的一種加密算法,美國國家标準局于1977年公布把它作為非機要部門使用的資料加密标準,二十年來,它一直活躍在國際保密通信的舞台上,扮演了十分重要的角色。

    DES是一個分組加密算法,他以64位為分組對資料加密。同時DES也是一個對稱算法:加密和解密用的是同一個算法。它的密匙長度是56位(因為每個第8位都用作奇偶校驗),密匙可以是任意的56位的數,而且可以任意時候改變。其中有極少量的數被認為是弱密匙,但是很容易避開他們。是以保密性依賴于密鑰。

    特點:分組比較短、密鑰太短、密碼生命周期短、運算速度較慢。

  DES算法具有極高安全性,到目前為止,除了用窮舉搜尋法對DES算法進行攻擊外,還沒有發現更有效的辦法。而56位長的密鑰的窮舉空間為256,這意味着如果一台計算機的速度是每一秒種檢測一百萬個密鑰,則它搜尋完全部密鑰就需要将近2285年的時間。

    DES現在已經不視為一種安全的加密算法,因為它使用的56位秘鑰過短,以現代計算能力,24小時内即可能被破解。也有一些分析報告提出了該算法的理論上的弱點,雖然實際情況未必出現。該标準在最近已經被進階加密标準(AES)所取代。

AES

    進階加密标準(Advanced Encryption Standard,AES),又稱Rijndael加密法,是美國聯邦政府采用的一種區塊加密标準。這個标準用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,進階加密标準由美國國家标準與技術研究院(NIST)于2001年11月26日釋出于FIPS PUB 197,并在2002年5月26日成為有效的标準。2006年,進階加密标準已然成為對稱密鑰加密中最流行的算法之一。

    AES的區塊長度固定為128 位元,密鑰長度則可以是128,192或256位元。

RSA

    RSA加密算法是一種非對稱加密算法。在公鑰加密标準和電子商業中RSA被廣泛使用。RSA是1977年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當時他們三人都在麻省理工學院工作。RSA就是他們三人姓氏開頭字母拼在一起組成的。

    RSA算法的可靠性基于分解極大的整數是很困難的。假如有人找到一種很快的分解因子的算法的話,那麼用RSA加密的資訊的可靠性就肯定會極度下降。但找到這樣的算法的可能性是非常小的。今天隻有短的RSA鑰匙才可能被強力方式解破。到2008年為止,世界上還沒有任何可靠的攻擊RSA算法的方式。隻要其鑰匙的長度足夠長,用RSA加密的資訊實際上是不能被解破的。

    RSA算法利用兩個很大的質數相乘所産生的乘積來加密。這兩個質數無論哪一個先與原檔案編碼相乘,對檔案加密,均可由另一個質數再相乘來解密。但要用一個質數來求出另一個質數,則是十分困難的。是以将這一對質數稱為密鑰對(Key Pair)。在加密應用時,某個使用者總是将一個密鑰公開,讓需發信的人員将資訊用其公共密鑰加密後發給該使用者,而一旦資訊加密後,隻有用該使用者一個人知道的私用密鑰才能解密。具有數字憑證身份的人員的公共密鑰可在網上查到,亦可在請對方發資訊時主動将公共密鑰傳給對方,這樣保證在Internet上傳輸資訊的保密和安全。

本文采用RSA加密算法加密license資訊,可以運作RSATester.java生成公鑰和私鑰。

RSAUtils.java

Java代碼  

java RSA加密生成license,用CPU序列号生成機器碼

import java.io.ByteArrayOutputStream;  

import java.security.Key;  

import java.security.KeyFactory;  

import java.security.KeyPair;  

import java.security.KeyPairGenerator;  

import java.security.PrivateKey;  

import java.security.PublicKey;  

import java.security.Signature;  

import java.security.interfaces.RSAPrivateKey;  

import java.security.interfaces.RSAPublicKey;  

import java.security.spec.PKCS8EncodedKeySpec;  

import java.security.spec.X509EncodedKeySpec;  

import java.util.HashMap;  

import java.util.Map;  

import javax.crypto.Cipher;  

/** *//** 

 * <p> 

 * RSA公鑰/私鑰/簽名工具包 

 * </p> 

 * 羅納德·李維斯特(Ron [R]ivest)、阿迪·薩莫爾(Adi [S]hamir)和倫納德·阿德曼(Leonard [A]dleman) 

 * 字元串格式的密鑰在未在特殊說明情況下都為BASE64編碼格式<br/> 

 * 由于非對稱加密速度極其緩慢,一般檔案不使用它來加密而是使用對稱加密,<br/> 

 * 非對稱加密算法可以用來對對稱加密的密鑰加密,這樣保證密鑰的安全也就保證了資料的安全 

 *  

 * @author IceWee 

 * @date 2012-4-26 

 * @version 1.0 

 */  

public class RSAUtils {  

    /** *//** 

     * 加密算法RSA 

     */  

    public static final String KEY_ALGORITHM = "RSA";  

     * 簽名算法 

    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";  

     * 擷取公鑰的key 

    private static final String PUBLIC_KEY = "RSAPublicKey";  

     * 擷取私鑰的key 

    private static final String PRIVATE_KEY = "RSAPrivateKey";  

     * RSA最大加密明文大小 

    private static final int MAX_ENCRYPT_BLOCK = 117;  

     * RSA最大解密密文大小 

    private static final int MAX_DECRYPT_BLOCK = 128;  

     * <p> 

     * 生成密鑰對(公鑰和私鑰) 

     * </p> 

     *  

     * @return 

     * @throws Exception 

    public static Map<String, Object> genKeyPair() throws Exception {  

        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);  

        keyPairGen.initialize(1024);  

        KeyPair keyPair = keyPairGen.generateKeyPair();  

        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  

        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();  

        Map<String, Object> keyMap = new HashMap<String, Object>(2);  

        keyMap.put(PUBLIC_KEY, publicKey);  

        keyMap.put(PRIVATE_KEY, privateKey);  

        return keyMap;  

    }  

     * 用私鑰對資訊生成數字簽名 

     * @param data 已加密資料 

     * @param privateKey 私鑰(BASE64編碼) 

    public static String sign(byte[] data, String privateKey) throws Exception {  

        byte[] keyBytes = Base64Utils.decode(privateKey);  

        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);  

        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);  

        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);  

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);  

        signature.initSign(privateK);  

        signature.update(data);  

        return Base64Utils.encode(signature.sign());  

     * 校驗數字簽名 

     * @param publicKey 公鑰(BASE64編碼) 

     * @param sign 數字簽名 

    public static boolean verify(byte[] data, String publicKey, String sign)  

            throws Exception {  

        byte[] keyBytes = Base64Utils.decode(publicKey);  

        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);  

        PublicKey publicK = keyFactory.generatePublic(keySpec);  

        signature.initVerify(publicK);  

        return signature.verify(Base64Utils.decode(sign));  

     * <P> 

     * 私鑰解密 

     * @param encryptedData 已加密資料 

    public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)  

        Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);  

        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());  

        cipher.init(Cipher.DECRYPT_MODE, privateK);  

        int inputLen = encryptedData.length;  

        ByteArrayOutputStream out = new ByteArrayOutputStream();  

        int offSet = 0;  

        byte[] cache;  

        int i = 0;  

        // 對資料分段解密  

        while (inputLen - offSet > 0) {  

            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {  

                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);  

            } else {  

                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);  

            }  

            out.write(cache, 0, cache.length);  

            i++;  

            offSet = i * MAX_DECRYPT_BLOCK;  

        }  

        byte[] decryptedData = out.toByteArray();  

        out.close();  

        return decryptedData;  

     * 公鑰解密 

    public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)  

        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);  

        Key publicK = keyFactory.generatePublic(x509KeySpec);  

        cipher.init(Cipher.DECRYPT_MODE, publicK);  

     * 公鑰加密 

     * @param data 源資料 

    public static byte[] encryptByPublicKey(byte[] data, String publicKey)  

        // 對資料加密  

        cipher.init(Cipher.ENCRYPT_MODE, publicK);  

        int inputLen = data.length;  

        // 對資料分段加密  

            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {  

                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);  

                cache = cipher.doFinal(data, offSet, inputLen - offSet);  

            offSet = i * MAX_ENCRYPT_BLOCK;  

        byte[] encryptedData = out.toByteArray();  

        return encryptedData;  

     * 私鑰加密 

    public static byte[] encryptByPrivateKey(byte[] data, String privateKey)  

        cipher.init(Cipher.ENCRYPT_MODE, privateK);  

     * 擷取私鑰 

     * @param keyMap 密鑰對 

    public static String getPrivateKey(Map<String, Object> keyMap)  

        Key key = (Key) keyMap.get(PRIVATE_KEY);  

        return Base64Utils.encode(key.getEncoded());  

     * 擷取公鑰 

    public static String getPublicKey(Map<String, Object> keyMap)  

        Key key = (Key) keyMap.get(PUBLIC_KEY);  

}  

 Base64Utils.java

java RSA加密生成license,用CPU序列号生成機器碼

import java.io.ByteArrayInputStream;  

import java.io.File;  

import java.io.FileInputStream;  

import java.io.FileOutputStream;  

import java.io.InputStream;  

import java.io.OutputStream;  

//import it.sauronsoftware.base64.Base64;  

import sun.misc.BASE64Decoder;  

import sun.misc.BASE64Encoder;  

//若報錯,編譯路徑移除jdk,再添加jdk  

 * BASE64編碼解碼工具包 

 * 依賴javabase64-1.3.1.jar 或 common-codec 

 * @date 2012-5-19 

public class Base64Utils {  

     * 檔案讀取緩沖區大小 

    private static final int CACHE_SIZE = 1024;  

     * BASE64字元串解碼為二進制資料 

     * @param base64 

    public static byte[] decode(String base64) throws Exception {  

        //return Base64.decode(base64.getBytes());  

        return new BASE64Decoder().decodeBuffer(base64);  

     * 二進制資料編碼為BASE64字元串 

     * @param bytes 

    public static String encode(byte[] bytes) throws Exception {  

        //return new String(Base64.encode(bytes));  

        return new BASE64Encoder().encode(bytes);  

     * 将檔案編碼為BASE64字元串 

     * 大檔案慎用,可能會導緻記憶體溢出 

     * @param filePath 檔案絕對路徑 

    public static String encodeFile(String filePath) throws Exception {  

        byte[] bytes = fileToByte(filePath);  

        return encode(bytes);  

     * BASE64字元串轉回檔案 

     * @param base64 編碼字元串 

    public static void decodeToFile(String filePath, String base64) throws Exception {  

        byte[] bytes = decode(base64);  

        byteArrayToFile(bytes, filePath);  

     * 檔案轉換為二進制數組 

     * @param filePath 檔案路徑 

    public static byte[] fileToByte(String filePath) throws Exception {  

        byte[] data = new byte[0];  

        File file = new File(filePath);  

        if (file.exists()) {  

            FileInputStream in = new FileInputStream(file);  

            ByteArrayOutputStream out = new ByteArrayOutputStream(2048);  

            byte[] cache = new byte[CACHE_SIZE];  

            int nRead = 0;  

            while ((nRead = in.read(cache)) != -1) {  

                out.write(cache, 0, nRead);  

                out.flush();  

            out.close();  

            in.close();  

            data = out.toByteArray();  

         }  

        return data;  

     * 二進制資料寫檔案 

     * @param bytes 二進制資料 

     * @param filePath 檔案生成目錄 

    public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {  

        InputStream in = new ByteArrayInputStream(bytes);     

        File destFile = new File(filePath);  

//        if (!destFile.getParentFile().exists()) {  

//            destFile.getParentFile().mkdirs();  

//        }  

        destFile.createNewFile();  

        OutputStream out = new FileOutputStream(destFile);  

        byte[] cache = new byte[CACHE_SIZE];  

        int nRead = 0;  

        while ((nRead = in.read(cache)) != -1) {     

            out.write(cache, 0, nRead);  

            out.flush();  

        in.close();  

RSATester.java

java RSA加密生成license,用CPU序列号生成機器碼

public class RSATester {  

    static String publicKey;  

    static String privateKey;  

    static {  

        try {  

            Map<String, Object> keyMap = RSAUtils.genKeyPair();  

            publicKey = RSAUtils.getPublicKey(keyMap);  

            privateKey = RSAUtils.getPrivateKey(keyMap);  

            System.err.println("公鑰: \n\r" + publicKey);  

            System.err.println("私鑰: \n\r" + privateKey);  

        } catch (Exception e) {  

            e.printStackTrace();  

    public static void main(String[] args) throws Exception {  

        test();  

        testSign();  

    static void test() throws Exception {  

        System.err.println("公鑰加密——私鑰解密");  

        String source = "這是一行沒有任何意義的文字,你看完了等于沒看,不是嗎?";  

        System.out.println("\r加密前文字:\r\n" + source);  

        byte[] data = source.getBytes();  

        byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);  

        System.out.println("加密後文字:\r\n" + new String(encodedData));  

        byte[] decodedData = RSAUtils.decryptByPrivateKey(encodedData, privateKey);  

        String target = new String(decodedData);  

        System.out.println("解密後文字: \r\n" + target);  

    static void testSign() throws Exception {  

        System.err.println("私鑰加密——公鑰解密");  

        String source = "這是一行測試RSA數字簽名的無意義文字";  

        System.out.println("原文字:\r\n" + source);  

        byte[] encodedData = RSAUtils.encryptByPrivateKey(data, privateKey);  

        System.out.println("加密後:\r\n" + new String(encodedData));  

        byte[] decodedData = RSAUtils.decryptByPublicKey(encodedData, publicKey);  

        System.out.println("解密後: \r\n" + target);  

        System.err.println("私鑰簽名——公鑰驗證簽名");  

        String sign = RSAUtils.sign(encodedData, privateKey);  

        System.err.println("簽名:\r" + sign);  

        boolean status = RSAUtils.verify(encodedData, publicKey, sign);  

        System.err.println("驗證結果:\r" + status);  

運作此類生成license 

LicenseGenerator.java

java RSA加密生成license,用CPU序列号生成機器碼

/** 

 * 生成license 

 * @author happyqing 

 * 2014.6.15 

public class LicenseGenerator {  

    /** 

     * serial:由客戶提供 

     * timeEnd:過期時間 

    private static String licensestatic = "serial=568b8fa5cdfd8a2623bda1d8ab7b7b34;" +  

                                          "timeEnd=1404057600000";  

    private static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaa8y9g+ioR2OSs8njT5uCGWm0YmOA1elSu/P5\n"  

            + "D3XYPCHsUPab74V5Og+NEZeTk9/LtG+jPSpKekTWm67gS2lQYWoygTwnoWsr4woaqNXmWw7L8Ty0\n"  

            + "LQFTojZgyynvu2RSIJp4c76z6SV/khiP/ireGtt8uzXPswPO5uaPU38tQQIDAQAB";  

     * RSA算法 

     * 公鑰和私鑰是一對,此處隻用私鑰加密 

    public static final String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJprzL2D6KhHY5KzyeNPm4IZabRi\n"  

            + "Y4DV6VK78/kPddg8IexQ9pvvhXk6D40Rl5OT38u0b6M9Kkp6RNabruBLaVBhajKBPCehayvjChqo\n"  

            + "1eZbDsvxPLQtAVOiNmDLKe+7ZFIgmnhzvrPpJX+SGI/+Kt4a23y7Nc+zA87m5o9Tfy1BAgMBAAEC\n"  

            + "gYAVnlfohEoTHQN0q1TtTNzRhutEhK23gLsMiSGr0Z1G64w4QFF2HT9LbHR25GqbD426QAWNDegY\n"  

            + "yytN/DesUQJqNXx8vuEuqs7+MQDgKgJqpAx+Fg3Iwsk/SVjq7meaSVGCgPKhtWHJk5oXoRMpsrlT\n"  

            + "AwUjpdpAZXIIKW3mrqkW0QJBANq4INw6lZlqRFtxT4uzYQYtzmB/nxMnCbL2SQ4ZQ/4CWlQpOnR/\n"  

            + "mH2JxIBCVtTADFlPM0DWF4aoqykYs9tu2X0CQQC0vgEk8DpkQbh1kgIyBGWCqYSKISTSXia0rbYo\n"  

            + "FPnzdldgtZVirNGNmiJGL8RPz0YKpZNOg9FLHq/oYXSNFI4VAkAJ4OcbC0pWc4ZC2wtMs/1d2hPI\n"  

            + "J/t3UfwOKTGDgYCgqFqMEpChUmIAyYgmgtiJI2NrZThbZVAKtPOGF6eH8anBAkAbxkL4wS3H8E1/\n"  

            + "S7OoqgJLZO9oJpW4+hzqkPM4D5klb58Xzm+pXTNKllAEBx0cwpZZ1n3fh+Qmrg2MIUW+1FTNAkBt\n"  

            + "WECowLUqW014M96WsFpiof7kjteOBNOjFyxhIbx2eT7//bnrADfq2Xu1/mSedUKrjGr/O+FRi7PO\n"  

            + "u7WhF6C9";  

    public static void generator() throws Exception {  

        //String source = "568b8fa5cdfd8a2623bda1d8ab7b7b34";  

        System.out.println("原文字:\r\n" + licensestatic);  

        byte[] data = licensestatic.getBytes();  

        System.out.println("加密後:\r\n" + new String(encodedData)); //加密後亂碼是正常的  

        Base64Utils.byteArrayToFile(encodedData, FileUtil.getBasePath()+File.separator+"license.dat");  

        System.out.println("license.dat:\r\n" + FileUtil.getBasePath()+File.separator+"license.dat");  

        //解密  

        generator();  

這裡把解密邏輯也放這裡了,實際上,公鑰和解密邏輯應該放在軟體運作的地方。

FileUtil.java

java RSA加密生成license,用CPU序列号生成機器碼

import java.io.FileNotFoundException;  

import java.io.IOException;  

import java.io.UnsupportedEncodingException;  

import java.net.URLDecoder;  

import java.util.logging.Level;  

import java.util.logging.Logger;  

 * 檔案工具類 

public class FileUtil {  

     * 獲得類的基路徑,打成jar包也可以正确獲得路徑 

     * @return  

    public static String getBasePath(){  

        /* 

        /D:/zhao/Documents/NetBeansProjects/docCompare/build/classes/ 

        /D:/zhao/Documents/NetBeansProjects/docCompare/dist/bundles/docCompare/app/docCompare.jar 

        */  

        String filePath = FileUtil.class.getProtectionDomain().getCodeSource().getLocation().getFile();  

        if (filePath.endsWith(".jar")){  

            filePath = filePath.substring(0, filePath.lastIndexOf("/"));  

            try {  

                filePath = URLDecoder.decode(filePath, "UTF-8"); //解決路徑中有空格%20的問題  

            } catch (UnsupportedEncodingException ex) {  

        filePath = file.getAbsolutePath();  

        return filePath;  

        System.out.println(getBasePath());  

serial是軟體運作的地方提供的,

純java擷取CPU序列号,生成機器碼

http://happyqing.iteye.com/blog/2080402

參考

http://www.blogjava.net/icewee/archive/2012/05/19/378570.html

一個簡單的RSA加密類

http://yuncode.net/code/c_5049f78253ad762

RSAEncrypt.java

java RSA加密生成license,用CPU序列号生成機器碼

 * RSA加密類 

public class RSAEncrypt {  

    public static void main(String[] args) {  

            RSAEncrypt encrypt = new RSAEncrypt();  

            String encryptText = "12345678";  

            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");  

            keyPairGen.initialize(1024);  

            KeyPair keyPair = keyPairGen.generateKeyPair();  

            // Generate keys  

            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 私鑰  

            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 公鑰  

            byte[] e = encrypt.encrypt(publicKey, encryptText.getBytes());  

            byte[] de = encrypt.decrypt(privateKey, e);  

            System.out.println(encrypt.bytesToString(e));  

            System.out.println();  

            System.out.println(encrypt.bytesToString(de));  

     * byte數組轉為string 

     * @param encrytpByte 

    protected String bytesToString(byte[] encrytpByte) {  

        String result = "";  

        for (Byte bytes : encrytpByte) {  

            result += (char) bytes.intValue();  

        return result;  

     * 加密方法 

     * @param publicKey 

     * @param obj 

    protected byte[] encrypt(RSAPublicKey publicKey, byte[] obj) {  

        if (publicKey != null) {  

                Cipher cipher = Cipher.getInstance("RSA");  

                cipher.init(Cipher.ENCRYPT_MODE, publicKey);  

                return cipher.doFinal(obj);  

            } catch (Exception e) {  

                e.printStackTrace();  

        return null;  

     * 解密方法 

     * @param privateKey 

    protected byte[] decrypt(RSAPrivateKey privateKey, byte[] obj) {  

        if (privateKey != null) {  

                cipher.init(Cipher.DECRYPT_MODE, privateKey);  

說明:

公鑰私鑰要自己生成,别拷别人的

`=_=`