java.security包小结

{{TOC}}

MessageDigest

MessageDigest类实现了消息摘要的算法,它继承与MessageDigestSpi类,是Java安全提供者体系结构中最为简单的一个引擎类。

1,MessageDigest类的实例。

public static MessageDigest getInstance(String algorithm)
public static MessageDigest getInstance(String algorithm, String provider)
public static MessageDigest getInstance(String algorithm,Provider provider)

目前Java8支持MD2、MD5、SHA-1(SHA)、SHA-224、SHA-256、SHA384、SHA-512七种信息摘要算法,算法名称不区分大小写。

2,实例化对象后,可以使用以下方法对此对象进行操作:

// 使用指定的字节更新摘要
public void update(byte input)
// 使用指定的字节数组更新摘要
public void update(byte[] input)
// 使用指定的字节数组,从指定的偏移量开始更新摘要
public void update(byte[] input, int offset, int len)
// 使用指定的字节缓冲区更新摘要
public void update(ByteBuffer input)

// 在完成摘要更新后,最终完成摘要计算,返回信息摘要字节数组
public byte[] digest()
// 如果只执行一次update操作,可在digest方法中直接传入待摘要信息
public byte[] digest(byte[] input)
// 如果只执行一次update操作,可在digest方法中直接传入待摘要信息,并制定偏移量
public int digest(byte[] input, int offset, int len)

// 比较两个摘要的相等性
public static boolean isEqual(byte[] digesta, byte[] digestb)
// 重置摘要以供再次使用
public void reset()

// 返回算法名称,比如MD5
public final String getAlgorithm()
// 返回此摘要对象的提供者
public final Provider getProvider()
// 返回以字节为单位的摘要长度,如果摘要提供者不支持并且实现是不可复制的,则返回0
public final int getDigestLength()

3,示例代码

String str = "hello world";
MessageDigest md5 = MessageDigest.getInstance("md5");
byte[] digest1 = md5.digest(str.getBytes());
System.err.println(Arrays.toString(digest1));

md5.update(str.getBytes());
byte[] digest2 = md5.digest();
System.err.println(Arrays.toString(digest2));

boolean equal = MessageDigest.isEqual(digest1, digest2);
System.err.println(equal);

int digestLength = md5.getDigestLength();
System.err.println(digestLength);

String algorithm = md5.getAlgorithm();
System.err.println(algorithm);

Provider provider = md5.getProvider();
System.err.println(provider);

运行结果:

digest1:[94, -74, 59, -69, -32, 30, -18, -48, -109, -53, 34, -69, -113, 90, -51, -61]
digest2:[94, -74, 59, -69, -32, 30, -18, -48, -109, -53, 34, -69, -113, 90, -51, -61]
equal:true
digestLength:16
algorithm:md5
provider:SUN version 1.8

DigestInputStream

消息摘要流,包含消息摘要输入流和消息摘要输出流。

DigestInputStream类集成了FilterInputStream类,可以通过读取输入流的方式完成摘要更新,因此我们称它为消息摘要输入流,在指定的读操作方法内部完成MessageDigest类的update()方法

1,DigestInputStream类的实例。

public DigestInputStream(InputStream stream, MessageDigest digest)

2,更新MessageDigest对象

public void setMessageDigest(MessageDigest digest)

3,获取MessageDigest对象

public MessageDigest getMessageDigest()

4,开启或关闭摘要功能,若关闭DigestInputStream就变成了一般的输入流

public void on(boolean on)

5,更新摘要

// 读取字节并更新消息摘要(如果开启了摘要功能)
public int read()
// 读取字节数组并更新消息摘要(如果开启了摘要功能)
public int read(byte[] b, int off, int len)

6,示例代码

byte[] input = "hello world".getBytes();
MessageDigest md5 = MessageDigest.getInstance("md5");

DigestInputStream dis = new DigestInputStream(new ByteArrayInputStream(input), md5);
dis.read(input, 0, input.length);
// 获得摘要信息
byte[] digest = dis.getMessageDigest().digest();
// 关闭流
dis.close();
// 输出
System.err.println(Arrays.toString(digest));

运行结果

[94, -74, 59, -69, -32, 30, -18, -48, -109, -53, 34, -69, -113, 90, -51, -61]

DigestOutputStream

与DigestInputStream类相对应,DigestOutputStream类继承了FilterOutputStream类,可以通过写入输出流的方式完成摘要更新,因此我们称它为消息摘要输出流,在指定的写操作方法内部完成MessageDigest类的update()方法

1,DigestOutputStream类的实例。

public DigestOutputStream(OutputStream stream, MessageDigest digest)

2,更新MessageDigest对象

public void setMessageDigest(MessageDigest digest)

3,获取MessageDigest对象

