📜  Java的对称加密密码术

📅  最后修改于: 2021-04-17 02:24:08             🧑  作者: Mango

密码学是对从未授权实体中保护数据的各种技术的研究。在计算机科学中,我们尝试开发保护敏感数据的策略和实践。大多数密码学都涉及用于保护数据的非常先进的数学功能。为密码学开发的算法的唯一目的是隐藏攻击者或中间人的数据。在本文中,我们将了解密码学中称为对称加密的概念。

在进入概念之前,让我们首先了解密码学中涉及的一些关键术语。他们是:

  • 文本:纯文本是通过加密加密算法从视图中隐藏的原始消息或数据。
  • 密文:给定密钥和纯文本时,它是加密操作的输出。它也是馈送给Decryption函数的数据。
  • 密钥:当用纯文本输入到加密函数产生密文时,密钥是一条数据或相关的数据对。由于算法是公开可用的,因此必须确保密钥的安全。
  • 盐:盐是添加到哈希函数的随机数据,在输出中提供更大的熵,从而降低了攻击发生的可能性。良好的加密散列应始终使用盐。

现在,让我们了解加密中涉及的组件的功能。

  • 数字签名:数字签名是一种函数,可验证远程收到的消息的真实性。通过使用私钥对消息签名,使用公共密钥对消息进行解密可以确认发件人的真实性。
  • 加密:加密是获取纯文本并将其转换为密文的过程,以后可以使用适当的密钥再次将其转换回原始数据。它可以通过共享密钥或非对称密钥对来完成。
  • 散列:散列允许我们将任意大小的字节集映射为相对唯一的字节集的有限大小。它是一种映射数据的单向数学函数。

Java密码学体系结构

JCA(Java密码体系结构)是Java加密,解密,散列,安全随机性以及其他几个允许我们通过Java编程执行加密功能的引擎的灵魂。以下是此体系结构中涉及的一些基本概念。

  • 安全随机:此引擎用于创建加密强度高的随机数。安全随机性是Java良好的加密操作的基本要求。它可用于种子或钥匙。
  • 消息摘要:此引擎用于生成加密安全的哈希。摘要是一个哈希函数,它接受可变长度的输入并产生固定长度的输出。
  • 签名:它是创建和验证数字签名的引擎。数字签名是唯一的,它们结合使用哈希和公钥加密非对称操作来创建唯一的值或签名。
  • 密码:它是提供加密操作的引擎。密码同时支持非对称和对称操作。密码还支持流和分组密码。

加密:加密是使用密钥隐藏明文数据的过程,该过程会产生密文。如果没有用于生成密文的密钥,则密文变得难以阅读。只有授权实体才能阅读原始文本。让我们了解加密的目标。在接下来的插图中,我们将“ A”视为发送方,将“ B”视为接收方。

  • 机密性:也就是所谓的隐私,即假设算法和密钥仅由“ A”和“ B”共享,则“ A”发送给“ B”的消息仅可由“ B”读取。

  • 完整性: “ A”发送的数据应接收到“ B”,而不受不良行为者的任何修改或任何中间人攻击。

  • 身份验证:这是使用密码学验证或识别用户身份的过程。例如,如果“ A”将消息发送到“ B”,则真实性证明该消息仅由“ A”发送。

  • 不可否认:这是一种证明来自“ A”的消息,并且“ B”可以相信来自“ A”的消息,并且“ A”可以确认他已发送消息。

对称加密:对称加密或共享密钥加密是一种加密方法,其中所涉及的双方都共享一个标准密钥。双方必须对该公用密钥保密。例如,“ A”将使用共享密钥“ K”对邮件进行加密,然后“ B”仅可使用“ K”对加密的邮件进行解密。

