来自SecretKeySpec的Java安全性init Cipher正确

时间:2013-01-09 07:16:06

标签: java jce diffie-hellman

我正在测试Diffie-Hellman KeyAgreement算法。并使用它来生成密钥。但在我得到SecretKeySpec之后,我遇到了使用它来初始化Cipher的问题。这是我的代码:

DiffieHellmanModule

package ggicci.infosec;

import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.KeyAgreement;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * Diffie-Hellman module for demonstrating KeyAgreement Algorithm
 * @author Ggicci
 * @since 2013.01.09
 */
public class DiffieHellmanModule {
    private static final byte[] skip1024ModulusBytes = { (byte) 0xF4,
            (byte) 0x88, (byte) 0xFD, (byte) 0x58, (byte) 0x4E, (byte) 0x49,
            (byte) 0xDB, (byte) 0xCD, (byte) 0x20, (byte) 0xB4, (byte) 0x9D,
            (byte) 0xE4, (byte) 0x91, (byte) 0x07, (byte) 0x36, (byte) 0x6B,
            (byte) 0x33, (byte) 0x6C, (byte) 0x38, (byte) 0x0D, (byte) 0x45,
            (byte) 0x1D, (byte) 0x0F, (byte) 0x7C, (byte) 0x88, (byte) 0xB3,
            (byte) 0x1C, (byte) 0x7C, (byte) 0x5B, (byte) 0x2D, (byte) 0x8E,
            (byte) 0xF6, (byte) 0xF3, (byte) 0xC9, (byte) 0x23, (byte) 0xC0,
            (byte) 0x43, (byte) 0xF0, (byte) 0xA5, (byte) 0x5B, (byte) 0x18,
            (byte) 0x8D, (byte) 0x8E, (byte) 0xBB, (byte) 0x55, (byte) 0x8C,
            (byte) 0xB8, (byte) 0x5D, (byte) 0x38, (byte) 0xD3, (byte) 0x34,
            (byte) 0xFD, (byte) 0x7C, (byte) 0x17, (byte) 0x57, (byte) 0x43,
            (byte) 0xA3, (byte) 0x1D, (byte) 0x18, (byte) 0x6C, (byte) 0xDE,
            (byte) 0x33, (byte) 0x21, (byte) 0x2C, (byte) 0xB5, (byte) 0x2A,
            (byte) 0xFF, (byte) 0x3C, (byte) 0xE1, (byte) 0xB1, (byte) 0x29,
            (byte) 0x40, (byte) 0x18, (byte) 0x11, (byte) 0x8D, (byte) 0x7C,
            (byte) 0x84, (byte) 0xA7, (byte) 0x0A, (byte) 0x72, (byte) 0xD6,
            (byte) 0x86, (byte) 0xC4, (byte) 0x03, (byte) 0x19, (byte) 0xC8,
            (byte) 0x07, (byte) 0x29, (byte) 0x7A, (byte) 0xCA, (byte) 0x95,
            (byte) 0x0C, (byte) 0xD9, (byte) 0x96, (byte) 0x9F, (byte) 0xAB,
            (byte) 0xD0, (byte) 0x0A, (byte) 0x50, (byte) 0x9B, (byte) 0x02,
            (byte) 0x46, (byte) 0xD3, (byte) 0x08, (byte) 0x3D, (byte) 0x66,
            (byte) 0xA4, (byte) 0x5D, (byte) 0x41, (byte) 0x9F, (byte) 0x9C,
            (byte) 0x7C, (byte) 0xBD, (byte) 0x89, (byte) 0x4B, (byte) 0x22,
            (byte) 0x19, (byte) 0x26, (byte) 0xBA, (byte) 0xAB, (byte) 0xA2,
            (byte) 0x5E, (byte) 0xC3, (byte) 0x55, (byte) 0xE9, (byte) 0x2F,
            (byte) 0x78, (byte) 0xC7 };
    private static final BigInteger skip1024Modulus;
    private static final BigInteger skip1024Base;
    private static KeyPairGenerator kpg;
    static {
        skip1024Modulus = new BigInteger(1, skip1024ModulusBytes);
        skip1024Base = BigInteger.valueOf(2);
        try {
            kpg = KeyPairGenerator.getInstance("DH");
            DHParameterSpec dhp = new DHParameterSpec(skip1024Modulus,
                    skip1024Base);
            kpg.initialize(dhp);
        } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        }
    }

    /**
     * Create KeyAgreement and generate secret key
     * 
     * @param prk_self
     *            the private key from the user who wants to generate the secret
     *            key
     * @param pbk_peer
     *            the public key from the user whom is to be agree on the secret
     *            key with
     * @param lastPhase
     *            flag which indicates whether or not this is the last phase of
     *            this key agreement
     * @return the secret key
     */
    public static SecretKeySpec agreeSecretKey(PrivateKey prk_self,
            PublicKey pbk_peer, boolean lastPhase) throws Exception {
        KeyAgreement ka = KeyAgreement.getInstance("DH");
        ka.init(prk_self);
        ka.doPhase(pbk_peer, lastPhase);
        byte[] bkey = ka.generateSecret();
        return new SecretKeySpec(bkey, "AES");
    }

    /**
     * Generate a key pair of algorithm "DiffieHellman"
     * 
     * @return the public and private key pair
     */
    public static KeyPair genDHKeyPair() {
        return kpg.genKeyPair();
    }
}

DHTest

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import ggicci.infosec.DiffieHellmanModule;

public class DHTest {

    public static void main(String[] args) {
        KeyPair kp1 = DiffieHellmanModule.genDHKeyPair();
        KeyPair kp2 = DiffieHellmanModule.genDHKeyPair();
        PublicKey pbk1 = kp1.getPublic();
        PublicKey pbk2 = kp2.getPublic();
        PrivateKey prk1 = kp1.getPrivate();
        PrivateKey prk2 = kp2.getPrivate();
        try {
            SecretKeySpec sk1 = DiffieHellmanModule.agreeSecretKey(prk1, pbk2, true);
            SecretKeySpec sk2 = DiffieHellmanModule.agreeSecretKey(prk2, pbk1, true);
            Cipher cipher = Cipher.getInstance(sk1.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, sk1); //-->Exception here:Invalid AES key length: 128 bytes
            byte[] ciphertext = cipher.doFinal("Hello World".getBytes("utf-8"));
            cipher.init(Cipher.DECRYPT_MODE, sk2);
            System.out.println("Decrypted: " + new String(cipher.doFinal(ciphertext), "utf-8"));
            System.out.println("Done");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

1 个答案:

答案 0 :(得分:0)

您正在使用语句byte[] bkey = ka.generateSecret();生成128字节的DiffieHellman密钥的关键数据,但随后将其用作具有new SecretKeySpec(bkey, "AES");

的AES密钥规范的输入

稍后会触发您尝试使用cipher.init(Cipher.ENCRYPT_MODE, sk1);初始化密码时看到的异常,因为AES密钥应该具有16,24或32字节(128,192或256位)的密钥数据,而不是128字节。