public MessageDigest getMessageDigest()

4,开启或关闭摘要功能,若关闭DigestOutputStream就变成了一般的输出流

public void on(boolean on)

5,更新摘要

// 使用指定的字节并更新消息摘要(如果开启了摘要功能)
public void write(int b)
// 使用指定的字节数组并更新消息摘要(如果开启了摘要功能)
public void write(byte[] b, int off, int len)

6,示例代码

byte[] input = "hello world".getBytes();
MessageDigest md5 = MessageDigest.getInstance("md5");

DigestOutputStream dos = new DigestOutputStream(new ByteOutputStream(), md5);
dos.write(input, 0, input.length);
// 获得摘要信息
byte[] digest = dos.getMessageDigest().digest();
// 关闭流
dos.close();
// 输出
System.err.println(Arrays.toString(digest));

运行结果

[94, -74, 59, -69, -32, 30, -18, -48, -109, -53, 34, -69, -113, 90, -51, -61]

AlgorithmParameterGenerator

用于生成将在某个特定算法中使用的参数集合,我们把它称为算法参数生成器,它同样是一个引擎类。

1,AlgorithmParameterGenerator类的实例。

public static AlgorithmParameterGenerator getInstance(String algorithm)
public static AlgorithmParameterGenerator getInstance(String algorithm,String provider)
public static AlgorithmParameterGenerator getInstance(String algorithm,Provider provider)

2,与算法无关的初始化

// 针对某个特定大小,初始化此algorithmParameterGenerator对象
public final void init(int size)
// 针对某个特定大小和随机源,初始化此algorithmParameterGenerator对象
public final void init(int size, SecureRandom random)

3,与算法有关的初始化

// 利用特定于算法的参数生成值集合,初始化此algorithmParameterGenerator对象
public final void init(AlgorithmParameterSpec genParamSpec)
// 利用特定于算法的参数生成值集合和随机源,初始化此algorithmParameterGenerator对象
public final void init(AlgorithmParameterSpec genParamSpec,SecureRandom random)

4,相关方法

// 返回与此参数生成器关联的算法的标准名称
public final String getAlgorithm()
// 返回与此参数生成器关联的算法的提供者
public final Provider getProvider()
// 生成algorithmParameters对象
public final AlgorithmParameters generateParameters()

5,示例代码

AlgorithmParameterGenerator generator = AlgorithmParameterGenerator.getInstance("DSA");
// 初始化size有512、1024、2048
generator.init(51);

AlgorithmParameters parameters = generator.generateParameters();
byte[] encoded = parameters.getEncoded();

// 输出
System.err.println(new BigInteger(encoded));

运行结果

15406803697678878789801553621932051958252900910553943240741460124472011420390617777900484575253674885329057950790028005419522753814028540721158146460589685370378585929714786641488421023123198999048384010225670977532038193147440275375551369472983488071504122919824063922050892159492256186178152508578782268511314253471188620818092818973557275026423746784077615343028456754768900855358

AlgorithmParameters

是个引擎类,它提供密码参数的不透明表示

不透明表示与透明表示的区别在于:

  • 不透明表示:在这种表示中,不可以直接访问各参数域,只能得到与参数集相关联的算法名和该参数集的某类编码
  • 透明表示:用户可以通过相应规范类中定义的某个“get”方法来访问每个值。

1,AlgorithmParameters类的实例。

public static AlgorithmParameters getInstance(String algorithm)
public static AlgorithmParameters getInstance(String algorithm,String provider)

2,初始化

// 根据参数的基本解码格式导入指定的参数字节数组并对其解码
public final void init(byte[] params)
// 根据指定的解码方案从参数字节数组导入参数并对其解码
public final void init(byte[] params, String format)
// 使用paramSpec指定的参数初始化此algorithmParameters对象
public final void init(AlgorithmParameterSpec paramSpec)

3,相关方法

// 返回基本编码格式的参数
public final byte[] getEncoded()
// 返回以指定方案编码的参数
public final byte[] getEncoded(String format)

4,示例代码

AlgorithmParameters parameters = AlgorithmParameters.getInstance("DSA");
parameters.init(new BigInteger("15406803697678878789801553621932051958252900910553943240741460124472011420390617777900484575253674885329057950790028005419522753814028540721158146460589685370378585929714786641488421023123198999048384010225670977532038193147440275375551369472983488071504122919824063922050892159492256186178152508578782268511314253471188620818092818973557275026423746784077615343028456754768900855358").toByteArray());
byte[] encoded = parameters.getEncoded();

// 输出
System.err.println(new BigInteger(encoded));

运行结果

