admin管理员组文章数量:1026989
java jar包签名
JAR文件可以用 jarsigner工具或者直接通过 java.securityAPI 签名。签名后的JAR 本身的文件
文件与原来JAR本身的 文件完全相同,只是更新了它的 manifest文件,并在 META-INF 目录中
增加了两个文件,一个签名文件和一个签名块文件。
JAR文件可以用一个存储在 Keystore数据库中的证书进行签名的。存储在 keystore 中的证书
有密码保护,必须向 jarsigner工具提供这个密码才能对 JAR 文件签名。
Jar文件使用jarsigner签名以后,在META-INF文件夹下会多出两个文件:XXX.SF文件与XXX.YYY
文件。XXX应该与你签名时使用密钥的别名一致.而XXX.YYY的扩展名,根据数字签名的类型RSA
、DSA 或者 PGP 以及用于签名 JAR 的证书类型而有不同的扩展名。XXX.SF文件的格式类似于
manifest 文件(一组 RFC-822 头)。XXX.SF文件主要包括的对JAR本身文件及Manifest文件的签
名码(加密后的散列码)。奇怪的是进行签名后Manifest文件中也有针对JAR本身文件的签名码,
且和XXX.SF文件中的不一样。为什么会有两个呢?不解。在XXX.YYY文件(比如TEST.RSA)中
,除了签名私钥所对应的公钥外,还包含了签名者的一些信息。
在验证一个签名的 JAR 时,将签名文件的摘要值与对 JAR 文件中的相应项计算的摘要值进行
比较。
MANIFEST.MF文件:
Manifest-Version: 1.0
Created-By: 1.6.0_11 (Sun Microsystems Inc.)
Main-Class: Hello
Name: Util.class
SHA1-Digest: UQkSPocH+hEH4W8d4/E7ifo7Y2A=
Name: Hello.class
SHA1-Digest: HQJfMvXm5JhrX2afxITiicvzDdQ=
TEST.SF文件
Signature-Version: 1.0
SHA1-Digest-Manifest-Main-Attributes: +yrcddwVI7QFdviahKRNKIHg2Zc=
Created-By: 1.6.0_11 (Sun Microsystems Inc.)
SHA1-Digest-Manifest: dCxOoUzPsGXrxxYH5PRNx47Er7M=
Name: Util.class
SHA1-Digest: 5g4n0t4ScMDowIF10vD7pMtcM1g=
Name: Hello.class
SHA1-Digest: OvGpI1SCZ7Py8O0rjqUUsZT6H/Q=
Keystore
要签名一个 JAR 文件,必须首先有一个私钥。私钥及其相关的公钥证书存储在名为keystores
的、有密码保护的数据库中。JDK 包含创建和修改 keystores 的工具。keystore 中的每一个密
钥都可以用一个别名标识,它通常是拥有这个密钥的签名者的名字。
所有 keystore 项 ( 密钥和信任的证书项 ) 都是用唯一别名访问的。别名是在用 keytool -
genkey 命令生成密钥对 ( 公钥和私钥 ) 并在 keystore 中添加项时指定的。之后的 keytool命
令必须使用同样的别名引用这一项。
例如,要生成一个别名为“robin”生成一个新的公钥 / 私钥对并将公钥包装到自签名的证书中,
要使用下述命令:
例1
keytool -genkey -alias robin -keystore robin.keystore -storepass GL2009 -keypass gl2009 -
validity 100 -keyalg RSA -keysize 1024 -sigalgMD5withRSA
这个命令序列用于生成一个名为的公钥/私钥对名字为robin,并把它添加到文件名为
robin.keystore的keystore文件中,如果该文件还不存在,则创建它。其中文件名密码为
GL2009,要添加的公钥/私钥对的私钥密码为gl2009,文件有效期为100天,公钥/私钥对名字
为robin,公钥/私钥对采用RSA算法,公钥/私钥的长度为1024,签名时采用MD5withRSA算法
(用MD5算法进行散列,用RSA算法对其散列码进行加密)
然后按照提示输入一些信息,如下:
What is your first and last name?
[Unknown]: hubing
What is the name of your organizational unit?
[Unknown]: GL
What is the name of your organization?
[Unknown]: gameloft
What is the name of your City or Locality?
[Unknown]: chengdu
What is the name of your State or Province?
[Unknown]: shichuan
What is the two-letter country code for this unit?
[Unknown]: cn
Is CN=hubing, OU=GL, O=gameloft, L=chengdu, ST=shichuan, C=cn correct?
[no]: yes
jarsigner 工具
通过jarsigner工具,可以使用 keystore 生成或者验证 JAR 文件的数字签名。
假设像例1那样创建了keystore文件robin.keystore,可以用下面的命令签名一个 JAR 文件:
例2
jarsigner -keystore robin.keystore -storepass GL2009 -keypass gl2009 Hello.jar robin
这个命令用密码“GL2009”从名为“robin.keystore”的keystore文件中提出名字为“robin”、密码为
“gl2009”的公钥/私钥对,并对Hello.jar 文件按照keystore文件robin.keystore中的约定进行数字
签名。
例3
jarsigner -keystore robin.keystore -storepass GL2009 -keypass gl2009 -signedjar
Hello_signed.jar Hello.jar robin
这个命令用密码“GL2009”从名为“robin.keystore”的keystore文件中提出名字为“robin”、密码为
“gl2009”的公钥/私钥对,并对Hello.jar 文件按照keystore文件robin.keystore中的约定进行数字
签名,签名的输出文件为Hello_signed.jar。
jarsigner工具还可以验证一个签名的 JAR 文件,很简单,只需执行以下命令:
jarsigner -verify Hello.jar
如果签名的 JAR 文件没有被篡改过,那么 jarsigner工具就会告诉您 JAR 通过验证了。否则,
它会抛出一个 SecurityException, 表明哪些文件没有通过验证。还可以用 java.util.jar和
java.securityAPI 以编程方式签名 JAR
java jar 包文件签名步骤
java 的jar包签名.可以防止别人篡改被签名的jar包.
步骤:
(1)将java程序打包
jar cvf test.jar test.class
(2)生成名为caoyong.store的密钥库,别名为caoyong
keytool -genkey -keystore caoyong.store -alias mcni
密码:123456 (根据需要自己输入) 以下根据需要输入,最后确认:y
(3)导出caoyong.cer数字证书
keytool -export -keystore caoyong.store -alias mcni -file caoyong.cer
密码:123456 (根据需要自己输入)
(4)对test.jar文件进行签名
jarsigner -keystore caoyong.store test.jar caoyong
密码:123456 (根据需要自己输入)
另外
一条警告说该证名书只能使用6个月。为了能使应用程序不受时间的限制,keytool命令提供了
一个参数validity,利用它可以指定签名有效日。例如:
keytool -genkey -keystore caoyong.store -alias caoyong -validity 55555
动态加载jar包
代码如下:
package my.jar;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Method;
import java.MalformedURLException;
import java.URL;
import java.URLClassLoader;
public class JarLoader
{
private URLClassLoader urlClassLoader;
public JarLoader(URLClassLoader urlClassLoader)
{
this.urlClassLoader = urlClassLoader;
}
public void loadJar(URL url) throws Exception
{
Method addURL = URLClassLoader.class.getDeclaredMethod(“addURL”,
URL.class);
addURL.setAccessible(true);
addURL.invoke(urlClassLoader, url);
}
private static void loadjar(JarLoader jarLoader, String path) throws
MalformedURLException, Exception
{
File libdir = new File(path);
if (libdir != null && libdir.isDirectory())
{
File[] listFiles = libdir.listFiles(new FileFilter()
{
public boolean accept(File file)
{
return file.exists() && file.isFile() &&
file.getName().endsWith(".jar");
}
});
for (File file : listFiles)
{
jarLoader.loadJar(file.toURI().toURL());
}
} else
{
System.out.println("[Console Message] Directory [" + path + "]
does not exsit, please check it");
System.exit(0);
}
}
public static void main(String[] args) throws MalformedURLException, Exception
{
JarLoader jarLoader = new JarLoader((URLClassLoader)
ClassLoader.getSystemClassLoader());
loadjar(jarLoader, System.getProperty(“user.dir”) + “/lib”);
}
}
dsa加密
package my.security;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
public class Testdsa
{
public static void main(String[] args) throws java.security.NoSuchAlgorithmException, java.lang.Exception
{
Testdsa my = new Testdsa();
my.run();
}
public void run()
{
// 数字签名生成密钥
// 第一步生成密钥对,如果已经生成过,本过程就可以跳过,对用户来讲myprikey.dat要保存在本地
// 而mypubkey.dat给发布给其它用户
if ((new java.io.File(“myprikey.dat”)).exists() == false)
{
if (generatekey() == false)
{
System.out.println(“生成密钥对败”);
return;
}
;
}
// 第二步,此用户
// 从文件中读入私钥,对一个字符串进行签名后保存在一个文件(myinfo.dat)中
// 并且再把myinfo.dat发送出去
// 为了方便数字签名也放进了myifno.dat文件中,当然也可分别发送
try
{
java.io.ObjectInputStream in = new java.io.ObjectInputStream(new java.io.FileInputStream(“myprikey.dat”));
PrivateKey myprikey = (PrivateKey) in.readObject();
in.close();
// java.security.spec.X509EncodedKeySpec pubX509=new
// java.security.spec.X509EncodedKeySpec(bX509);
// java.security.spec.X509EncodedKeySpec
// pubkeyEncode=java.security.spec.X509EncodedKeySpec
String myinfo = “这是我的信息”; // 要签名的信息
// 用私钥对信息生成数字签名
java.security.Signature signet = java.security.Signature.getInstance(“DSA”);
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[] signed = signet.sign(); // 对信息的数字签名
System.out.println(“signed(签名内容)=” + byte2hex(signed));
// 把信息和数字签名保存在一个文件中
java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(new java.io.FileOutputStream(“myinfo.dat”));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
System.out.println(“签名并生成文件成功”);
} catch (java.lang.Exception e)
{
e.printStackTrace();
System.out.println(“签名并生成文件失败”);
}
;
// 第三步
// 其他人通过公共方式得到此户的公钥和文件
// 其他人用此户的公钥,对文件进行检查,如果成功说明是此用户发布的信息.
//
try
{
java.io.ObjectInputStream in = new java.io.ObjectInputStream(new java.io.FileInputStream(“mypubkey.dat”));
PublicKey pubkey = (PublicKey) in.readObject();
in.close();
System.out.println(pubkey.getFormat());
in = new java.io.ObjectInputStream(new java.io.FileInputStream(“myinfo.dat”));
String info = (String) in.readObject();
byte[] signed = (byte[]) in.readObject();
in.close();
java.security.Signature signetcheck = java.security.Signature.getInstance(“DSA”);
signetcheck.initVerify(pubkey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed))
{
System.out.println(“info=” + info);
System.out.println(“签名正常”);
} else
System.out.println(“非签名正常”);
} catch (java.lang.Exception e)
{
e.printStackTrace();
}
}
// 生成一对文件myprikey.dat和mypubkey.dat—私钥和公钥,
// 公钥要用户发送(文件,网络等方法)给其它用户,私钥保存在本地
public boolean generatekey()
{
try
{
java.security.KeyPairGenerator keygen = java.security.KeyPairGenerator.getInstance(“DSA”);
// SecureRandom secrand=new SecureRandom();
// secrand.setSeed(“tttt”.getBytes()); //初始化随机产生器
// keygen.initialize(576,secrand); //初始化密钥生成器
keygen.initialize(512);
KeyPair keys = keygen.genKeyPair();
// KeyPair keys=keygen.generateKeyPair(); //生成密钥组
PublicKey pubkey = keys.getPublic();
PrivateKey prikey = keys.getPrivate();
java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(
new java.io.FileOutputStream(“myprikey.dat”));
out.writeObject(prikey);
out.close();
System.out.println(“写入对象 prikeys ok”);
out = new java.io.ObjectOutputStream(new java.io.FileOutputStream(“mypubkey.dat”));
out.writeObject(pubkey);
out.close();
System.out.println(“写入对象 pubkeys ok”);
System.out.println(“生成密钥对成功”);
return true;
} catch (java.lang.Exception e)
{
e.printStackTrace();
System.out.println(“生成密钥对失败”);
return false;
}
}
public String byte2hex(byte[] b)
{
String hs = “”;
String stmp = “”;
for (int n = 0; n < b.length; n++)
{
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1)
hs = hs + “0” + stmp;
else
hs = hs + stmp;
if (n < b.length - 1)
hs = hs + “:”;
}
return hs.toUpperCase();
}
}
实践对jar包的代码签名完整示例
第一步,首先配置jdk的环境变量,如果你的电脑已经配置了,那直接跳过这一步
path=%JAVA_HOME%/bin
JAVA_HOME=C:/Java/jdk1.6.0_01
CLASSPATH=.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar
配置要这几个jdk的环境参数,好了,配完了,试着在cmd里跑一下java,javac,看看命令是否生效,如果配置成功执行第二步。
第二步,来写几个简单的类,简单的才是大家的。你完全可以直接copy我的代码,部分看不懂,忽略它,做实验而已,对那个jar文件签名不是签,这个例子的代码逻辑是后面才用到的,不用读第一个类Doer
package com.yfq.test;
public abstract interface Doer {
void doYourThing();
}
第二个类
package com.yfq.test.friend;
import java.security.AccessController;
import java.security.PrivilegedAction;
import com.yfq.test.Doer;
public class Friend implements Doer{
private Doer next;
private boolean direct;
public Friend(Doer next,boolean direct){this.next=next;this.direct=direct;
}@Override
public void doYourThing() {System.out.println("Im a Friend");if (direct) {next.doYourThing();} else {AccessController.doPrivileged(new PrivilegedAction() {@Overridepublic Object run() {next.doYourThing();return null;}});}
}
}
第三个类
package com.yfq.test.stranger;
import java.security.AccessController;
import java.security.PrivilegedAction;
import com.yfq.test.Doer;
public class Stranger implements Doer {
private Doer next;
private boolean direct;public Stranger(Doer next, boolean direct) {this.next = next;this.direct = direct;
}@Override
public void doYourThing() {System.out.println("Im a Stranger");if (direct) {next.doYourThing();} else {AccessController.doPrivileged(new PrivilegedAction() {@Overridepublic Object run() {next.doYourThing();return null;}});}
}
}
好了,编译一下,用强大的ecplise来编译,项目-右键-Build Project(工具是拿来用的,不要浪费这些强大的功能!)
第三步,打jar包,用ecplise就可以了就有导出jar包的功能,我还是那句老话,有工具不用,不是牛,是蠢。步骤一,项目-右键-Export-java-JAR file-next步骤二,展开目录清单-分别对com.yfq.tes.friend和com.yfq.test.stranger打包(friend.jar,stranger.jar),放到哪里就随便你了,只要你记得就好,我这里假设是放在d盘的根目录下第四步,用java的keytool生成密钥对,用java的jarsigner做签名(记得笔记七我们说过对hash摘要的加密是非对称加密的吗?这里就需要两把不同的钥匙啦),一步步跟我来。步骤一,cmd窗口,进入到存放friend.jar和stranger.jar的目录下,假设我的jar文件放在d盘下,直接输入盘符d:就可以了。步骤二,在cmd窗口中输入keytool -genkey -keystore ijvmkeys.keystore -keyalg RSA -validity 10000 -alias friend.keystore生成第一个密钥对,这个密钥对的别名是 friend.keystore,采用的加密算法为RSA,密钥对的过期时间是10000天,密钥对存储的文件名ijvmkeys.keystore,而查看ijvmkeys.keystore的密码和friend.keystore密钥对的查看密码我们设置为123456
注意:这里在设置名字和姓氏的时候要特别的注意,不要随便的乱写,否则将导致后面的签名失败,一般我们写完网络域名的形式如:www.keycoding这样。
步骤三,在cmd窗口输入,keytool -genkey -keystore ijvmkeys.keystore -keyalg RSA -validity 10000 -alias stranger.keystore按照步骤2的截图,一步一步输入吧,这个步骤是生成别名为stranger.keystore的密钥对。好了密钥对生成结束,看看你的jar文件目录下有没有多出一个文件ijvmkeys.keystore,是滴,这里生成了一个用于存放密钥对的文件。步骤四,查看生成的密钥文件,在cmd窗口输入keytool -list -v -keystore ijvmkeys.keystore步骤五,对jar进行摘要并对hash摘要进行加密生成签名,放置到jar文件结构的尾部在cmd窗口输入 jarsigner -verbose -keystore ijvmkeys.keystore friend.jar friend.keystorejarsigner -verbose -keystore ijvmkeys.keystore stranger.jar stranger.keystore步骤六,右键frend.jar和stranger.jar用rar解压器看看它们在META-INF目录下是否生成了两个附加的文件
而关于这两个附加文件的用处,我这里也简单的说明一下,首先从名字上来讲他是八个字符,他默认取我们的密钥对的名字的前八个字符做名字而因为我们的密钥对名字是friend.keystore所以生成的名字将点替换为下滑线。如果你想要自己指定名字在keytool后面加上-sigFile XXXX这个参数
另外FRIEND_K.SF这个文件我们简单的展开
Signature-Version: 1.0
SHA1-Digest-Manifest-Main-Attributes: QHukAYw2MtCop4vlrhjJDDro1fQ=
Created-By: 1.6.0_12 (Sun Microsystems Inc.)
SHA1-Digest-Manifest: YePdyFc1+FVdY1PIcj6WVuTJAFE=
Name: com/yfq/test/friend/Friend$1.class
SHA1-Digest: mj79V3+YKsRAzxGHpyFGhOdY4dU=
Name: com/yfq/test/friend/Friend.class
SHA1-Digest: tqPfF2lz4Ol8eJ3tQ2IBvvtduj0=
它包含了签名的版本,签名者,还有被签名的类名,以及这个类的hash摘要,第四行是整个本文件的摘要,用于jar包的校验
FRIEND_K.DSA 文件,SF 文件被签名且签名被放入 .DSA 文件。.DSA 文件还包含来自密钥仓库的证书或证书链(被编码到其中),它们鉴别与用于签名的私钥对应的公钥。
步骤七,校验jar包在cmd中输入jarsigner -verify friend.jar和jarsigner -verify stranger.jar到这里jar签名的实验已经完毕!!!!!
查看上面步骤四截图,我们来验证一下在笔记七里说过的话。
1.我们说过hash摘要是一个128的值,对不对呢,看证书指纹那一行,md5:…
你数一数总共有几个十六进制数,32个,一个十六进制数用4个位可以表示完,那么总共是几位,32*4=128,但是后面还有一个sha1的,怎么回事他貌似不止128位,是滴,散列函数多种多样,到底用那个散列函数,md5还是sha1这个就看你喜欢,而要使用哪个散列函数是可以指定的,keytool的参数-keyalg “DSA”,这个参数就是用来指定用什么散列算法的,默认的就是DSA,普通的128位散列数已经是安全的了。
2.在 笔记七中,记不记得最下面那个图,有一个认证机构会对解密签名(被加密的hash摘要)的公钥做认证(也就是加密公钥),并发布证书,我们这里没有认证机构,你有没有这个疑问?
keytool程序在生成密钥时,总是会生成一个自签名证书(自签名是指:如果附近没有认证机构,可以用私钥对公钥签名,生成一个自签名证书)
总结:
通过本章我们学习对一个jar进行签名,一个jar可以同时被多个机构或作者签名,看起来实验很复杂其实很简单。如果你还想了解更多关于jar包签名的知识,本人在这里推荐一篇文章(),本人自己在学习jar包签名的时候也从这篇文章中收益匪浅,希望它对你有帮助。
java keytool 工具
转自
Keytool 是一个JAVA环境下的安全钥匙与证书的管理工具,Keytool将密钥(key)和证书(certificates)存在一个称为keystore 的文件(受密码保护)中。
在keystore里,包含两种数据:
密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密)
可信任的证书实体(trusted certificate entries)——只包含公钥
jarsigner是JDK中包含的用于JAR文件签名和验证的工具。为Java档案文件(JAR)生成签名,以及对已签名的jar文件的进行校验。
JDK中ketyTool常用命令:
-genkey 在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书,(默认情况下,keystore会存在用户系统默认目录,如:win系统,会生成在C:\Documents and Settings\用户名\文件名为“.keystore”)
-alias 产生别名(default:mykey,每个keystore都关联这一个独一无二的alias,不区分大小写)
-keystore 指定密钥库的名称(产生的各类信息将不在.keystore文件中)
-keyalg 指定密钥的算法 (如RSA、DSA,default:DSA)
-validity 指定创建的证书有效期多少天(default:90)
-keysize 指定密钥长度(default:1024,范围:512 ~ 1024)
-storepass 指定密钥库的密码(获取keystore信息所需的密码)
-keypass 指定别名条目的密码(私钥的密码)
-dname 指定证书拥有者信息
例如: “CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=州或省份名称,C=单位的两字母国家代码”
-list 显示密钥库中的证书信息
keytool -list -v -keystore 指定keystore -storepass 密码 -v 显示密钥库中的证书详细信息
-export 将别名指定的证书导出到文件
keytool -export -alias 需要导出的别名 -keystore 指定keystore -file 指定导出的证书位置及证书名称 -storepass 密码
-delete 删除密钥库中某条目
keytool -delete -alias 指定需删除的keystore别名 -keystore 指定keystore -storepass 密码
-printcert 查看导出的证书信息
keytool -printcert -file yushan.crt
-keypasswd 修改密钥库中指定条目口令
keytool -keypasswd -alias 需修改的别名 -keypass 旧密码 -new 新密码 -storepass keystore密码 -keystore sage
-storepasswd 修改keystore口令
keytool -storepasswd -keystore e:\yushan.keystore(需修改口令的keystore) -storepass 123456(原始密码) -new yushan(新密码)
-import 将已签名数字证书导入密钥库
keytool -import -alias 别名 -keystore指定keystore -file需导入的证书
keytool 使用demo(注:.keystore可以换成.jks后缀):
1、keystore的生成:
分阶段生成:
keytool -genkey -alias yushan(别名) -keypass yushan(别名密码) -keyalg RSA(算法) -keysize 1024(密钥长度) -validity 365(有效期,天单位) -keystore
e:\yushan.keystore(指定生成证书的位置和证书名称) -storepass 123456(获取keystore信息的密码);
回车输入相关信息即可;
一次性生成:
keytool -genkey -alias yushan -keypass yushan -keyalg RSA -keysize 1024 -validity 365 -keystore e:\yushan.keystore -storepass 123456 -dname “CN=(名字与
姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称), ST=(州或省份名称), C=(单位的两字母国家代码)”;
(中英文即可)
2、keystore信息的查看:
keytool -list -v -keystore e:\keytool\yushan.keystore -storepass 123456
显示内容:
Keystore 类型: JKS
Keystore 提供者: SUN
您的 keystore 包含 1 输入
别名名称: yushan
创建日期: 2009-7-29
项类型: PrivateKeyEntry
认证链长度: 1
认证 [1]:
所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
序列号:4a6f29ed
有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
证书指纹:
MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
签名算法名称:SHA1withRSA
版本: 3
缺省情况下,-list 命令打印证书的 MD5 指纹。而如果指定了 -v 选项,将以可读格式打印证书,如果指定了 -rfc 选项,将以可打印的编码格式输出证书。
keytool -list -rfc -keystore e:\yushan.keystore -storepass 123456
显示:
Keystore 类型: JKS
Keystore 提供者: SUN
您的 keystore 包含 1 输入
别名名称: yushan
创建日期: 2009-7-29
项类型: PrivateKeyEntry
认证链长度: 1
认证 [1]:
-----BEGIN CERTIFICATE-----
MIICSzCCAbSgAwIBAgIESm8p7TANBgkqhkiG9w0BAQUFADBqMQ8wDQYDVQQGDAbkuK3lm70xDzAN
BgNVBAgMBua5luWNlzEPMA0GA1UEBwwG5rmY5r2tMREwDwYDVQQKDAh4eOWNj+S8mjERMA8GA1UE
CwwIeHjlhazlj7gxDzANBgNVBAMTBnl1c2hhbjAeFw0wOTA3MjgxNjQwMTNaFw0xMDA3MjgxNjQw
MTNaMGoxDzANBgNVBAYMBuS4reWbvTEPMA0GA1UECAwG5rmW5Y2XMQ8wDQYDVQQHDAbmuZjmva0x
ETAPBgNVBAoMCHh45Y2P5LyaMREwDwYDVQQLDAh4eOWFrOWPuDEPMA0GA1UEAxMGeXVzaGFuMIGf
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJoru1RQczRzTnBWxefVNspQBykS220rS8Y/oX3mZa
hjL4wLfOURzUuxxuVQR2jx7QI+XKME+DHQj9r6aAcLBCi/T1jwF8mVYxtpRuTzE/6KEZdhowEe70
liWLVE+hytLBHZ03Zhwcd6q5HUMu27du3MPQvqiwzTY7MrwIvQQ8iQIDAQABMA0GCSqGSIb3DQEB
BQUAA4GBAGoQQ1/FnTfkpQh+Ni6h3fZdn3sR8ZzDMbOAIYVLAhBb85XDJ8QZTarHbZMJcIdHxAl1
i08ct3E8U87V9t8GZFWVC4BFg/+zeFEv76SFpVE56iX7P1jpsu78z0m69hHlds77VJTdyfMSvtXv
sYHP3fxfzx9WyhipBwd8VPK/NgEP
-----END CERTIFICATE-----
3、证书的导出:
keytool -export -alias yushan -keystore e:\yushan.keystore -file e:\yushan.crt -storepass 123456
4、查看导出的证书信息
keytool -printcert -file yushan.crt
显示:(在windows下可以双击yushan.crt查看)
所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
序列号:4a6f29ed
有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
证书指纹:
MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
签名算法名称:SHA1withRSA
版本: 3
5、证书的导入:
准备一个导入的证书:
keytool -genkey -alias shuany -keypass shuany -keyalg RSA -keysize 1024 -validity 365 -keystore e:\shuany.keystore -storepass 123456 -dname “CN=shuany,
OU=xx, O=xx, L=xx, ST=xx, C=xx”;
keytool -export -alias shuany -keystore e:\shuany.keystore -file e:\shuany.crt -storepass 123456
现在将shuany.crt 加入到yushan.keystore中:
keytool -import -alias shuany(指定导入证书的别名,如果不指定默认为mykey,别名唯一,否则导入出错) -file e:\shuany.crt -keystore e:\yushan.keystore -storepass
123456
keytool -list -v -keystore e:\keytool\yushan.keystore -storepass 123456
显示:
Keystore 类型: JKS
Keystore 提供者: SUN
您的 keystore 包含 2 输入
别名名称: yushan
创建日期: 2009-7-29
项类型: PrivateKeyEntry
认证链长度: 1
认证 [1]:
所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
序列号:4a6f29ed
有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
证书指纹:
MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
签名算法名称:SHA1withRSA
版本: 3
别名名称: shuany
创建日期: 2009-7-29
输入类型: trustedCertEntry
所有者:CN=shuany, OU=xx, O=xx, L=xx, ST=xx, C=xx
签发人:CN=shuany, OU=xx, O=xx, L=xx, ST=xx, C=xx
序列号:4a6f2cd9
有效期: Wed Jul 29 00:52:41 CST 2009 至Thu Jul 29 00:52:41 CST 2010
证书指纹:
MD5:15:03:57:9B:14:BD:C5:50:21:15:47:1E:29:87:A4:E6
SHA1:C1:4F:8B:CD:5E:C2:94:77:B7:42:29:35:5C:BB:BB:2E:9E:F0:89:F5
签名算法名称:SHA1withRSA
版本: 3
6、证书条目的删除:
keytool -delete -alias shuany -keystore yushan.keystore -storepass 123456
7、证书条目口令的修改:
keytool -keypasswd -alias yushan -keypass yushan -new 123456 -keystore e:\yushan.keystore -storepass 123456
8、keystore口令的修改:
keytool -storepasswd -keystore e:\yushan.keystore -storepass 123456 -new yushan
9、修改keystore中别名为yushan的信息
keytool -selfcert -alias yushan -keypass yushan -keystore e:\yushan.keystore -storepass 123456 -dname “cn=yushan,ou=yushan,o=yushan,c=us”
jarsigner工具简介
jarsigner工具主要有以下两个作用:
a.对JAR文件签名 jarsigner [ options ] jarfile alias
b.校验签名以及签名JAR文件的完整性 jarsigner -verify [ options ] jarfile
JAR文件可以同时包含多个package的类文件,图片,声音以及数字数据,一边更快更方便的发布。jar工具用来创建JAR文件,从技术角度来说,任何zip文件都可以被看作是JAR文件,虽然使用jar创建的JAR文件包含META-INF/MANIFEST.MF文件。
数字签名是从一个实体(人、公司等)的某些数据(正被“签名”的数据)和私钥计算出来的位串。与手写的签名一样,数字签名有很多有用的特性:
1.真实性2.不可能被伪造(假设私钥没有泄露)3.已签名的数据不能被修改;如果被修改了,签名将不再被校验为可信的。
为了给文件生成实体的签名,该实体首先必须与一对公/私钥相关联,以及一个或多个鉴别其公钥的证书。证书是来自一个实体的已被数字签署的声明,表示某个其它实体的公钥有特定值。
使用keytool 创建和管理密钥仓库(keystore)后,jarsigner 使用来自密钥仓库(keystore)的密钥和证书信息为 JAR 文件生成数字签名。
语法参数:
jarsigner -verify [选项] jar 文件
[-keystore ] 密钥库位置
[-storepass <口令>] 用于密钥库完整性的口令
[-storetype <类型>] 密钥库类型
[-keypass <口令>] 专用密钥的口令(如果不同)
[-sigfile <文件>] .SF/.DSA 文件的名称
[-signedjar <文件>] 已签名的 JAR 文件的名称
[-digestalg <算法>] 摘要算法的名称
[-sigalg <算法>] 签名算法的名称
[-verify] 验证已签名的 JAR 文件
[-verbose] 签名/验证时输出详细信息
[-certs] 输出详细信息和验证时显示证书
[-tsa ] 时间戳机构的位置
[-tsacert <别名>] 时间戳机构的公共密钥证书
[-altsigner <类>] 替代的签名机制的类名
[-altsignerpath <路径列表>] 替代的签名机制的位置
[-internalsf] 在签名块内包含 .SF 文件
[-sectionsonly] 不计算整个清单的散列
[-protected] 密钥库已保护验证路径
[-providerName <名称>] 提供者名称
[-providerClass <类> 加密服务提供者的名称
[-providerArg <参数>]] … 主类文件和构造函数参数
使用demo:
C:>jar cf pg.jar org*.*
C:>jarsigner -storetype jks -keystore c:\mykeystore.keystore -digestalg MD5 -sigalg MD5withRSA -signedjar pgsigned.jar pg.jar myalias
C:>jarsigner -verify pgsigned.jar
修改MYALIAS.SF文件的内容,然后再校验:
C:>jarsigner -verify pgsigned.jar
附:Java KeyStore的类型
JKS和JCEKS是Java密钥库(KeyStore)的两种比较常见类型(我所知道的共有5种,JKS, JCEKS, PKCS12, BKS,UBER)。
JKS的Provider是SUN,在每个版本的JDK中都有,JCEKS的Provider是SUNJCE,1.4后我们都能够直接使用它。
JCEKS在安全级别上要比JKS强,使用的Provider是JCEKS(推荐),尤其在保护KeyStore中的私钥上(使用TripleDes)。
PKCS#12是公钥加密标准,它规定了可包含所有私钥、公钥和证书。其以二进制格式存储,也称为 PFX 文件,在windows中可以直接导入到密钥区,注意,PKCS#12的密钥库保护密码同时也用于保护Key。
BKS 来自BouncyCastle Provider,它使用的也是TripleDES来保护密钥库中的Key,它能够防止证书库被不小心修改(Keystore的keyentry改掉1个 bit都会产生错误),BKS能够跟JKS互操作,读者可以用Keytool去TryTry。
UBER比较特别,当密码是通过命令行提供的时候,它只能跟keytool交互。整个keystore是通过PBE/SHA1/Twofish加密,因此keystore能够防止被误改、察看以及校验。以前,Sun JDK(提供者为SUN)允许你在不提供密码的情况下直接加载一个Keystore,类似cacerts,UBER不允许这种情况。
java jar包签名
JAR文件可以用 jarsigner工具或者直接通过 java.securityAPI 签名。签名后的JAR 本身的文件
文件与原来JAR本身的 文件完全相同,只是更新了它的 manifest文件,并在 META-INF 目录中
增加了两个文件,一个签名文件和一个签名块文件。
JAR文件可以用一个存储在 Keystore数据库中的证书进行签名的。存储在 keystore 中的证书
有密码保护,必须向 jarsigner工具提供这个密码才能对 JAR 文件签名。
Jar文件使用jarsigner签名以后,在META-INF文件夹下会多出两个文件:XXX.SF文件与XXX.YYY
文件。XXX应该与你签名时使用密钥的别名一致.而XXX.YYY的扩展名,根据数字签名的类型RSA
、DSA 或者 PGP 以及用于签名 JAR 的证书类型而有不同的扩展名。XXX.SF文件的格式类似于
manifest 文件(一组 RFC-822 头)。XXX.SF文件主要包括的对JAR本身文件及Manifest文件的签
名码(加密后的散列码)。奇怪的是进行签名后Manifest文件中也有针对JAR本身文件的签名码,
且和XXX.SF文件中的不一样。为什么会有两个呢?不解。在XXX.YYY文件(比如TEST.RSA)中
,除了签名私钥所对应的公钥外,还包含了签名者的一些信息。
在验证一个签名的 JAR 时,将签名文件的摘要值与对 JAR 文件中的相应项计算的摘要值进行
比较。
MANIFEST.MF文件:
Manifest-Version: 1.0
Created-By: 1.6.0_11 (Sun Microsystems Inc.)
Main-Class: Hello
Name: Util.class
SHA1-Digest: UQkSPocH+hEH4W8d4/E7ifo7Y2A=
Name: Hello.class
SHA1-Digest: HQJfMvXm5JhrX2afxITiicvzDdQ=
TEST.SF文件
Signature-Version: 1.0
SHA1-Digest-Manifest-Main-Attributes: +yrcddwVI7QFdviahKRNKIHg2Zc=
Created-By: 1.6.0_11 (Sun Microsystems Inc.)
SHA1-Digest-Manifest: dCxOoUzPsGXrxxYH5PRNx47Er7M=
Name: Util.class
SHA1-Digest: 5g4n0t4ScMDowIF10vD7pMtcM1g=
Name: Hello.class
SHA1-Digest: OvGpI1SCZ7Py8O0rjqUUsZT6H/Q=
Keystore
要签名一个 JAR 文件,必须首先有一个私钥。私钥及其相关的公钥证书存储在名为keystores
的、有密码保护的数据库中。JDK 包含创建和修改 keystores 的工具。keystore 中的每一个密
钥都可以用一个别名标识,它通常是拥有这个密钥的签名者的名字。
所有 keystore 项 ( 密钥和信任的证书项 ) 都是用唯一别名访问的。别名是在用 keytool -
genkey 命令生成密钥对 ( 公钥和私钥 ) 并在 keystore 中添加项时指定的。之后的 keytool命
令必须使用同样的别名引用这一项。
例如,要生成一个别名为“robin”生成一个新的公钥 / 私钥对并将公钥包装到自签名的证书中,
要使用下述命令:
例1
keytool -genkey -alias robin -keystore robin.keystore -storepass GL2009 -keypass gl2009 -
validity 100 -keyalg RSA -keysize 1024 -sigalgMD5withRSA
这个命令序列用于生成一个名为的公钥/私钥对名字为robin,并把它添加到文件名为
robin.keystore的keystore文件中,如果该文件还不存在,则创建它。其中文件名密码为
GL2009,要添加的公钥/私钥对的私钥密码为gl2009,文件有效期为100天,公钥/私钥对名字
为robin,公钥/私钥对采用RSA算法,公钥/私钥的长度为1024,签名时采用MD5withRSA算法
(用MD5算法进行散列,用RSA算法对其散列码进行加密)
然后按照提示输入一些信息,如下:
What is your first and last name?
[Unknown]: hubing
What is the name of your organizational unit?
[Unknown]: GL
What is the name of your organization?
[Unknown]: gameloft
What is the name of your City or Locality?
[Unknown]: chengdu
What is the name of your State or Province?
[Unknown]: shichuan
What is the two-letter country code for this unit?
[Unknown]: cn
Is CN=hubing, OU=GL, O=gameloft, L=chengdu, ST=shichuan, C=cn correct?
[no]: yes
jarsigner 工具
通过jarsigner工具,可以使用 keystore 生成或者验证 JAR 文件的数字签名。
假设像例1那样创建了keystore文件robin.keystore,可以用下面的命令签名一个 JAR 文件:
例2
jarsigner -keystore robin.keystore -storepass GL2009 -keypass gl2009 Hello.jar robin
这个命令用密码“GL2009”从名为“robin.keystore”的keystore文件中提出名字为“robin”、密码为
“gl2009”的公钥/私钥对,并对Hello.jar 文件按照keystore文件robin.keystore中的约定进行数字
签名。
例3
jarsigner -keystore robin.keystore -storepass GL2009 -keypass gl2009 -signedjar
Hello_signed.jar Hello.jar robin
这个命令用密码“GL2009”从名为“robin.keystore”的keystore文件中提出名字为“robin”、密码为
“gl2009”的公钥/私钥对,并对Hello.jar 文件按照keystore文件robin.keystore中的约定进行数字
签名,签名的输出文件为Hello_signed.jar。
jarsigner工具还可以验证一个签名的 JAR 文件,很简单,只需执行以下命令:
jarsigner -verify Hello.jar
如果签名的 JAR 文件没有被篡改过,那么 jarsigner工具就会告诉您 JAR 通过验证了。否则,
它会抛出一个 SecurityException, 表明哪些文件没有通过验证。还可以用 java.util.jar和
java.securityAPI 以编程方式签名 JAR
java jar 包文件签名步骤
java 的jar包签名.可以防止别人篡改被签名的jar包.
步骤:
(1)将java程序打包
jar cvf test.jar test.class
(2)生成名为caoyong.store的密钥库,别名为caoyong
keytool -genkey -keystore caoyong.store -alias mcni
密码:123456 (根据需要自己输入) 以下根据需要输入,最后确认:y
(3)导出caoyong.cer数字证书
keytool -export -keystore caoyong.store -alias mcni -file caoyong.cer
密码:123456 (根据需要自己输入)
(4)对test.jar文件进行签名
jarsigner -keystore caoyong.store test.jar caoyong
密码:123456 (根据需要自己输入)
另外
一条警告说该证名书只能使用6个月。为了能使应用程序不受时间的限制,keytool命令提供了
一个参数validity,利用它可以指定签名有效日。例如:
keytool -genkey -keystore caoyong.store -alias caoyong -validity 55555
动态加载jar包
代码如下:
package my.jar;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Method;
import java.MalformedURLException;
import java.URL;
import java.URLClassLoader;
public class JarLoader
{
private URLClassLoader urlClassLoader;
public JarLoader(URLClassLoader urlClassLoader)
{
this.urlClassLoader = urlClassLoader;
}
public void loadJar(URL url) throws Exception
{
Method addURL = URLClassLoader.class.getDeclaredMethod(“addURL”,
URL.class);
addURL.setAccessible(true);
addURL.invoke(urlClassLoader, url);
}
private static void loadjar(JarLoader jarLoader, String path) throws
MalformedURLException, Exception
{
File libdir = new File(path);
if (libdir != null && libdir.isDirectory())
{
File[] listFiles = libdir.listFiles(new FileFilter()
{
public boolean accept(File file)
{
return file.exists() && file.isFile() &&
file.getName().endsWith(".jar");
}
});
for (File file : listFiles)
{
jarLoader.loadJar(file.toURI().toURL());
}
} else
{
System.out.println("[Console Message] Directory [" + path + "]
does not exsit, please check it");
System.exit(0);
}
}
public static void main(String[] args) throws MalformedURLException, Exception
{
JarLoader jarLoader = new JarLoader((URLClassLoader)
ClassLoader.getSystemClassLoader());
loadjar(jarLoader, System.getProperty(“user.dir”) + “/lib”);
}
}
dsa加密
package my.security;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
public class Testdsa
{
public static void main(String[] args) throws java.security.NoSuchAlgorithmException, java.lang.Exception
{
Testdsa my = new Testdsa();
my.run();
}
public void run()
{
// 数字签名生成密钥
// 第一步生成密钥对,如果已经生成过,本过程就可以跳过,对用户来讲myprikey.dat要保存在本地
// 而mypubkey.dat给发布给其它用户
if ((new java.io.File(“myprikey.dat”)).exists() == false)
{
if (generatekey() == false)
{
System.out.println(“生成密钥对败”);
return;
}
;
}
// 第二步,此用户
// 从文件中读入私钥,对一个字符串进行签名后保存在一个文件(myinfo.dat)中
// 并且再把myinfo.dat发送出去
// 为了方便数字签名也放进了myifno.dat文件中,当然也可分别发送
try
{
java.io.ObjectInputStream in = new java.io.ObjectInputStream(new java.io.FileInputStream(“myprikey.dat”));
PrivateKey myprikey = (PrivateKey) in.readObject();
in.close();
// java.security.spec.X509EncodedKeySpec pubX509=new
// java.security.spec.X509EncodedKeySpec(bX509);
// java.security.spec.X509EncodedKeySpec
// pubkeyEncode=java.security.spec.X509EncodedKeySpec
String myinfo = “这是我的信息”; // 要签名的信息
// 用私钥对信息生成数字签名
java.security.Signature signet = java.security.Signature.getInstance(“DSA”);
signet.initSign(myprikey);
signet.update(myinfo.getBytes());
byte[] signed = signet.sign(); // 对信息的数字签名
System.out.println(“signed(签名内容)=” + byte2hex(signed));
// 把信息和数字签名保存在一个文件中
java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(new java.io.FileOutputStream(“myinfo.dat”));
out.writeObject(myinfo);
out.writeObject(signed);
out.close();
System.out.println(“签名并生成文件成功”);
} catch (java.lang.Exception e)
{
e.printStackTrace();
System.out.println(“签名并生成文件失败”);
}
;
// 第三步
// 其他人通过公共方式得到此户的公钥和文件
// 其他人用此户的公钥,对文件进行检查,如果成功说明是此用户发布的信息.
//
try
{
java.io.ObjectInputStream in = new java.io.ObjectInputStream(new java.io.FileInputStream(“mypubkey.dat”));
PublicKey pubkey = (PublicKey) in.readObject();
in.close();
System.out.println(pubkey.getFormat());
in = new java.io.ObjectInputStream(new java.io.FileInputStream(“myinfo.dat”));
String info = (String) in.readObject();
byte[] signed = (byte[]) in.readObject();
in.close();
java.security.Signature signetcheck = java.security.Signature.getInstance(“DSA”);
signetcheck.initVerify(pubkey);
signetcheck.update(info.getBytes());
if (signetcheck.verify(signed))
{
System.out.println(“info=” + info);
System.out.println(“签名正常”);
} else
System.out.println(“非签名正常”);
} catch (java.lang.Exception e)
{
e.printStackTrace();
}
}
// 生成一对文件myprikey.dat和mypubkey.dat—私钥和公钥,
// 公钥要用户发送(文件,网络等方法)给其它用户,私钥保存在本地
public boolean generatekey()
{
try
{
java.security.KeyPairGenerator keygen = java.security.KeyPairGenerator.getInstance(“DSA”);
// SecureRandom secrand=new SecureRandom();
// secrand.setSeed(“tttt”.getBytes()); //初始化随机产生器
// keygen.initialize(576,secrand); //初始化密钥生成器
keygen.initialize(512);
KeyPair keys = keygen.genKeyPair();
// KeyPair keys=keygen.generateKeyPair(); //生成密钥组
PublicKey pubkey = keys.getPublic();
PrivateKey prikey = keys.getPrivate();
java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(
new java.io.FileOutputStream(“myprikey.dat”));
out.writeObject(prikey);
out.close();
System.out.println(“写入对象 prikeys ok”);
out = new java.io.ObjectOutputStream(new java.io.FileOutputStream(“mypubkey.dat”));
out.writeObject(pubkey);
out.close();
System.out.println(“写入对象 pubkeys ok”);
System.out.println(“生成密钥对成功”);
return true;
} catch (java.lang.Exception e)
{
e.printStackTrace();
System.out.println(“生成密钥对失败”);
return false;
}
}
public String byte2hex(byte[] b)
{
String hs = “”;
String stmp = “”;
for (int n = 0; n < b.length; n++)
{
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1)
hs = hs + “0” + stmp;
else
hs = hs + stmp;
if (n < b.length - 1)
hs = hs + “:”;
}
return hs.toUpperCase();
}
}
实践对jar包的代码签名完整示例
第一步,首先配置jdk的环境变量,如果你的电脑已经配置了,那直接跳过这一步
path=%JAVA_HOME%/bin
JAVA_HOME=C:/Java/jdk1.6.0_01
CLASSPATH=.;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar
配置要这几个jdk的环境参数,好了,配完了,试着在cmd里跑一下java,javac,看看命令是否生效,如果配置成功执行第二步。
第二步,来写几个简单的类,简单的才是大家的。你完全可以直接copy我的代码,部分看不懂,忽略它,做实验而已,对那个jar文件签名不是签,这个例子的代码逻辑是后面才用到的,不用读第一个类Doer
package com.yfq.test;
public abstract interface Doer {
void doYourThing();
}
第二个类
package com.yfq.test.friend;
import java.security.AccessController;
import java.security.PrivilegedAction;
import com.yfq.test.Doer;
public class Friend implements Doer{
private Doer next;
private boolean direct;
public Friend(Doer next,boolean direct){this.next=next;this.direct=direct;
}@Override
public void doYourThing() {System.out.println("Im a Friend");if (direct) {next.doYourThing();} else {AccessController.doPrivileged(new PrivilegedAction() {@Overridepublic Object run() {next.doYourThing();return null;}});}
}
}
第三个类
package com.yfq.test.stranger;
import java.security.AccessController;
import java.security.PrivilegedAction;
import com.yfq.test.Doer;
public class Stranger implements Doer {
private Doer next;
private boolean direct;public Stranger(Doer next, boolean direct) {this.next = next;this.direct = direct;
}@Override
public void doYourThing() {System.out.println("Im a Stranger");if (direct) {next.doYourThing();} else {AccessController.doPrivileged(new PrivilegedAction() {@Overridepublic Object run() {next.doYourThing();return null;}});}
}
}
好了,编译一下,用强大的ecplise来编译,项目-右键-Build Project(工具是拿来用的,不要浪费这些强大的功能!)
第三步,打jar包,用ecplise就可以了就有导出jar包的功能,我还是那句老话,有工具不用,不是牛,是蠢。步骤一,项目-右键-Export-java-JAR file-next步骤二,展开目录清单-分别对com.yfq.tes.friend和com.yfq.test.stranger打包(friend.jar,stranger.jar),放到哪里就随便你了,只要你记得就好,我这里假设是放在d盘的根目录下第四步,用java的keytool生成密钥对,用java的jarsigner做签名(记得笔记七我们说过对hash摘要的加密是非对称加密的吗?这里就需要两把不同的钥匙啦),一步步跟我来。步骤一,cmd窗口,进入到存放friend.jar和stranger.jar的目录下,假设我的jar文件放在d盘下,直接输入盘符d:就可以了。步骤二,在cmd窗口中输入keytool -genkey -keystore ijvmkeys.keystore -keyalg RSA -validity 10000 -alias friend.keystore生成第一个密钥对,这个密钥对的别名是 friend.keystore,采用的加密算法为RSA,密钥对的过期时间是10000天,密钥对存储的文件名ijvmkeys.keystore,而查看ijvmkeys.keystore的密码和friend.keystore密钥对的查看密码我们设置为123456
注意:这里在设置名字和姓氏的时候要特别的注意,不要随便的乱写,否则将导致后面的签名失败,一般我们写完网络域名的形式如:www.keycoding这样。
步骤三,在cmd窗口输入,keytool -genkey -keystore ijvmkeys.keystore -keyalg RSA -validity 10000 -alias stranger.keystore按照步骤2的截图,一步一步输入吧,这个步骤是生成别名为stranger.keystore的密钥对。好了密钥对生成结束,看看你的jar文件目录下有没有多出一个文件ijvmkeys.keystore,是滴,这里生成了一个用于存放密钥对的文件。步骤四,查看生成的密钥文件,在cmd窗口输入keytool -list -v -keystore ijvmkeys.keystore步骤五,对jar进行摘要并对hash摘要进行加密生成签名,放置到jar文件结构的尾部在cmd窗口输入 jarsigner -verbose -keystore ijvmkeys.keystore friend.jar friend.keystorejarsigner -verbose -keystore ijvmkeys.keystore stranger.jar stranger.keystore步骤六,右键frend.jar和stranger.jar用rar解压器看看它们在META-INF目录下是否生成了两个附加的文件
而关于这两个附加文件的用处,我这里也简单的说明一下,首先从名字上来讲他是八个字符,他默认取我们的密钥对的名字的前八个字符做名字而因为我们的密钥对名字是friend.keystore所以生成的名字将点替换为下滑线。如果你想要自己指定名字在keytool后面加上-sigFile XXXX这个参数
另外FRIEND_K.SF这个文件我们简单的展开
Signature-Version: 1.0
SHA1-Digest-Manifest-Main-Attributes: QHukAYw2MtCop4vlrhjJDDro1fQ=
Created-By: 1.6.0_12 (Sun Microsystems Inc.)
SHA1-Digest-Manifest: YePdyFc1+FVdY1PIcj6WVuTJAFE=
Name: com/yfq/test/friend/Friend$1.class
SHA1-Digest: mj79V3+YKsRAzxGHpyFGhOdY4dU=
Name: com/yfq/test/friend/Friend.class
SHA1-Digest: tqPfF2lz4Ol8eJ3tQ2IBvvtduj0=
它包含了签名的版本,签名者,还有被签名的类名,以及这个类的hash摘要,第四行是整个本文件的摘要,用于jar包的校验
FRIEND_K.DSA 文件,SF 文件被签名且签名被放入 .DSA 文件。.DSA 文件还包含来自密钥仓库的证书或证书链(被编码到其中),它们鉴别与用于签名的私钥对应的公钥。
步骤七,校验jar包在cmd中输入jarsigner -verify friend.jar和jarsigner -verify stranger.jar到这里jar签名的实验已经完毕!!!!!
查看上面步骤四截图,我们来验证一下在笔记七里说过的话。
1.我们说过hash摘要是一个128的值,对不对呢,看证书指纹那一行,md5:…
你数一数总共有几个十六进制数,32个,一个十六进制数用4个位可以表示完,那么总共是几位,32*4=128,但是后面还有一个sha1的,怎么回事他貌似不止128位,是滴,散列函数多种多样,到底用那个散列函数,md5还是sha1这个就看你喜欢,而要使用哪个散列函数是可以指定的,keytool的参数-keyalg “DSA”,这个参数就是用来指定用什么散列算法的,默认的就是DSA,普通的128位散列数已经是安全的了。
2.在 笔记七中,记不记得最下面那个图,有一个认证机构会对解密签名(被加密的hash摘要)的公钥做认证(也就是加密公钥),并发布证书,我们这里没有认证机构,你有没有这个疑问?
keytool程序在生成密钥时,总是会生成一个自签名证书(自签名是指:如果附近没有认证机构,可以用私钥对公钥签名,生成一个自签名证书)
总结:
通过本章我们学习对一个jar进行签名,一个jar可以同时被多个机构或作者签名,看起来实验很复杂其实很简单。如果你还想了解更多关于jar包签名的知识,本人在这里推荐一篇文章(),本人自己在学习jar包签名的时候也从这篇文章中收益匪浅,希望它对你有帮助。
java keytool 工具
转自
Keytool 是一个JAVA环境下的安全钥匙与证书的管理工具,Keytool将密钥(key)和证书(certificates)存在一个称为keystore 的文件(受密码保护)中。
在keystore里,包含两种数据:
密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密)
可信任的证书实体(trusted certificate entries)——只包含公钥
jarsigner是JDK中包含的用于JAR文件签名和验证的工具。为Java档案文件(JAR)生成签名,以及对已签名的jar文件的进行校验。
JDK中ketyTool常用命令:
-genkey 在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书,(默认情况下,keystore会存在用户系统默认目录,如:win系统,会生成在C:\Documents and Settings\用户名\文件名为“.keystore”)
-alias 产生别名(default:mykey,每个keystore都关联这一个独一无二的alias,不区分大小写)
-keystore 指定密钥库的名称(产生的各类信息将不在.keystore文件中)
-keyalg 指定密钥的算法 (如RSA、DSA,default:DSA)
-validity 指定创建的证书有效期多少天(default:90)
-keysize 指定密钥长度(default:1024,范围:512 ~ 1024)
-storepass 指定密钥库的密码(获取keystore信息所需的密码)
-keypass 指定别名条目的密码(私钥的密码)
-dname 指定证书拥有者信息
例如: “CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=州或省份名称,C=单位的两字母国家代码”
-list 显示密钥库中的证书信息
keytool -list -v -keystore 指定keystore -storepass 密码 -v 显示密钥库中的证书详细信息
-export 将别名指定的证书导出到文件
keytool -export -alias 需要导出的别名 -keystore 指定keystore -file 指定导出的证书位置及证书名称 -storepass 密码
-delete 删除密钥库中某条目
keytool -delete -alias 指定需删除的keystore别名 -keystore 指定keystore -storepass 密码
-printcert 查看导出的证书信息
keytool -printcert -file yushan.crt
-keypasswd 修改密钥库中指定条目口令
keytool -keypasswd -alias 需修改的别名 -keypass 旧密码 -new 新密码 -storepass keystore密码 -keystore sage
-storepasswd 修改keystore口令
keytool -storepasswd -keystore e:\yushan.keystore(需修改口令的keystore) -storepass 123456(原始密码) -new yushan(新密码)
-import 将已签名数字证书导入密钥库
keytool -import -alias 别名 -keystore指定keystore -file需导入的证书
keytool 使用demo(注:.keystore可以换成.jks后缀):
1、keystore的生成:
分阶段生成:
keytool -genkey -alias yushan(别名) -keypass yushan(别名密码) -keyalg RSA(算法) -keysize 1024(密钥长度) -validity 365(有效期,天单位) -keystore
e:\yushan.keystore(指定生成证书的位置和证书名称) -storepass 123456(获取keystore信息的密码);
回车输入相关信息即可;
一次性生成:
keytool -genkey -alias yushan -keypass yushan -keyalg RSA -keysize 1024 -validity 365 -keystore e:\yushan.keystore -storepass 123456 -dname “CN=(名字与
姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称), ST=(州或省份名称), C=(单位的两字母国家代码)”;
(中英文即可)
2、keystore信息的查看:
keytool -list -v -keystore e:\keytool\yushan.keystore -storepass 123456
显示内容:
Keystore 类型: JKS
Keystore 提供者: SUN
您的 keystore 包含 1 输入
别名名称: yushan
创建日期: 2009-7-29
项类型: PrivateKeyEntry
认证链长度: 1
认证 [1]:
所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
序列号:4a6f29ed
有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
证书指纹:
MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
签名算法名称:SHA1withRSA
版本: 3
缺省情况下,-list 命令打印证书的 MD5 指纹。而如果指定了 -v 选项,将以可读格式打印证书,如果指定了 -rfc 选项,将以可打印的编码格式输出证书。
keytool -list -rfc -keystore e:\yushan.keystore -storepass 123456
显示:
Keystore 类型: JKS
Keystore 提供者: SUN
您的 keystore 包含 1 输入
别名名称: yushan
创建日期: 2009-7-29
项类型: PrivateKeyEntry
认证链长度: 1
认证 [1]:
-----BEGIN CERTIFICATE-----
MIICSzCCAbSgAwIBAgIESm8p7TANBgkqhkiG9w0BAQUFADBqMQ8wDQYDVQQGDAbkuK3lm70xDzAN
BgNVBAgMBua5luWNlzEPMA0GA1UEBwwG5rmY5r2tMREwDwYDVQQKDAh4eOWNj+S8mjERMA8GA1UE
CwwIeHjlhazlj7gxDzANBgNVBAMTBnl1c2hhbjAeFw0wOTA3MjgxNjQwMTNaFw0xMDA3MjgxNjQw
MTNaMGoxDzANBgNVBAYMBuS4reWbvTEPMA0GA1UECAwG5rmW5Y2XMQ8wDQYDVQQHDAbmuZjmva0x
ETAPBgNVBAoMCHh45Y2P5LyaMREwDwYDVQQLDAh4eOWFrOWPuDEPMA0GA1UEAxMGeXVzaGFuMIGf
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJoru1RQczRzTnBWxefVNspQBykS220rS8Y/oX3mZa
hjL4wLfOURzUuxxuVQR2jx7QI+XKME+DHQj9r6aAcLBCi/T1jwF8mVYxtpRuTzE/6KEZdhowEe70
liWLVE+hytLBHZ03Zhwcd6q5HUMu27du3MPQvqiwzTY7MrwIvQQ8iQIDAQABMA0GCSqGSIb3DQEB
BQUAA4GBAGoQQ1/FnTfkpQh+Ni6h3fZdn3sR8ZzDMbOAIYVLAhBb85XDJ8QZTarHbZMJcIdHxAl1
i08ct3E8U87V9t8GZFWVC4BFg/+zeFEv76SFpVE56iX7P1jpsu78z0m69hHlds77VJTdyfMSvtXv
sYHP3fxfzx9WyhipBwd8VPK/NgEP
-----END CERTIFICATE-----
3、证书的导出:
keytool -export -alias yushan -keystore e:\yushan.keystore -file e:\yushan.crt -storepass 123456
4、查看导出的证书信息
keytool -printcert -file yushan.crt
显示:(在windows下可以双击yushan.crt查看)
所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
序列号:4a6f29ed
有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
证书指纹:
MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
签名算法名称:SHA1withRSA
版本: 3
5、证书的导入:
准备一个导入的证书:
keytool -genkey -alias shuany -keypass shuany -keyalg RSA -keysize 1024 -validity 365 -keystore e:\shuany.keystore -storepass 123456 -dname “CN=shuany,
OU=xx, O=xx, L=xx, ST=xx, C=xx”;
keytool -export -alias shuany -keystore e:\shuany.keystore -file e:\shuany.crt -storepass 123456
现在将shuany.crt 加入到yushan.keystore中:
keytool -import -alias shuany(指定导入证书的别名,如果不指定默认为mykey,别名唯一,否则导入出错) -file e:\shuany.crt -keystore e:\yushan.keystore -storepass
123456
keytool -list -v -keystore e:\keytool\yushan.keystore -storepass 123456
显示:
Keystore 类型: JKS
Keystore 提供者: SUN
您的 keystore 包含 2 输入
别名名称: yushan
创建日期: 2009-7-29
项类型: PrivateKeyEntry
认证链长度: 1
认证 [1]:
所有者:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
签发人:CN=yushan, OU=xx公司, O=xx协会, L=湘潭, ST=湖南, C=中国
序列号:4a6f29ed
有效期: Wed Jul 29 00:40:13 CST 2009 至Thu Jul 29 00:40:13 CST 2010
证书指纹:
MD5:A3:D7:D9:74:C3:50:7D:10:C9:C2:47:B0:33:90:45:C3
SHA1:2B:FC:9E:3A:DF:C6:C4:FB:87:B8:A0:C6:99:43:E9:4C:4A:E1:18:E8
签名算法名称:SHA1withRSA
版本: 3
别名名称: shuany
创建日期: 2009-7-29
输入类型: trustedCertEntry
所有者:CN=shuany, OU=xx, O=xx, L=xx, ST=xx, C=xx
签发人:CN=shuany, OU=xx, O=xx, L=xx, ST=xx, C=xx
序列号:4a6f2cd9
有效期: Wed Jul 29 00:52:41 CST 2009 至Thu Jul 29 00:52:41 CST 2010
证书指纹:
MD5:15:03:57:9B:14:BD:C5:50:21:15:47:1E:29:87:A4:E6
SHA1:C1:4F:8B:CD:5E:C2:94:77:B7:42:29:35:5C:BB:BB:2E:9E:F0:89:F5
签名算法名称:SHA1withRSA
版本: 3
6、证书条目的删除:
keytool -delete -alias shuany -keystore yushan.keystore -storepass 123456
7、证书条目口令的修改:
keytool -keypasswd -alias yushan -keypass yushan -new 123456 -keystore e:\yushan.keystore -storepass 123456
8、keystore口令的修改:
keytool -storepasswd -keystore e:\yushan.keystore -storepass 123456 -new yushan
9、修改keystore中别名为yushan的信息
keytool -selfcert -alias yushan -keypass yushan -keystore e:\yushan.keystore -storepass 123456 -dname “cn=yushan,ou=yushan,o=yushan,c=us”
jarsigner工具简介
jarsigner工具主要有以下两个作用:
a.对JAR文件签名 jarsigner [ options ] jarfile alias
b.校验签名以及签名JAR文件的完整性 jarsigner -verify [ options ] jarfile
JAR文件可以同时包含多个package的类文件,图片,声音以及数字数据,一边更快更方便的发布。jar工具用来创建JAR文件,从技术角度来说,任何zip文件都可以被看作是JAR文件,虽然使用jar创建的JAR文件包含META-INF/MANIFEST.MF文件。
数字签名是从一个实体(人、公司等)的某些数据(正被“签名”的数据)和私钥计算出来的位串。与手写的签名一样,数字签名有很多有用的特性:
1.真实性2.不可能被伪造(假设私钥没有泄露)3.已签名的数据不能被修改;如果被修改了,签名将不再被校验为可信的。
为了给文件生成实体的签名,该实体首先必须与一对公/私钥相关联,以及一个或多个鉴别其公钥的证书。证书是来自一个实体的已被数字签署的声明,表示某个其它实体的公钥有特定值。
使用keytool 创建和管理密钥仓库(keystore)后,jarsigner 使用来自密钥仓库(keystore)的密钥和证书信息为 JAR 文件生成数字签名。
语法参数:
jarsigner -verify [选项] jar 文件
[-keystore ] 密钥库位置
[-storepass <口令>] 用于密钥库完整性的口令
[-storetype <类型>] 密钥库类型
[-keypass <口令>] 专用密钥的口令(如果不同)
[-sigfile <文件>] .SF/.DSA 文件的名称
[-signedjar <文件>] 已签名的 JAR 文件的名称
[-digestalg <算法>] 摘要算法的名称
[-sigalg <算法>] 签名算法的名称
[-verify] 验证已签名的 JAR 文件
[-verbose] 签名/验证时输出详细信息
[-certs] 输出详细信息和验证时显示证书
[-tsa ] 时间戳机构的位置
[-tsacert <别名>] 时间戳机构的公共密钥证书
[-altsigner <类>] 替代的签名机制的类名
[-altsignerpath <路径列表>] 替代的签名机制的位置
[-internalsf] 在签名块内包含 .SF 文件
[-sectionsonly] 不计算整个清单的散列
[-protected] 密钥库已保护验证路径
[-providerName <名称>] 提供者名称
[-providerClass <类> 加密服务提供者的名称
[-providerArg <参数>]] … 主类文件和构造函数参数
使用demo:
C:>jar cf pg.jar org*.*
C:>jarsigner -storetype jks -keystore c:\mykeystore.keystore -digestalg MD5 -sigalg MD5withRSA -signedjar pgsigned.jar pg.jar myalias
C:>jarsigner -verify pgsigned.jar
修改MYALIAS.SF文件的内容,然后再校验:
C:>jarsigner -verify pgsigned.jar
附:Java KeyStore的类型
JKS和JCEKS是Java密钥库(KeyStore)的两种比较常见类型(我所知道的共有5种,JKS, JCEKS, PKCS12, BKS,UBER)。
JKS的Provider是SUN,在每个版本的JDK中都有,JCEKS的Provider是SUNJCE,1.4后我们都能够直接使用它。
JCEKS在安全级别上要比JKS强,使用的Provider是JCEKS(推荐),尤其在保护KeyStore中的私钥上(使用TripleDes)。
PKCS#12是公钥加密标准,它规定了可包含所有私钥、公钥和证书。其以二进制格式存储,也称为 PFX 文件,在windows中可以直接导入到密钥区,注意,PKCS#12的密钥库保护密码同时也用于保护Key。
BKS 来自BouncyCastle Provider,它使用的也是TripleDES来保护密钥库中的Key,它能够防止证书库被不小心修改(Keystore的keyentry改掉1个 bit都会产生错误),BKS能够跟JKS互操作,读者可以用Keytool去TryTry。
UBER比较特别,当密码是通过命令行提供的时候,它只能跟keytool交互。整个keystore是通过PBE/SHA1/Twofish加密,因此keystore能够防止被误改、察看以及校验。以前,Sun JDK(提供者为SUN)允许你在不提供密码的情况下直接加载一个Keystore,类似cacerts,UBER不允许这种情况。
本文标签: java jar包签名
版权声明:本文标题:java jar包签名 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/IT/1694659916a254655.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论