『壹』 java類中經常會出現一個常量是序列號,序列號是什麼意思
serialVersionUID作用:
序列化時為了保持版本的兼容性,即在版本升級時反序列化仍保持對象的唯一性。
有兩種生成方式:
一個是默認的1L,比如:private static final long serialVersionUID = 1L;
一個是根據類名、介面名、成員方法及屬性等來生成一個64位的哈希欄位,比如:
private static final long serialVersionUID = xxxxL;
當你一個類實現了Serializable介面,如果沒有定義serialVersionUID,Eclipse會提供這個
提示功能告訴你去定義 。在Eclipse中點擊類中warning的圖標一下,Eclipse就會
自動給定兩種生成的方式。如果不想定義它,在Eclipse的設置中也
可以把它關掉的,設置如下:
Window ==> Preferences ==> Java ==> Compiler ==> Error/Warnings ==>
Potential programming problems
將Serializable class without serialVersionUID的warning改成ignore即可。
如果你沒有考慮到兼容性問題時,就把它關掉,不過有這個功能是好的,只要任何類別實現了Serializable這個介面的話,如果沒有加入serialVersionUID,Eclipse都會給你warning提示,這個serialVersionUID為了讓該類別Serializable向後兼容。
如果你的類Serialized存到硬碟上面後,可是後來你卻更改了類別的field(增加或減少或改名),當你Deserialize時,就會出現Exception的,這樣就會造成不兼容性的問題。
但當serialVersionUID相同時,它就會將不一樣的field以type的預設值Deserialize,可避開不兼容性問題。
『貳』 跪求在JAVA里如何獲得CPU的序列號,和硬碟的序列號。
利用Runtime call操作系統的命令,具體的命令取決於不同的操作系統,注意不要調用Runtime.getRuntime().exec(String)介面,要用Runtime.getRuntime().exec(String[])這個介面,不然復雜命令的執行會有問題。例子如下(拿cpu個數,其他類似):
定義命令:
WindowsCmd ="cmd.exe /c echo %NUMBER_OF_PROCESSORS%";//windows的特殊
SolarisCmd = {"/bin/sh", "-c", "/usr/sbin/psrinfo | wc -l"};
AIXCmd = {"/bin/sh", "-c", "/usr/sbin/lsdev -Cc processor | wc -l"};
HPUXCmd = {"/bin/sh", "-c", "echo \"map\" | /usr/sbin/cstm | grep CPU | wc -l "};
LinuxCmd = {"/bin/sh", "-c", "cat /proc/cpuinfo | grep ^process | wc -l"};
然後判斷系統:
os = System.getProperty("os.name").toLowerCase();
根據不同的操作系統call不同的命令。
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
public class GetMACAddress
{
public String getMACAddress(String ipAddress)
{
String str = "",strMAC = "",macAddress = "";
try
{
Process pp = Runtime.getRuntime().exec("nbtstat -a " + ipAddress);
InputStreamReader ir = new InputStreamReader(pp.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
for(int i = 1;i < 100;i++)
{
str = input.readLine();
if(str != null)
{
if(str.indexOf("MAC Address") > 1)
{
strMAC = str.substring(str.indexOf("MAC Address") + 14,str.length());
break;
}
}
}
}
catch(IOException ex)
{
return "Can't Get MAC Address!";
}
//
if(strMAC.length() < 17)
{
return "Error!";
}
macAddress = strMAC.substring(0,2) + ":"
+ strMAC.substring(3,5) + ":"
+ strMAC.substring(6,8) + ":"
+ strMAC.substring(9,11) + ":"
+ strMAC.substring(12,14) + ":"
+ strMAC.substring(15,17);
//
return macAddress;
}
public static void main(String[] args)
{
GetMACAddress getMACAddress = new GetMACAddress();
System.out.println(getMACAddress.getMACAddress("172.18.8.225"));
try
{
java.lang.Process proc = Runtime.getRuntime().exec("ipconfig /all");
InputStream istr = proc.getInputStream();
byte[] data = new byte[1024];
istr.read(data);
String netdata = new String(data);
System.out.println("Your Mac Address=" + procAll(netdata));
}
catch(IOException e)
{
System.out.println("error=" + e);
}
}
public static String procAll(String str)
{
return procStringEnd(procFirstMac(procAddress(str)));
}
public static String procAddress(String str)
{
int indexof = str.indexOf("Physical Address");
if(indexof > 0)
{
return str.substring(indexof,str.length());
}
return str;
}
public static String procFirstMac(String str)
{
int indexof = str.indexOf(":");
if(indexof > 0)
{
return str.substring(indexof + 1,str.length()).trim();
}
return str;
}
public static String procStringEnd(String str)
{
int indexof = str.indexOf("\r");
if(indexof > 0)
{
return str.substring(0,indexof).trim();
}
return str;
}
}
import java.util.Vector;
class GetNetMAC
{
//網卡物理地址長度
static private final int _physicalLength = 16;
public static void main(String[] args)
{
//output you computer phycail ip address
System.out.println("The MAC Addressis:\t" + getPhysicalAddress());
}
static public String getPhysicalAddress()
{
GetNetMACShell shell = new GetNetMACShell();
String cmd = "cmd.exe /c ipconfig/all";
Vector result;
result = shell.execute(cmd);
return parseCmd(result.toString());
}
//從字元串中解析出所需要獲得的字元串
static private String parseCmd(String s)
{
String find = "Physical Address. . . . . . . . . :";
int findIndex = s.indexOf(find);
if(findIndex == -1)
{
return "not find";
}
else
{
return s.substring(findIndex + find.length() + 1,findIndex + find.length() + 1 + _physicalLength);
}
}
}
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.InputStreamReader;
import java.util.Vector;
public class GetNetMACShell
{
private Process process = null;
public Vector execute(String shellCommand)
{
try
{
Start(shellCommand);
Vector vResult = new Vector();
DataInputStream in = new DataInputStream(process.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
do
{
line = reader.readLine();
if(line == null)
{
break;
}
else
{
vResult.addElement(line);
}
}
while(true);
reader.close();
return vResult;
}
catch(Exception e)
{
//error
return null;
}
}
public void Start(String shellCommand)
{
try
{
if(process != null)
{
kill();
}
Runtime sys = Runtime.getRuntime();
process = sys.exec(shellCommand);
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
public void kill()
{
if(process != null)
{
process.destroy();
process = null;
}
}
}
試試是否可以:)
『叄』 如何用java語言對即時通訊軟體進行加密
一、Java軟體加密基本思路
對於應用軟體的保護筆者從兩個方面進行考慮,第一是阻止盜版使用軟體,第二是阻止競爭對手對軟體反編譯,即阻止對軟體的逆向工程。
1、阻止盜版
在軟體運行時對自身存在的合法性進行判斷,如果認為自身的存在和運行是被授權的、合法的,就運行;否則終止運行。這樣即使軟體可以被隨意復制,只要盜版用戶沒有相應的授權信息就無法使用軟體。
2、阻止反編譯
對編譯產生的Class文件加密處理,並在運行時進行解密,解密者無法對軟體進行反編譯。
二、Java軟體加密的總體流程
為了保護用Java語言開發的軟體,我們設計並實現了一個實用、高強度的加密演算法。以下稱需要保護的Java軟體為「受保護程序」,稱對「受保護程序」進行加密保護的軟體為「加密程序」。對軟體加密保護的流程如圖1所示。
三、加密演算法分析設計
1、用戶信息提取器設計
為了防止用戶發布序列號而導致「一次發行,到處都是」的盜版問題,提取用戶機器中硬體相關的、具有唯一性的信息——用戶計算機的硬碟分區C的序列號,並要求用戶將此信息與用戶名一起返回,之後用「序列號生成器」根據用戶返回信息生成一個唯一合法的軟體注冊序列號發回用戶,用戶即可使用此號碼注冊使用軟體。
這個信息提取器使用Winclows 32匯編以一個獨立的小程序方式實現,程序代碼如圖2所示。
2、序列號生成器與序列號合法性判斷函數的設計
序列號生成器與序列號合法性判斷函數中運用RSA加密演算法。在序列號生成器中是使用私鑰將用戶返回的信息(硬碟序列號,用戶名)進行加密得到相應的注冊序列號;在序列號合法性判斷函數中使用私鑰將用戶輸入的注冊序列號解密,再與(硬碟序列號,用戶名)進行比較,一致則調用程序裝載器將程序其他部分解密裝入內存,初始化刪環境並運行程序主體;否則退出。
RSA加密演算法的實現需要使用大數運算庫,我們使用MIRACL大數庫來實現RSA計算,序列號生成器的主要代碼如下:
char szlnputString[]=」機器碼和用戶名組成的字元串」;
char szSerial[256]=[0];//用於存放生成的注冊碼
bign,d,c,m; //MIRACL中的大數類型
mip→IBASE=16; //以16進制模式
n= mlrvar(0); //初始化大數
d= mirvar(0);
c= mirvar(0); //C存放輸入的字元串大數
m= mlrva(o);
bytes to big( len, szlnputString,c);
//將輸入字元串轉換成大數形式並存入變數c中
cinstr(n,」以字元串形成表示的模數」);//初始化模數
cinstr(d,」以字元串形成表示的公鑰」)://初始化公鑰
powmod(c,d,n,m); //計算m=cdmod n
cotstr(m,szSerial);//m的16進制字元串即為注冊碼
序列號合法性檢測函數的主要代碼如下:
char szlnputStringL]=」機器碼和用戶名組成的字元串」;
char szSerial[ 256]=」用戶輸入的序列號」
bign,e,c,m; //MIRACL中的大數類型
mip→IBASE=16; //以16進制模式
cinstr(m,szSerial); //將序列號的16進制轉成大數形式
cinstr(n,」模數n的字元串形式」);//初始化模數n
cinstr(e,」字元串形式的公鑰」);//初始化公鑰
if compare(m,n)==-1) //m<n時才進行解密
{
powmod(m,e,n,c);//計算m=me mod n
big_to _bytes(0,c,szSerial,0); //轉為字元串
return lstrcmp( szlnputString,szSerial);
}
3、強耦合關系的設計
如果在序列號合法性檢測函數中簡單地使用圖3所示流程:
解密者可以使用以下幾種手段進行攻擊:
(1)修改「判斷合法性子函數」的返回指令,讓它永遠返回正確值,這樣可以使用任意的序列號,安裝/使用軟體。
(2)修改判斷後的跳轉指令,使程序永遠跳到正確的分支運行,效果和上一種一樣。
(3)在「判斷合法性子函數」之前執行一條跳轉指令,繞過判斷,直接跳轉到「正常執行」分支運行,這樣可以不用輸入序列號安裝/使用軟體。
為阻止以上攻擊手段,筆者在程序中增加了「序列號合法性檢測函數」與程序其他部分「強耦合」(即增強其與程序其他部分的關聯度,成為程序整體密不可分的一部分,一旦被修改程序將無法正常工作)的要求(見圖1),並且設置一個「完整性檢測函數」用於判斷相關的代碼是否被修改過。當然,基於同樣的原因,「完整性檢測函數」也必須與程序其他部分存在「強耦合」關系。
強耦合關系通過以下方式建立:
在程序其他部分的函數(例如函數A)中隨機的訪問需要強耦合的「序列號合法性檢測函數」和「完整性檢測函數」,在調用時隨機的選擇使用一個錯誤的序列號或是用戶輸入的序列號,並根據返回結果選擇執行A中正常的功能代碼還是錯誤退出的功能代碼,流程如圖4所示。
經過這種改進,如果破解者通過修改代碼的方式破解將因「完整性檢測」失敗導致程序退出;如果使用SMC等技術繞過「序列號合法性判斷函數」而直接跳至序列號正確時的執行入口,在後續的運行中,將因為隨機的耦合調用失敗導致程序退出。破解者要破解軟體將不得不跟蹤所有進行了耦合調用的函數,這顯然是一個艱巨的任務。
4、完整性檢測函數的設計
我們使用CRC演算法算出需進行完整性檢測的文件的校驗碼,並用RSA加密演算法的公鑰(不同於序列號合法性檢測中的公鑰/私鑰對)將其加密存放在特定的文件中,在檢測時先用CRC演算法重新生成需進行完
整性檢測的文件的校驗碼,並用私鑰將保存的校驗碼解密,兩者相比較,相等則正常運行;否則退出。
5、程序載入器的設計
與編譯成機器碼執行的程序不同,Java程序只能由Java虛擬機解釋執行,因此程序載入器的工作包括:初始化Java虛擬機;在內存中解密當前要運行的class文件;使解密後的c:lass文件在虛擬機中運行,在
需要時解密另一個class文件。圖5是用於初始化JVM的代碼:
以上介紹了我們設計的針對Java軟體的加密保護方法,其中綜合運用了多種加密技術,抗破解強度高;使用純軟體保護技術,成本低。經筆者在Windows系列平台上進行測試,運行穩定,效果良好。
在研宄開發過程中,我們還總結出加密保護軟體的一些經驗:
1、對關鍵代碼和數據要靜態加密,再動態解密執行;要結合具體的工作平台使用反跟蹤/調試技術;
2、要充分利用系統的功能,如在Windows下使用DLL文件或驅動程序形式能得到最大的豐又限,可以充分利用系統具有的各種功能;
3、如果可能應該將關鍵代碼存放在不可禚復制的地方;
4、序列號要與機器碼等用戶信息相關以阻止鹽復布序列號;
5、加密流程的合理性比加密演算法本身的強度更重要。
『肆』 求java自動生成一個序列號的方法,急急急...
package com.test4;
public class Test7 {
public static void main(String[] args) {
System.out.println(getNum("20100505",3));
}
//假設資料庫里有個20100505005的編號
private static String getNum(String firstPart, int len) {
//調用資料庫獲內得20100505005這個容編號
String oldNum = "20100505005";
int num = Integer.parseInt(oldNum.replace(firstPart,""));
String numStr = ++num +"";
int length = numStr.length();
for (int i = length; i < len; i++) {
numStr = "0"+numStr;
}
return firstPart + numStr;
}
}