15406803697678878789801553621932051958252900910553943240741460124472011420390617777900484575253674885329057950790028005419522753814028540721158146460589685370378585929714786641488421023123198999048384010225670977532038193147440275375551369472983488071504122919824063922050892159492256186178152508578782268511314253471188620818092818973557275026423746784077615343028456754768900855358

KeyPairGenerator

公钥和私钥的生成是由KeyPairGenerator类来实现的,因此我们将它称为密钥对生成器,它同样是个引擎类。

1,KeyPairGenerator类的实例。

public static KeyPairGenerator getInstance(String algorithm)
public static KeyPairGenerator getInstance(String algorithm,String provider)
public static KeyPairGenerator getInstance(String algorithm,Provider provider)

2,与算法无关的初始化方法

public void initialize(int keysize)
public void initialize(int keysize, SecureRandom random)

3,特定于算法的初始化方法

public void initialize(AlgorithmParameterSpec params)
public void initialize(AlgorithmParameterSpec params,SecureRandom random)

4,相关方法

// 生成keyPair对象
public KeyPair generateKeyPair()
// 生成keyPair对象
public final KeyPair genKeyPair()
// 返回此密钥对生成器算法的标准名称
public String getAlgorithm()
// 返回此密钥对生成器对象的提供者
public final Provider getProvider()

5,示例代码

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
// 初始化
kpg.initialize(1024);
// 生成KeyPair对象
KeyPair keyPair = kpg.genKeyPair();

// 公钥
PublicKey aPublic = keyPair.getPublic();
// 私钥
PrivateKey aPrivate = keyPair.getPrivate();

KeyFactory

也是用来生产密钥(公钥和私钥)的引擎类,我们将它称为密钥工厂,它用来生成公钥/私钥,或者说的它的作用是通过密钥规范还原密钥。

与KeyFactory类对应的类是SecretKeyFactory类,这个类用于生成秘密密钥。

1,KeyFactory类的实例。

public static KeyFactory getInstance(String algorithm)
public static KeyFactory getInstance(String algorithm, String provider)
public static KeyFactory getInstance(String algorithm, Provider provider)

2,相关方法

// 根据提供的密钥规范(密钥材料)生成PublicKey对象
public final PublicKey generatePublic(KeySpec keySpec)
// 根据提供的密钥规范(密钥材料)生成PrivateKey对象
public final PrivateKey generatePrivate(KeySpec keySpec)
// 获取与此KeyFactory相关联的算法名称
public final String getAlgorithm()
// 返回此KeyFactory对象的提供者
public final Provider getProvider()

3,示例代码

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.genKeyPair();
// 获得私钥密钥字节数组。实际使用过程中该密钥以此形式保存传递给另一方
byte[] encoded1 = keyPair.getPrivate().getEncoded();
System.err.println("encoded1:" + Arrays.toString(encoded1));

// 由私钥密钥字节数组获得密钥规范
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(encoded1);
// 实例化密钥工厂,并指定RSA算法
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(spec);
byte[] encoded2 = privateKey.getEncoded();
System.err.println("encoded2:" + Arrays.toString(encoded2));

运行结果

encoded1:[48, -126, 2, 118, 2, 1, 0, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 4, -126, 2, 96, 48, -126, 2, 92, 2, 1, 0, 2, -127, -127, 0, -100, -4, 80, -48, -52, -55, -74, -26, -85, -106, 16, -66, -92, 58, -24, -22, -106, -41, -105, 29, -25, 86, 41, -15, 92, 85, -25, -76, -2, -21, 34, 72, -60, -2, -77, -86, -31, -70, 4, -8, 125, 64, -60, 49, 37, -24, -1, 105, -115, 109, 3, 83, -15, -12, 20, 49, 93, -109, -51, 113, 17, -56, 50, -17, 62, 71, -74, 121, 126, -124, 23, -56, 45, -76, -30, -16, -34, -1, 120, 116, 122, 7, 47, -68, -15, 104, 118, 59, -28, -122, 53, -91, -43, 17, -75, 124, 52, 84, 32, 4, 67, 55, 112, -67, -110, 121, -114, 123, 106, 116, -29, 104, 57, 7, 87, 5, 60, 89, -51, -65, 101, -67, 42, -74, 124, 21, 69, 53, 2, 3, 1, 0, 1, 2, -127, -128, 30, 98, -92, 13, -42, 37, -112, -10, 82, -19, -25, -19, -50, -127, -20, -123, 67, -113, 21, 27, -33, -92, 8, -40, 67, -60, 8, -26, 58, -107, 46, 124, -95, 76, -97, 96, 10, -14, -29, 117, 105, 96, -8, -40, 126, 122, -5, -68, -27, 119, -35, 54, 9, 85, -15, -10, -96, 35, 52, -105, -105, 22, -123, -19, 3, 46, 50, -73, 13, -64, -105, 107, -123, 123, -84, -82, -18, -39, -47, -73, 40, 3, 57, 119, 64, 5, 46, 0, 56, 101, -16, 32, -79, 77, -65, -82, -85, -68, 97, -18, -92, 12, 81, -77, 47, -116, -91, -21, 75, 117, 108, -24, -56, 76, -84, -123, 77, -45, -85, -47, -8, -72, -91, -101, -96, -26, -74, 61, 2, 65, 0, -5, 40, -71, -111, 65, -5, -11, 95, -48, 85, 3, -31, -73, -82, 110, 70, 62, -66, -14, -77, 13, -24, 119, 35, 103, 12, -13, 123, -120, 95, -126, 89, 95, -103, 110, 82, 73, -45, 94, -7, 44, 52, -77, -104, -9, 32, -31, -60, 48, 1, -32, 60, 55, -119, 67, -79, -88, -29, -107, -64, 66, 95, -79, 111, 2, 65, 0, -96, 2, -22, -11, -3, -99, 20, 66, 31, -125, -54, 107, -17, -66, 1, -24, 32, -115, -17, 95, 16, 111, 99, 6, -123, 77, 2, -87, 126, 100, -51, -1, -65, 86, 4, 39, -43, 94, 56, -50, -50, -38, 22, 30, 45, -8, 122, 9, -50, 47, 0, 51, 68, 52, 98, 36, 105, 26, -20, 30, -114, -65, 25, -101, 2, 64, 36, 19, -41, -124, 28, 28, 91, 68, -26, 34, 48, 42, -114, 62, 10, 45, 32, -6, 64, -42, -93, -102, -50, -14, 80, -19, 53, 84, 123, 100, 108, -50, -11, -62, -114, 108, 87, -102, 123, 60, 3, -77, -106, 80, -44, -66, -18, 111, 70, 14, 30, -19, -57, 116, 122, 58, -36, -19, -60, 39, 23, -31, -77, 21, 2, 65, 0, -108, -59, -31, -68, 81, -49, -88, -76, 74, 36, -7, 34, 30, 72, 37, -15, -77, -61, 4, 26, -7, 102, -9, 69, 106, -49, 77, 120, 86, 2, 87, -34, 64, 2, 51, -34, -19, 109, -85, -105, -19, -113, -84, 28, -25, 85, 45, -14, -53, -9, -69, 81, -17, 74, 93, 45, -55, 99, -76, -62, 60, -86, -59, -99, 2, 64, 30, -59, -76, -88, -89, -1, 83, -17, 19, 103, 6, -104, -70, 4, 15, 109, 104, -52, 37, 51, 22, -34, -33, -40, 123, 70, 111, 10, -14, -124, -14, 67, -79, 104, 14, -127, 24, 98, 125, -126, 68, 48, 42, -96, 22, 47, -1, -64, -78, -102, -78, 16, -54, 47, 111, -63, -38, 42, 74, 78, -24, -95, -94, -100]
encoded2:[48, -126, 2, 118, 2, 1, 0, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 4, -126, 2, 96, 48, -126, 2, 92, 2, 1, 0, 2, -127, -127, 0, -100, -4, 80, -48, -52, -55, -74, -26, -85, -106, 16, -66, -92, 58, -24, -22, -106, -41, -105, 29, -25, 86, 41, -15, 92, 85, -25, -76, -2, -21, 34, 72, -60, -2, -77, -86, -31, -70, 4, -8, 125, 64, -60, 49, 37, -24, -1, 105, -115, 109, 3, 83, -15, -12, 20, 49, 93, -109, -51, 113, 17, -56, 50, -17, 62, 71, -74, 121, 126, -124, 23, -56, 45, -76, -30, -16, -34, -1, 120, 116, 122, 7, 47, -68, -15, 104, 118, 59, -28, -122, 53, -91, -43, 17, -75, 124, 52, 84, 32, 4, 67, 55, 112, -67, -110, 121, -114, 123, 106, 116, -29, 104, 57, 7, 87, 5, 60, 89, -51, -65, 101, -67, 42, -74, 124, 21, 69, 53, 2, 3, 1, 0, 1, 2, -127, -128, 30, 98, -92, 13, -42, 37, -112, -10, 82, -19, -25, -19, -50, -127, -20, -123, 67, -113, 21, 27, -33, -92, 8, -40, 67, -60, 8, -26, 58, -107, 46, 124, -95, 76, -97, 96, 10, -14, -29, 117, 105, 96, -8, -40, 126, 122, -5, -68, -27, 119, -35, 54, 9, 85, -15, -10, -96, 35, 52, -105, -105, 22, -123, -19, 3, 46, 50, -73, 13, -64, -105, 107, -123, 123, -84, -82, -18, -39, -47, -73, 40, 3, 57, 119, 64, 5, 46, 0, 56, 101, -16, 32, -79, 77, -65, -82, -85, -68, 97, -18, -92, 12, 81, -77, 47, -116, -91, -21, 75, 117, 108, -24, -56, 76, -84, -123, 77, -45, -85, -47, -8, -72, -91, -101, -96, -26, -74, 61, 2, 65, 0, -5, 40, -71, -111, 65, -5, -11, 95, -48, 85, 3, -31, -73, -82, 110, 70, 62, -66, -14, -77, 13, -24, 119, 35, 103, 12, -13, 123, -120, 95, -126, 89, 95, -103, 110, 82, 73, -45, 94, -7, 44, 52, -77, -104, -9, 32, -31, -60, 48, 1, -32, 60, 55, -119, 67, -79, -88, -29, -107, -64, 66, 95, -79, 111, 2, 65, 0, -96, 2, -22, -11, -3, -99, 20, 66, 31, -125, -54, 107, -17, -66, 1, -24, 32, -115, -17, 95, 16, 111, 99, 6, -123, 77, 2, -87, 126, 100, -51, -1, -65, 86, 4, 39, -43, 94, 56, -50, -50, -38, 22, 30, 45, -8, 122, 9, -50, 47, 0, 51, 68, 52, 98, 36, 105, 26, -20, 30, -114, -65, 25, -101, 2, 64, 36, 19, -41, -124, 28, 28, 91, 68, -26, 34, 48, 42, -114, 62, 10, 45, 32, -6, 64, -42, -93, -102, -50, -14, 80, -19, 53, 84, 123, 100, 108, -50, -11, -62, -114, 108, 87, -102, 123, 60, 3, -77, -106, 80, -44, -66, -18, 111, 70, 14, 30, -19, -57, 116, 122, 58, -36, -19, -60, 39, 23, -31, -77, 21, 2, 65, 0, -108, -59, -31, -68, 81, -49, -88, -76, 74, 36, -7, 34, 30, 72, 37, -15, -77, -61, 4, 26, -7, 102, -9, 69, 106, -49, 77, 120, 86, 2, 87, -34, 64, 2, 51, -34, -19, 109, -85, -105, -19, -113, -84, 28, -25, 85, 45, -14, -53, -9, -69, 81, -17, 74, 93, 45, -55, 99, -76, -62, 60, -86, -59, -99, 2, 64, 30, -59, -76, -88, -89, -1, 83, -17, 19, 103, 6, -104, -70, 4, 15, 109, 104, -52, 37, 51, 22, -34, -33, -40, 123, 70, 111, 10, -14, 、-124, -14, 67, -79, 104, 14, -127, 24, 98, 125, -126, 68, 48, 42, -96, 22, 47, -1, -64, -78, -102, -78, 16, -54, 47, 111, -63, -38, 42, 74, 78, -24, -95, -94, -100]

SecureRandom

继承于Random类,它起到强加密随机数生成器的作用,我们称它为安全随机数生成器,同样是个引擎类。

1,SecureRandom类的实例

public SecureRandom()
// 给定一个种子
public SecureRandom(byte seed[])

public static SecureRandom getInstance(String algorithm)
public static SecureRandom getInstance(String algorithm, String provider)
public static SecureRandom getInstance(String algorithm,Provider provider)

2,相关方法

// 返回给定的种子字节数量
public byte[] generateSeed(int numBytes)
// 返回给定的种子字节数量
public static byte[] getSeed(int numBytes)
// 重新设置此随机对象的种子
public void setSeed(long seed)
synchronized public void setSeed(byte[] seed)

3,示例代码

SecureRandom secureRandom = new SecureRandom();
KeyGenerator kg = KeyGenerator.getInstance("DES");
kg.init(secureRandom);

SecretKey secretKey = kg.generateKey();
System.err.println(Arrays.toString(secretKey.getEncoded()));

运行结果

[64, 50, 121, 93, 62, 8, 109, -17]

Signature

用来生成和验证数字签名,同样是个引擎类。

1,Signature类的实例

public static Signature getInstance(String algorithm)
public static Signature getInstance(String algorithm, String provider)
public static Signature getInstance(String algorithm, Provider provider)

2,用于签名操作的初始化

public final void initSign(PrivateKey privateKey)
public final void initSign(PrivateKey privateKey, SecureRandom random)

3,用于验证操作的初始化

// 一般的数字签名验证操作
public final void initVerify(PublicKey publicKey)
// 数字证书的验证操作
public final void initVerify(Certificate certificate)

4,更新Signature对象中的数据

public final void update(byte b)
public final void update(byte[] data)
public final void update(ByteBuffer data)
public final void update(byte[] data, int off, int len)

5,签名操作

// 返回所有已更新数据的签名字节
public final byte[] sign()
// 完成签名操作,并得到存储在缓冲区中的签名字节长度
public final int sign(byte[] outbuf, int offset, int len)

6,验证操作

// 验证传入的签名,并返回验证结果
public final boolean verify(byte[] signature)
// 从指定的偏移量开始,验证指定的字节数组传入的签名,并返回验证结果
public final boolean verify(byte[] signature, int offset, int length)

7,示例代码

byte[] input = "hello world".getBytes();

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.genKeyPair();

Signature signature = Signature.getInstance(kpg.getAlgorithm());
signature.initSign(keyPair.getPrivate());
signature.update(input);
// 签名后的数据
byte[] sign = signature.sign();

signature.initVerify(keyPair.getPublic());
// 签名原文
signature.update(input);
// 验签
boolean verify = signature.verify(sign);
System.err.println("验签结果:" + verify);

运行结果

验签结果:true

SignedObject

是一个用来创建实际运行时的对象的类,在检测不到这些对象的情况下,其完整性不会遭到损害。更明确的说,SignedObject包含里另外一个Serializable对象,即要签名的对象及其签名,我们可以称它为签名对象

签名对象是对原始对象的“深层复制”(以序列化的形式),一旦生成来副本,对原始对象的进一步操作就不再影响该副本。

1,SignedObject类的实例

public SignedObject(Serializable object, PrivateKey signingKey,Signature signingEngine)

2,相关方法

// 获得已封装的对象
public Object getObject()
// 在已签名的对象上按字节数组的形式获取签名
public byte[] getSignature()
// 通过指定的验证密钥验证SignedObject中的签名是否为内部存储对象的有效签名
public boolean verify(PublicKey verificationKey,Signature verificationEngine)

3,示例代码

byte[] input = "hello world".getBytes();

KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.genKeyPair();

Signature signature = Signature.getInstance(kpg.getAlgorithm());
SignedObject signedObject = new SignedObject(input, keyPair.getPrivate(), signature);

byte[] bytes = signedObject.getSignature();
System.err.println("签名数据:" + Arrays.toString(bytes));

boolean verify = signedObject.verify(keyPair.getPublic(), signature);
System.err.println("验签结果:" + verify);

运行结果

签名数据:[48, 44, 2, 20, 109, -93, 46, -64, 36, -36, 77, 0, 55, -77, 81, 13, 42, -51, -78, 127, -128, 6, -60, -50, 2, 20, 30, 103, 14, -9, 115, 58, 104, 118, 60, -35, 25, -90, 14, 93, -27, 101, 87, -77, -19, 110]
验签结果:true

KeyStore

被称为密钥库,用于管理密钥和证书的存储,是个引擎类。

1,KeyStore类的实例

public static KeyStore getInstance(String type)
public static KeyStore getInstance(String type, String provider)
public static KeyStore getInstance(String type, Provider provider)

2,相关方法

// 返回此密钥库的类型
public final String getType()
// 返回此密钥库中的条目个数
public final int size()
// 返回此密钥库的提供者
public final Provider getProvider()
// 列出此密钥库的所有别名
public final Enumeration<String> aliases()
// 返回与给定别名关联的密钥,并用给定的密码来恢复它。虽然是key类型,实际是PrivateKey接口的实例
public final Key getKey(String alias, char[] password)
// 获取证书
public final Certificate getCertificate(String alias)
// 获取证书链
public final Certificate[] getCertificateChain(String alias)
// 返回证书与给定证书匹配的第一个密钥库条目的别名
public final String getCertificateAlias(Certificate cert)
// 返回给定别名标识的条目的创建日期
public final Date getCreationDate(String alias)
// 删除此密钥库中给定别名标识的条目
public final void deleteEntry(String alias)
// 别名对应证书
public final boolean isCertificateEntry(String alias)
// 别名对应密钥
public final boolean isKeyEntry(String alias)
// 获得别名对应的私钥
public final Key getKey(String alias, char[] password)
// 获得别名对应的私钥
public final Entry getEntry(String alias, ProtectionParameter protParam)

3,示例代码

// 返回此密钥库的类型
String type = keyStore.getType();
System.err.println("type:" + type);

// 返回此密钥库中的条目个数
int size = keyStore.size();
System.err.println("size:" + size);

// 返回此密钥库的提供者
Provider provider = keyStore.getProvider();
System.err.println("provider:" + provider);

// 列出此密钥库的所有别名
String alias = null;
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
    String s = aliases.nextElement();
    System.err.println("alias:" + s);
    // 最后一个别名
    alias = s;
}