非对称加密:非对称加密或公钥/私钥对加密基于数学上相关的两个密钥(即,一个要加密而另一个要解密)的概念。例如,“ A”将创建一个公钥和私钥,并且他将与所有人共享该公钥。他可以使用私钥加密消息,然后将其发送到“ B”。 “ B”可以使用“ A”的公开密钥解密消息,该公开密钥是公开可用的。如果“ B”想要向“ A”发送私人消息,则他可以使用“ A”的公共密钥加密数据,然后“ B”可以使用其私人密钥解密数据。

实施对称加密

为了实现对称加密,我们需要一个共享密钥。我们将生成一个共享密钥,但是在此之前,我们需要了解一些类和函数。他们是:

  1. SecureRandom类:此类有助于生成安全的随机数。以下是该类的构造函数详细信息:
    • SecureRandom()使用默认随机数算法构造一个随机安全数生成器。
    • public SecureRandom(byte [] seed) SecureRandom实例使用指定的种子字节作为种子。此构造函数所需的参数是种子。
    • 受保护的SecureRandom(SecureRandomSpi secureRandomSpi,提供程序提供者)。此构造函数的参数是secureRandomSpi,它引用SecureRandom实现。和提供者,代表提供者。

    以下是此类的方法。

    • getInstance():返回一个SecureRandom对象,并应用随机数生成算法。此方法的语法为:
      公共静态SecureRandom getInstance(String algo)抛出NoSuchAlgorithmException

    • getProvider():此方法返回一个SecureRandom对象。此方法的语法为:
    • getAlgorithm():此方法返回由SecureRandom对象实现的算法名称。此方法的语法为:
    • setSeed():此方法重新设置随机对象的种子。给定的种子将被添加,而不是替换现有的种子。从而帮助随机性。此方法的语法为:
    • getSeed():此方法返回给定数量的种子字节,该种子字节是使用种子生成算法计算得出的。此方法的语法为:
  2. KeyGenerator类:此类提供密钥生成器的功能。以下是带有密钥大小的标准KeyGenerator算法。
    • AES(128)
    • DES(56)
    • DESede(168)
    • HmacSHA1
    • HmacSHA256

生成对称密钥的方法:可以遵循以下步骤来生成对称密钥。

  • 使用Java中的SecureRandom类创建一个秘密密钥,该密钥用于生成随机数。这将用于加密和解密数据。密钥可以创建为:
  • KeyGenerator类将提供一个getInstance()方法,该方法可用于传递表示密钥生成算法的字符串变量。它返回一个KeyGenerator对象。在此示例中,我们在这里使用AES算法。可以实现为:
  • 现在,生成了密钥,如果我们希望实际看到生成的密钥(它是一个对象),我们可以使用DatatypeConverter将其转换为十六进制格式

下面是上述方法的实现:

// Java program to generate
// a symmetric key
import java.security
    .SecureRandom;
  
import javax.crypto
    .KeyGenerator;
import javax.crypto.SecretKey;
import javax.xml.bind
    .DatatypeConverter;
  
// Class to create a
// symmetric key
public class symmetric {
  
    public static final String AES
        = "AES";
  
    // Function to create a secret key
    public static SecretKey createAESKey()
        throws Exception
    {
  
        // Creating a new instance of
        // SecureRandom class.
        SecureRandom securerandom
            = new SecureRandom();
  
        // Passing the string to
        // KeyGenerator
        KeyGenerator keygenerator
            = KeyGenerator.getInstance(AES);
  
        // Initializing the KeyGenerator
        // with 256 bits.
        keygenerator.init(256, securerandom);
        SecretKey key = keygenerator.generateKey();
        return key;
    }
  
    // Driver code
    public static void main(String args[])
        throws Exception
    {
        SecretKey Symmetrickey
            = createAESKey();
        System.out.println("Output");
        System.out.print("The Symmetric Key is :"
                         + DatatypeConverter.printHexBinary(
                               Symmetrickey.getEncoded()));
    }
}

输出:

使用对称密钥的加密和解密:可以按照以下步骤进行加密和解密。

  • 创建避免在加密过程中重复所需的初始化向量。这基本上是一个随机数。
  • 密码类提供了两种功能:加密和解密。它可以用来指定两种不同的模式。
  • 最后,在密码上调用doFinal()方法,该密码以单部分操作对数据进行加密或解密,或者完成多部分操作并返回字节数组。

以下是对称加密和解密的实现。在这里,我们使用AES(高级加密标准)算法来执行加密。

// Java program to implement the
// encryption and decryption
  
import java.security.SecureRandom;
import java.util.Scanner;
  
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec
    .IvParameterSpec;
import javax.xml.bind
    .DatatypeConverter;
  
// Creating the symmetric
// class which implements
// the symmetric
public class symmetric {
  
    private static final String AES
        = "AES";
  
    // We are using a Block cipher(CBC mode)
    private static final String AES_CIPHER_ALGORITHM
        = "AES/CBC/PKCS5PADDING";
  
    private static Scanner message;
  
    // Function to create a
    // secret key
    public static SecretKey createAESKey()
        throws Exception
    {
        SecureRandom securerandom
            = new SecureRandom();
        KeyGenerator keygenerator
            = KeyGenerator.getInstance(AES);
  
        keygenerator.init(256, securerandom);
        SecretKey key
            = keygenerator.generateKey();
  
        return key;
    }
  
    // Function to initialize a vector
    // with an arbitrary value
    public static byte[] createInitializationVector()
    {
  
        // Used with encryption
        byte[] initializationVector
            = new byte[16];
        SecureRandom secureRandom
            = new SecureRandom();
        secureRandom.nextBytes(initializationVector);
        return initializationVector;
    }
  
    // This function takes plaintext,
    // the key with an initialization
    // vector to convert plainText
    // into CipherText.
    public static byte[] do_AESEncryption(
        String plainText,
        SecretKey secretKey,
        byte[] initializationVector)
        throws Exception
    {
        Cipher cipher
            = Cipher.getInstance(
                AES_CIPHER_ALGORITHM);
  
        IvParameterSpec ivParameterSpec
            = new IvParameterSpec(
                initializationVector);
  
        cipher.init(Cipher.ENCRYPT_MODE,
                    secretKey,
                    ivParameterSpec);
  
        return cipher.doFinal(
            plainText.getBytes());
    }
  
    // This function performs the
    // reverse operation of the
    // do_AESEncryption function.
    // It converts ciphertext to
    // the plaintext using the key.
    public static String do_AESDecryption(
        byte[] cipherText,
        SecretKey secretKey,
        byte[] initializationVector)
        throws Exception
    {
        Cipher cipher
            = Cipher.getInstance(
                AES_CIPHER_ALGORITHM);
  
        IvParameterSpec ivParameterSpec
            = new IvParameterSpec(
                initializationVector);
  
        cipher.init(
            Cipher.DECRYPT_MODE,
            secretKey,
            ivParameterSpec);
  
        byte[] result
            = cipher.doFinal(cipherText);
  
        return new String(result);
    }
  
    // Driver code
    public static void main(String args[])
        throws Exception
    {
        SecretKey Symmetrickey
            = createAESKey();
  
        System.out.println(
            "The Symmetric Key is :"
            + DatatypeConverter.printHexBinary(
                  Symmetrickey.getEncoded()));
  
        byte[] initializationVector
            = createInitializationVector();
  
        String plainText
            = "This is the message "
              + "I want To Encrypt.";
  
        // Encrypting the message
        // using the symmetric key
        byte[] cipherText
            = do_AESEncryption(
                plainText,
                Symmetrickey,
                initializationVector);
  
        System.out.println(
            "The ciphertext or "
            + "Encrypted Message is: "
            + DatatypeConverter.printHexBinary(
                  cipherText));
  
        // Decrypting the encrypted
        // message
        String decryptedText
            = do_AESDecryption(
                cipherText,
                Symmetrickey,
                initializationVector);
  
        System.out.println(
            "Your original message is: "
            + decryptedText);
    }
}

输出: