1、解密密钥只有解密人自己知道。它们分别称为公开密钥(Public key)和秘密密钥(Private key)。迄今为止的所有公钥密码体系中,RSA 系统是最著名、最多使用的一种。RSA 公开密钥密码系统是由 R.Rivest、A.Shamir 和 L.Adleman 俊教授于 1977 年提出的。RSA 的取名就是来自于这三位发明者的姓的第一个字母1.5. 数字签名所谓数字签名就是信息发送者用其私钥对从所传报文中提取出的特征数据(或称数字指纹)进行 RSA 算法操作,以保证发信人无法抵赖曾发过该信息(即不可抵赖性),同时也确保信息报文在经签名后末被篡改(即完整性)。当信息接收者收到报文后,就可
2、以用发送者的公钥对数字签名进行验证。在数字签名中有重要作用的数字指纹是通过一类特殊的散列函数(HASH 函数)生成的,对这些 HASH 函数的特殊要求是:接受的输入报文数据没有长度限制;对任何输入报文数据生成固定长度的摘要(数字指纹)输出从报文能方便地算出摘要;难以对指定的摘要生成一个报文,而由该报文反推算出该指定的摘要;DSA回页首第 2 章在 JAVA 中的实现2.1. 相关Diffie-Hellman 密钥一致协议和 DES 程序需要 JCE 工具库的支持 , 可以到 下载 JCE, 并进行安装。简易安装把 jce1.2.1lib 下的所有内容复制到 %java_home%libext
3、下 , 如果没有 ext 目录自行建立 , 再把 jce1_2_1.jar 和 sunjce_provider.jar 添加到 CLASSPATH 内 , 更详细说明请看相应用户手册2.2. 消息摘要 MD5 和 SHA 的使用使用方法 :首先用生成一个 MessageDigest 类 , 确定计算方法java.security.MessageDigest alga=java.security.MessageDigest.getInstance(SHA-1);添加要进行计算摘要的信息alga.update(myinfo.getBytes();计算出摘要byte digesta=alga.dig
4、est();发送给其他人你的信息和摘要其他人用相同的方法初始化 , 添加信息 , 最后进行比较摘要是否相同algb.isEqual(digesta,algb.digest()相关 AIPjava.security.MessageDigest 类static getInstance(String algorithm)返回一个 MessageDigest 对象 , 它实现指定的算法参数 : 算法名 , 如 SHA-1 或 MD5void update (byte input)void update (byte input)void update(byte input, int offset, in
5、t len)byte digest()完成计算 , 返回计算得到的摘要 ( 对于 MD5 是 16 位 ,SHA 是 20 位 )void reset()复位static boolean isEqual(byte digesta, byte digestb)比效两个摘要是否相同代码:import java.security.*; public class myDigest public static void main(String args) myDigest my=new myDigest(); my.testDigest(); public void testDigest() try S
6、tring myinfo=我的测试信息; /java.security.MessageDigest alg=java.security.MessageDigest.getInstance(MD5 java.security.MessageDigest alga=java.security.MessageDigest.getInstance( alga.update(myinfo.getBytes(); byte digesta=alga.digest(); System.out.println(本信息摘要是 :+byte2hex(digesta); / 通过某中方式传给其他人你的信息 (myi
7、nfo) 和摘要 (digesta) 对方可以判断是否更改或传输正常 java.security.MessageDigest algb=java.security.MessageDigest.getInstance( algb.update(myinfo.getBytes(); if (algb.isEqual(digesta,algb.digest() 信息检查正常 else 摘要不相同 catch (java.security.NoSuchAlgorithmException ex) 非法摘要算法 public String byte2hex(byte b) / 二行制转字符串 Strin
8、g hs= String stmp= for (int n=0;nb.length;n+) stmp=(java.lang.Integer.toHexString(bn & 0XFF); if (stmp.length()=1) hs=hs+0+stmp; else hs=hs+stmp; if (nb.length-1) hs=hs+: return hs.toUpperCase(); 2.3. 数字签名 DSA对于一个用户来讲首先要生成他的密钥对 , 并且分别保存 生成一个 KeyPairGenerator 实例java.security.KeyPairGenerator keygen=j
9、ava.security.KeyPairGenerator.getInstance(DSA/如果设定随机产生器就用如相代码初始化SecureRandom secrand=new SecureRandom();secrand.setSeed(tttt.getBytes(); / 初始化随机产生器keygen.initialize(512,secrand); / 初始化密钥生成器/否则keygen.initialize(512);/生成密钥公钥 pubkey 和私钥 prikey KeyPair keys=keygen.generateKeyPair(); / 生成密钥组PublicKey pub
10、key=keys.getPublic();PrivateKey prikey=keys.getPrivate();/分别保存在 myprikey.dat 和 mypubkey.dat 中 , 以便下次不在生成/( 生成密钥对的时间比较长java.io.ObjectOutputStream out=new java.io.ObjectOutputStream( new java.io.FileOutputStream(myprikey.dat);out.writeObject(prikey);out.close();out=new java.io.ObjectOutputStream(new j
11、ava.io.FileOutputStream(mypubkey.datout.writeObject(pubkey);用他私人密钥 (prikey) 对他所确认的信息 (info) 进行数字签名产生一个签名数组 从文件中读入私人密钥 (prikey)java.io.ObjectInputStream in=new java.io.ObjectInputStream( new java.io.FileInputStream(PrivateKey myprikey=(PrivateKey)in.readObject();in.close();初始一个 Signature 对象 , 并用私钥对信息
12、签名java.security.Signature signet=java.security.Signature.getInstance(signet.initSign(myprikey);signet.update(myinfo.getBytes();byte signed=signet.sign();把信息和签名保存在一个文件中 (myinfo.dat) myinfo.datout.writeObject(myinfo);out.writeObject(signed);把他的公钥的信息及签名发给其它用户其他用户用他的公共密钥 (pubkey) 和签名 (signed) 和信息 (info)
13、 进行验证是否由他签名的信息 读入公钥java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream( PublicKey pubkey=(PublicKey)in.readObject(); in.close();读入签名和信息in=new java.io.ObjectInputStream(new java.io.FileInputStream( String info=(String)in.readObject(); byte signed=(byte)in.readObject
14、();初始一个 Signature 对象 , 并用公钥和签名进行验证java.security.Signature signetcheck=java.security.Signature.getInstance( signetcheck.initVerify(pubkey); signetcheck.update(info.getBytes(); if (signetcheck.verify(signed) System.out.println(签名正常对于密钥的保存本文是用对象流的方式保存和传送的 , 也可可以用编码的方式保存 . 注意要import java.security.spec.*
15、 import java.security.*具休说明如下public key 是用 X.509 编码的 , 例码如下 : byte bobEncodedPubKey=mypublic.getEncoded(); / 生成编码 / 传送二进制编码 / 以下代码转换编码为相应 key 对象 X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey); KeyFactory keyFactory = KeyFactory.getInstance( PublicKey bobPubKey = keyFacto
16、ry.generatePublic(bobPubKeySpec);对于 Private key 是用 PKCS#8 编码 , 例码如下 :byte bPKCS=myprikey.getEncoded(); PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(bPKCS); KeyFactory keyf=KeyFactory.getInstance( PrivateKey otherprikey=keyf.generatePrivate(priPKCS8);常用 API java.security.KeyPairGenerator 密钥生成
17、器类public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException以指定的算法返回一个 KeyPairGenerator 对象参数 : algorithm 算法名 . 如 :,RSApublic void initialize(int keysize)以指定的长度初始化 KeyPairGenerator 对象 , 如果没有初始化系统以 1024 长度默认设置keysize 算法位长 . 其范围必须在 512 到 1024 之间,且必须为 64 的倍数public void
18、initialize(int keysize, SecureRandom random)以指定的长度初始化和随机发生器初始化 KeyPairGenerator 对象参数 :keysize 算法位长 . 其范围必须在 512 到 1024 之间,且必须为 64 的倍数random 一个随机位的来源 ( 对于 initialize(int keysize) 使用了默认随机器public abstract KeyPair generateKeyPair()产生新密钥对java.security.KeyPair 密钥对类public PrivateKey getPrivate()返回私钥public
19、PublicKey getPublic()返回公钥java.security.Signature 签名类public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException返回一个指定算法的 Signature 对象参数 algorithm 如 :public final void initSign(PrivateKey privateKey)throws InvalidKeyException用指定的私钥初始化参数 :privateKey 所进行签名时用的私钥public final voi
20、d update(byte data)throws SignatureExceptionpublic final void update(byte data)throws SignatureExceptionpublic final void update(byte data, int off, int len)throws SignatureException添加要签名的信息public final byte sign()throws SignatureException返回签名的数组 , 前提是 initSign 和 updatepublic final void initVerify(P
21、ublicKey publicKey)throws InvalidKeyException用指定的公钥初始化参数 :publicKey 验证时用的公钥public final boolean verify(byte signature)throws SignatureException验证签名是否有效 , 前提是已经 initVerify 初始化参数 : signature 签名数组 import java.security.*; import java.security.spec.*; public class testdsa public static void main(String a
22、rgs) 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().exists()=false) if (generatekey()=false) 生成密钥对败 retu
23、rn; ; / 第二步 , 此用户 / 从文件中读入私钥 , 对一个字符串进行签名后保存在一个文件 (myinfo.dat) 中 / 并且再把 myinfo.dat 发送出去 / 为了方便数字签名也放进了 myifno.dat 文件中 , 当然也可分别发送 java.io.ObjectInputStream in=new java.io.ObjectInputStream( PrivateKey myprikey=(PrivateKey)in.readObject(); / java.security.spec.X509EncodedKeySpec pubX509= / new java.se
24、curity.spec.X509EncodedKeySpec(bX509); /java.security.spec.X509EncodedKeySpec pubkeyEncode= / java.security.spec.X509EncodedKeySpec 这是我的信息 / 要签名的信息 / 用私钥对信息生成数字签名 java.security.Signature signet=java.security.Signature.getInstance( signet.initSign(myprikey); signet.update(myinfo.getBytes(); byte sign
25、ed=signet.sign(); / 对信息的数字签名signed( 签名内容 )=+byte2hex(signed); / 把信息和数字签名保存在一个文件中 java.io.ObjectOutputStream out=new java.io.ObjectOutputStream( out.writeObject(myinfo); out.writeObject(signed); out.close();签名并生成文件成功 catch (java.lang.Exception e) e.printStackTrace();签名并生成文件失败 / 第三步 / 其他人通过公共方式得到此户的公钥和文件 / 其他人用此户的公钥 , 对文件进行检查 , 如果成功说明是此用户发布的信息 . / System.out.println(pubkey.getFormat(); in=new java.io.ObjectInputStream(new java.io.
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2