// 返回与给定别名关联的密钥,并用给定的密码来恢复它。虽然是key类型,实际是PrivateKey接口的实例
PrivateKey key = (PrivateKey) keyStore.getKey(alias, password);
System.err.println("key:" + key.getAlgorithm());

// 获取证书
Certificate certificate = keyStore.getCertificate(alias);
System.err.println("type:" + certificate.getType());

// 获取证书链
Certificate[] certificates = keyStore.getCertificateChain(alias);
for (Certificate cert : certificates) {
    System.err.println("type:" + cert.getType());
}

// 返回证书与给定证书匹配的第一个密钥库条目的别名
alias = keyStore.getCertificateAlias(certificate);
System.err.println("alias:" + alias);

// 返回给定别名标识的条目的创建日期
Date date = keyStore.getCreationDate(alias);
System.err.println("date:" + date);

// 删除此密钥库中给定别名标识的条目
// keyStore.deleteEntry(alias);

// 别名对应证书
boolean certificateEntry = keyStore.isCertificateEntry(alias);
System.err.println("certificateEntry:" + certificateEntry);

// 别名对应密钥
boolean keyEntry = keyStore.isKeyEntry(alias);
System.err.println("keyEntry:" + keyEntry);

// 获得别名对应的私钥
PrivateKey key1 = (PrivateKey) keyStore.getKey(alias, password);
System.err.println("key1:" + Base64.getEncoder().encodeToString(key1.getEncoded()));
// 或
KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(password));
PrivateKey key2 = entry.getPrivateKey();
System.err.println("key2:" + Base64.getEncoder().encodeToString(key2.getEncoded()));

运行结果

