我是菜鸟:java密码学的应用

下面是阅读 Java Cryptography Architecture(JCA) Reference Guide的一些笔记

Architecture

java 安全体系的结构
- Cryptographic Service Providers (加密服务提供者)
java.security.Provider 是所有安全服务提供者的基类,每一个CSP实例都包含了provider的名字和它实现了所有算法的名字。当需要一个特定算法的实例时,JCA就会查询provider,如果找到就返回相应的实例。
每个JDK安装了一个或者多个provider,需要更多的provider需要自己安装。
当在应用程序中使用JCA时,仅仅需要一个特定的对象和一个特定的算法/服务。例如MessageDigest对象中的MD5算法。这样便可以获得一个实例。对于provider的选取要么选择优先级最高的那个(如果没有指定具体的算法),要么选择指定的provider。
- provider的实现过程
每个引擎类提供的应用API都被实现相应SPI(Service Provider Interface)的类路由到provide的具体实现中。每一个引擎类都对应一个SPI。
调用过程:
假设需要使用AES算法。
.应用程序 调用 getInstance() 获得cipher 引擎类。
. cipher 引擎类要求JAC框架找到第一个满足AES的provider.
. JCA 框架查询所有的provider并且返回其中合适的一个provider.
. 然后provider找到相应的实现类,并创建实例和返回。
2. 密钥管理
keystore 可用来管理密钥和证书,它实现了java.security.KeyStore 类,应用程序可以向它请求数据用于认证、加密或者签名等。

JCA概念

Engine Classes

An engine class provides the interface to a specific type of cryptographic service, independent of a particular cryptographic algorithm or provider.

一些引擎类

  1. SecureRandom: 用来生成随机数。
  2. MessageDigest: 用来生成消息摘要(hash)和一些特定的数据
  3. Signature: 使用密钥初始化用来签名数据和验证数字签名。
  4. Cipher: 使用密钥初始化后用来加密、解密数据。包括例如对称分块加密(AES,DES,DESede,Blowfish, IDEA),流密码(RC4),非对称加密(RSA)以及基于密码的加密(PBE)
  5. Message Authentication Codes (MAC): 例如MessageDigests, 产生带密钥的hash值
    6.KeyFactory: 用来转化现存的不透明的密钥到一个特殊格式。vice versa(反之亦然)。
  6. SecretKeyFactory: 与6类似,其是6的特例,只能用于对称密钥。
  7. KeyPairGenerator: 用来生成一组公私钥对。
  8. KeyGenerator: used to generate new secret keys for use with a specified algorithm.
  9. KeyAgreement:用特定的算法来进行密钥协商。
  10. AlgorithmParameters: 用来存储特定算法的相应参数包括加密解密的参数。u
  11. AlgorithmParameterGenerator :
  12. KeyStore: used to create and manage a keystore. A keystore is a database of keys. Private keys in a keystore have a certificate chain associated with them, which authenticates the corresponding public key. A keystore also contains certificates from trusted entities.
  13. CertificateFactory: used to create public key certificates and Certificate Revocation Lists (CRLs).
  14. CertPathBuilder: used to build certificate chains (also known as certification paths).
  15. CertPathValidator: used to validate certificate chains.
  16. CertStore: used to retrieve Certificates and CRLs from a repository.

具体实现

static EngineClassName getInstance(String algorithm) throws NoSuchAlgorithmException
e.g.:
MessageDigest md = MessageDigest.getInstance(“MD5”); // MD5 对大小写不敏感
MessageDigest.getInstance(“SHA-1”);

The SecureRandom Class

产生安全的随机数

The MessageDigest Class

  1. Creating a MessageDigest Object (getInstance();)
  2. Updating a Message Digest Object (如果消息以分块的形式,则需要调用updata以产生最终的hash value.)
  3. Computing the Digest
    byte[] digest()

The Signature Class

我是菜鸟:java密码学的应用_第1张图片
编写代码过程
1. create a signature object
Signature dsa = Signature.getInstance(“SHA1withDSA”);
2. 生成密钥对,并用私钥初始化上面的对象并对数据进行签名
PrivateKey priv = pair.getPrivate();
dsa.initSign(priv);
dsa.update(data);
byte[] sig = dsa.sign();
3. Verifying a Signature
PublicKey pub = pair.getPublic();
dsa.initVerify(pub);
dsa.update(data);
boolean verifies = dsa.verify(sig);
System.out.println(“signature verifies: ” + verifies);
另外如果我们拥有的不是公私钥对,而是生成公私钥对的参数,例如DSA private key: x (the private key), p (the prime), q (the sub-prime), and g (the base),那么必须先要生成公私钥。
DSAPrivateKeySpec dsaPrivKeySpec = new DSAPrivateKeySpec(x, p, q, g);
e.g.,:
Sign

*//私钥*
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PrivateKey privKey = keyFactory.generatePrivate(dsaPrivKeySpec);

Signature sig = Signature.getInstance("SHA1withDSA");
sig.initSign(privKey);
sig.update(someData);
byte[] signature = sig.sign();
*//公约*
DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec(y, p, q, g);
byte[] encKey = pubKey.getEncoded();  //extract the (encoded) key bytes

Verify:

   X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encodedPubKey);

    KeyFactory keyFactory = KeyFactory.getInstance("DSA");
    PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);

    Signature sig = Signature.getInstance("SHA1withDSA");
    sig.initVerify(pubKey);
    sig.update(data);
    sig.verify(signature);

NOTE: 验证方可以获得p,q,g和公约。

DSAPublicKeySpec dsaPubKeySpec =
        (DSAPublicKeySpec)keyFactory.getKeySpec(pubKey,
            DSAPublicKeySpec.class);
dsaPubKeySpec.getX();
....

The Cipher Class


分组密码和流密码:分组密码一次处理一个数据块,如果数据不足,需要先填充再加密。填充方式可以为应用填充或者选择cipher的填充方式(PKCS5PADDING)。(我也不明白这是什么填充方法)。
流密码一次处理一个单元(如byte or bit),因此不用填充。

简单的分组密码(ECB),对于2个相同的数据加密后的数据是一样的,为了打破这种限制有另外的模式如CBC,CFB,OFB。 使用这些模式的时候,需要一个不需要保密的初始向量。另外AES、RSA的密钥长度是不固定的,而DES、3DES的密钥是固定的。(哇,这个都忘记了。)
1. Creating a Cipher Object
getInstance( transformation )

注意: A transformation is of the form:
“algorithm/mode/padding” or
“algorithm”
2. Initializing a Cipher Object
3. Encrypting and Decrypting Data
To encrypt or decrypt data in a single step, call one of the doFinal methods
To encrypt or decrypt data in multiple steps, call one of the update methods, a multiple-part operation must be terminated by one of the above doFinal methods.

一些重要的内容已经看完,下面是一些其他的内容。
密钥的包装,为了更加安全的传送密钥。

Wrapping and Unwrapping Keys

首先需要创建一个Cipher(WRAP_MODE), 然后调用wrap函数,
注意在获取密钥的时候,需要向unwrap的应用提供:算法的名字和包装密钥的类型(Cipher.SECRET_KEY, Cipher.PRIVATE_KEY, or Cipher.PUBLIC_KEY)。

为了解包密钥,同样需要定义个Cipher(UNWRAP_MODE),并且调用unwrap()方法来获得key。

Managing Algorithm Parameters

可以通过调用getParameters来获取参数Cipher object 的参数,返回一个java.security.AlgorithmParameters 对象。

import javax.crypto.*;
    import java.security.AlgorithmParameters;

    // get cipher object for password-based encryption
    Cipher c = Cipher.getInstance("PBEWithMD5AndDES");

    // initialize cipher for encryption, without supplying
    // any parameters. Here, "myKey" is assumed to refer
    // to an already-generated key.
    c.init(Cipher.ENCRYPT_MODE, myKey);

    // encrypt some data and store away ciphertext
    // for later decryption
    byte[] cipherText = c.doFinal("This is just an example".getBytes());

    // retrieve parameters generated by underlying cipher
    // implementation
    AlgorithmParameters algParams = c.getParameters();

    // get parameter encoding and store it away
    byte[] encodedAlgParams = algParams.getEncoded();
//利用上面的参数重新加密其他的内容
 AlgorithmParameters algParams;
    algParams = AlgorithmParameters.getInstance("PBEWithMD5AndDES");

    // initialize with parameter encoding from above
    algParams.init(encodedAlgParams);

    // get cipher object for password-based encryption
    Cipher c = Cipher.getInstance("PBEWithMD5AndDES");

    // initialize cipher for decryption, using one of the
    // init() methods that takes an AlgorithmParameters
    // object, and pass it the algParams object from above
    c.init(Cipher.DECRYPT_MODE, myKey, algParams);

Note:The following method in Cipher can be used to determine how big the output buffer should be:

public int getOutputSize(int inputLen)

MAC

example:

import java.security.*;
import javax.crypto.*;

/** * This program demonstrates how to generate a secret-key object for * HMAC-MD5, and initialize an HMAC-MD5 object with it. */

public class initMac {

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

        // Generate secret key for HMAC-MD5
        KeyGenerator kg = KeyGenerator.getInstance("HmacMD5");
        SecretKey sk = kg.generateKey();

        // Get instance of Mac object implementing HMAC-MD5, and
        // initialize it with the above secret key
        Mac mac = Mac.getInstance("HmacMD5");  
        mac.init(sk);
        byte[] result = mac.doFinal("Hi There".getBytes());
    }
}

你可能感兴趣的:(我是菜鸟:java密码学的应用)