type:jks
size:1
provider:SUN version 1.8
alias:androiddebugkey
key:RSA
type:X.509
type:X.509
alias:androiddebugkey
date:Sun Jul 23 21:32:43 CST 2017
certificateEntry:false
keyEntry:true
key1:MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDtSz9eI3JdrMSHWSWH9ccqzdGTMRGa5iduZBtQSiuFdZBJee5o2qGoi2vvW04MF3lF8dGF3v3FYsdb+y8eQS9e91sroe5wq2jNtlSoY3OSQt3K4EZAU875pVGmwku66DiENXHbtSnSpLXMw2g1QUow8vYQ8Zz/6lpWBO4xxdXFaYY2TpAHfAFoKm/63kilif0M2g4vrN+hWYPYFa9W1DVq6BfMIyquizfjZtk8K5RI24X3F2wZk83QI0VA+KkjdszLugGK8NMYKNWOF2yvWXKfAaDiuEhDa8REOXhh62W51zTvnRQDbt0excg7r+6p+orrB+VH+RgBZQLu0b20Hv7XAgMBAAECggEBAN5nxZfFH17/HCBDhLK+wJK037XWqsqE5vZHa3ZAXjQzMS480yCBsjzXmC16ZVdd9POCp7+SdkW3xGTIs6vmqrCWpGPr3SDK92q/du9wbxTqCRkqRY3rPzWrJjFnMDWZi8cWlIW5cd6VNDQb/iLT8+aXAdx1qJIQI+U1r88EvszLwdOf3N2Fq/hkOFn2nfaNw6zHYON37rAFcOw8/XHv52U6t4ExxbiatLjl7/wo4c0mpleDZlLx1eG0AWMB4/P2mI4oMJWLULYCl3y51HENoKLkHSxJE27sn6FhXLgs9M1bQLKqGV2sgidU51y7g0N4mZ4GWOH9CXVyoSaAn2duABECgYEA9t9wEqONLmUTyBIF+HTFRtcA17RQgHA8zo+qoSBVe2fO+7RnGxOBDwbJ+3H+ZyOkmleo3ygEIGh6/bxZuXo48viSurQ4QntAi1NIfVP4qqy+pIXRDbjqZgi2FsLOvKK3POPOUk7FXmdhTwpLzRkSooCS2I33KiOmxjvVTOYYxo8CgYEA9hEmMmqR3b5bwdYAxO5IUFMq/QOqak2W4k/XWITRHb10oynfCEgL+9PSA16ODvmxlfa0R+ATv3HPbzPjMdYRIjXOx/vgU+R/pDmxuiccX7xDE8RXByltX5dTy1dHc0FLFEhT0oX0k5fNGrm92mC9k4ri2QVZ7H0j1q2JJF11JzkCgYBQGJhVA8lXhyXO4MIdJU2oOTOlyHPh6AhigEw88K+rVTfbhGF7cG2MAYjg0tBWiELsbIp2tJX6KcvVrRlzSwtVEX8Rok0qjLCZQ5EeUHM6dMd5u4zjJd6u8h6Z7eSDYUuQLt0O6U2x3lq8+Ts0tPDN1mdOaWkKu/xtDpaa14CsUwKBgQCWUQWXeNigsB/Xeoa/xpxwTU4OgAXDqKBKoeF4VrJ0S38MCZEQuwpvDQfXPRTk+w3MAYhB/BW0Nq80TGs2z4Fp95rZOfng5c4/oWr7v9aqeRQ06BUN7/W7lnL+3dNtCe72dfSWv3QYEXyfHeZnl/9XOVm4n3c+a3fQNfR4PYtKqQKBgQC+VVvFdDTsswbyKlFdCM4i+YSklDHY7QNqjzxW46iXbf85PnX0ol4hIn6WhctccDd++C5u62LAISzvsq1nirskb10wiaK3Xb7Q3Eul5ATHWS0nZxPEvrlEDso16cRh7od7QamhTE4hH4gMsWd+6j0YsYIPd47jXs+QVKfpPVSPUA==
key2:MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDtSz9eI3JdrMSHWSWH9ccqzdGTMRGa5iduZBtQSiuFdZBJee5o2qGoi2vvW04MF3lF8dGF3v3FYsdb+y8eQS9e91sroe5wq2jNtlSoY3OSQt3K4EZAU875pVGmwku66DiENXHbtSnSpLXMw2g1QUow8vYQ8Zz/6lpWBO4xxdXFaYY2TpAHfAFoKm/63kilif0M2g4vrN+hWYPYFa9W1DVq6BfMIyquizfjZtk8K5RI24X3F2wZk83QI0VA+KkjdszLugGK8NMYKNWOF2yvWXKfAaDiuEhDa8REOXhh62W51zTvnRQDbt0excg7r+6p+orrB+VH+RgBZQLu0b20Hv7XAgMBAAECggEBAN5nxZfFH17/HCBDhLK+wJK037XWqsqE5vZHa3ZAXjQzMS480yCBsjzXmC16ZVdd9POCp7+SdkW3xGTIs6vmqrCWpGPr3SDK92q/du9wbxTqCRkqRY3rPzWrJjFnMDWZi8cWlIW5cd6VNDQb/iLT8+aXAdx1qJIQI+U1r88EvszLwdOf3N2Fq/hkOFn2nfaNw6zHYON37rAFcOw8/XHv52U6t4ExxbiatLjl7/wo4c0mpleDZlLx1eG0AWMB4/P2mI4oMJWLULYCl3y51HENoKLkHSxJE27sn6FhXLgs9M1bQLKqGV2sgidU51y7g0N4mZ4GWOH9CXVyoSaAn2duABECgYEA9t9wEqONLmUTyBIF+HTFRtcA17RQgHA8zo+qoSBVe2fO+7RnGxOBDwbJ+3H+ZyOkmleo3ygEIGh6/bxZuXo48viSurQ4QntAi1NIfVP4qqy+pIXRDbjqZgi2FsLOvKK3POPOUk7FXmdhTwpLzRkSooCS2I33KiOmxjvVTOYYxo8CgYEA9hEmMmqR3b5bwdYAxO5IUFMq/QOqak2W4k/XWITRHb10oynfCEgL+9PSA16ODvmxlfa0R+ATv3HPbzPjMdYRIjXOx/vgU+R/pDmxuiccX7xDE8RXByltX5dTy1dHc0FLFEhT0oX0k5fNGrm92mC9k4ri2QVZ7H0j1q2JJF11JzkCgYBQGJhVA8lXhyXO4MIdJU2oOTOlyHPh6AhigEw88K+rVTfbhGF7cG2MAYjg0tBWiELsbIp2tJX6KcvVrRlzSwtVEX8Rok0qjLCZQ5EeUHM6dMd5u4zjJd6u8h6Z7eSDYUuQLt0O6U2x3lq8+Ts0tPDN1mdOaWkKu/xtDpaa14CsUwKBgQCWUQWXeNigsB/Xeoa/xpxwTU4OgAXDqKBKoeF4VrJ0S38MCZEQuwpvDQfXPRTk+w3MAYhB/BW0Nq80TGs2z4Fp95rZOfng5c4/oWr7v9aqeRQ06BUN7/W7lnL+3dNtCe72dfSWv3QYEXyfHeZnl/9XOVm4n3c+a3fQNfR4PYtKqQKBgQC+VVvFdDTsswbyKlFdCM4i+YSklDHY7QNqjzxW46iXbf85PnX0ol4hIn6WhctccDd++C5u62LAISzvsq1nirskb10wiaK3Xb7Q3Eul5ATHWS0nZxPEvrlEDso16cRh7od7QamhTE4hH4gMsWd+6j0YsYIPd47jXs+QVKfpPVSPUA==
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容