Java加密与解密的艺术~AES-GCM-NoPadding实现

来源:Java AES加密和解密_一名可爱的技术搬运工-CSDN博客

AES加密

高级加密标准 (AES,Rijndael)是一种分组密码加密和解密算法,是全球使用最广泛的加密算法。 AES使用128、192或256位的密钥来处理128位的块。

本文向您展示了一些Java AES加密和解密示例:

  • AES字符串加密–(加密和解密字符串)。
  • AES基于密码的加密–(密钥将从给定的密码派生)。
  • AES文件加密。 (基于密码)。

在本文中,我们重点介绍通过Galois Counter Mode(GCM)进行的256位AES加密。

GCM = CTR + Authentication.

进一步阅读 
阅读本– NIST – Galois /计数器模式(GCM)的建议

不要使用AES电子密码本(ECB)模式 
AES ECB模式或AES/ECB/PKCS5Padding (在Java中)在语义上并不安全 – ECB加密的密文可能泄漏有关纯文本的信息。 这是关于为什么不应该使用ECB加密的讨论。

1. Java和AES加密输入。

在AES加密和解密中,我们需要以下输入:

AES加密最佳做法 
不要重复使用具有相同密钥的IV。

1.1 IV(初始值或初始向量),它是随机字节,通常为12个字节或16个字节。 在Java中,我们可以使用SecureRandom生成随机IV。

// 16 bytes IVpublic static byte[] getRandomNonce() {byte[] nonce = new byte[16];new SecureRandom().nextBytes(nonce);return nonce;}// 12 bytes IVpublic static byte[] getRandomNonce() {byte[] nonce = new byte[12];new SecureRandom().nextBytes(nonce);return nonce;}

1.2 AES密钥,即AES-128AES-256 。 在Java中,我们可以使用KeyGenerator生成AES密钥。

// 256 bits AES secret keypublic static SecretKey getAESKey() throws NoSuchAlgorithmException {KeyGenerator keyGen = KeyGenerator.getInstance("AES");keyGen.init(256, SecureRandom.getInstanceStrong());return keyGen.generateKey();}

1.3从给定密码派生的AES密钥。 在Java中,我们可以使用SecretKeyFactoryPBKDF2WithHmacSHA256从给定的密码生成AES密钥。

// AES key derived from a passwordpublic static SecretKey getAESKeyFromPassword(char[] password, byte[] salt)throws NoSuchAlgorithmException, InvalidKeySpecException {SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");// iterationCount = 65536// keyLength = 256KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");return secret;}

我们使用salt来保护彩虹攻击,它也是一个随机字节,我们可以使用相同的1.1 getRandomNonce生成它。

1.4我们将上述方法分组为一个util类,这样我们就不会一次又一次重复相同的代码。

CryptoUtils.java

package com.mkyong.crypto.utils;import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.ArrayList;
import java.util.List;public class CryptoUtils {public static byte[] getRandomNonce(int numBytes) {byte[] nonce = new byte[numBytes];new SecureRandom().nextBytes(nonce);return nonce;}// AES secret keypublic static SecretKey getAESKey(int keysize) throws NoSuchAlgorithmException {KeyGenerator keyGen = KeyGenerator.getInstance("AES");keyGen.init(keysize, SecureRandom.getInstanceStrong());return keyGen.generateKey();}// Password derived AES 256 bits secret keypublic static SecretKey getAESKeyFromPassword(char[] password, byte[] salt)throws NoSuchAlgorithmException, InvalidKeySpecException {SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");// iterationCount = 65536// keyLength = 256KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");return secret;}// hex representationpublic static String hex(byte[] bytes) {StringBuilder result = new StringBuilder();for (byte b : bytes) {result.append(String.format("%02x", b));}return result.toString();}// print hex with block size splitpublic static String hexWithBlockSize(byte[] bytes, int blockSize) {String hex = hex(bytes);// one hex = 2 charsblockSize = blockSize * 2;// better idea how to print this?List<String> result = new ArrayList<>();int index = 0;while (index < hex.length()) {result.add(hex.substring(index, Math.min(index + blockSize, hex.length())));index += blockSize;}return result.toString();}}
  1. package com.mkyong.crypto.utils;

2. AES加密和解密。

AES-GSM是使用最广泛的认证密码。 本示例将在Galois计数器模式(GCM)中使用256位AES加密和解密字符串。

AES-GCM输入:

  • AES密钥(256位)
  • IV – 96位(12字节)
  • 身份验证标签的长度(以位为单位)– 128位(16字节)

2.1在Java中,我们使用AES/GCM/NoPadding表示AES-GCM算法。 对于加密的输出,我们将16字节的IV前缀到加密的文本(密文)之前,因为解密需要相同的IV。

如果IV是众所周知的,可以吗? 
IV公开是可以的,唯一的秘诀就是密钥,对它保密并保密。

本示例将使用AES加密纯文本Hello World AES-GCM ,然后将其解密回原始纯文本。

EncryptorAesGcm.java

package com.mkyong.crypto.encryptor;import com.mkyong.crypto.utils.CryptoUtils;import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;/*** AES-GCM inputs - 12 bytes IV, need the same IV and secret keys for encryption and decryption.* <p>* The output consist of iv, encrypted content, and auth tag in the following format:* output = byte[] {i i i c c c c c c ...}* <p>* i = IV bytes* c = content bytes (encrypted content, auth tag)*/
public class EncryptorAesGcm {private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";private static final int TAG_LENGTH_BIT = 128;private static final int IV_LENGTH_BYTE = 12;private static final int AES_KEY_BIT = 256;private static final Charset UTF_8 = StandardCharsets.UTF_8;// AES-GCM needs GCMParameterSpecpublic static byte[] encrypt(byte[] pText, SecretKey secret, byte[] iv) throws Exception {Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);cipher.init(Cipher.ENCRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv));byte[] encryptedText = cipher.doFinal(pText);return encryptedText;}// prefix IV length + IV bytes to cipher textpublic static byte[] encryptWithPrefixIV(byte[] pText, SecretKey secret, byte[] iv) throws Exception {byte[] cipherText = encrypt(pText, secret, iv);byte[] cipherTextWithIv = ByteBuffer.allocate(iv.length + cipherText.length).put(iv).put(cipherText).array();return cipherTextWithIv;}public static String decrypt(byte[] cText, SecretKey secret, byte[] iv) throws Exception {Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);cipher.init(Cipher.DECRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv));byte[] plainText = cipher.doFinal(cText);return new String(plainText, UTF_8);}public static String decryptWithPrefixIV(byte[] cText, SecretKey secret) throws Exception {ByteBuffer bb = ByteBuffer.wrap(cText);byte[] iv = new byte[IV_LENGTH_BYTE];bb.get(iv);//bb.get(iv, 0, iv.length);byte[] cipherText = new byte[bb.remaining()];bb.get(cipherText);String plainText = decrypt(cipherText, secret, iv);return plainText;}public static void main(String[] args) throws Exception {String OUTPUT_FORMAT = "%-30s:%s";String pText = "Hello World AES-GCM, Welcome to Cryptography!";// encrypt and decrypt need the same key.// get AES 256 bits (32 bytes) keySecretKey secretKey = CryptoUtils.getAESKey(AES_KEY_BIT);// encrypt and decrypt need the same IV.// AES-GCM needs IV 96-bit (12 bytes)byte[] iv = CryptoUtils.getRandomNonce(IV_LENGTH_BYTE);byte[] encryptedText = EncryptorAesGcm.encryptWithPrefixIV(pText.getBytes(UTF_8), secretKey, iv);System.out.println("\n------ AES GCM Encryption ------");System.out.println(String.format(OUTPUT_FORMAT, "Input (plain text)", pText));System.out.println(String.format(OUTPUT_FORMAT, "Key (hex)", CryptoUtils.hex(secretKey.getEncoded())));System.out.println(String.format(OUTPUT_FORMAT, "IV  (hex)", CryptoUtils.hex(iv)));System.out.println(String.format(OUTPUT_FORMAT, "Encrypted (hex) ", CryptoUtils.hex(encryptedText)));System.out.println(String.format(OUTPUT_FORMAT, "Encrypted (hex) (block = 16)", CryptoUtils.hexWithBlockSize(encryptedText, 16)));System.out.println("\n------ AES GCM Decryption ------");System.out.println(String.format(OUTPUT_FORMAT, "Input (hex)", CryptoUtils.hex(encryptedText)));System.out.println(String.format(OUTPUT_FORMAT, "Input (hex) (block = 16)", CryptoUtils.hexWithBlockSize(encryptedText, 16)));System.out.println(String.format(OUTPUT_FORMAT, "Key (hex)", CryptoUtils.hex(secretKey.getEncoded())));String decryptedText = EncryptorAesGcm.decryptWithPrefixIV(encryptedText, secretKey);System.out.println(String.format(OUTPUT_FORMAT, "Decrypted (plain text)", decryptedText));}}
  1. package com.mkyong.crypto.encryptor;

输出量

纯文本: Hello World AES-GCM

Terminal

------ AES GCM Encryption ------
Input (plain text)            :Hello World AES-GCM
Key (hex)                     :603d87185bf855532f14a77a91ec7b025c004bf664e9f5c6e95613ee9577f436
IV  (hex)                     :bdb271ce5235996a0709e09c
Encrypted (hex)               :bdb271ce5235996a0709e09c2d03eefe319e9329768724755c56291aecaef88cd1e6bdf72b8c7b54d75a94e66b0cd3
Encrypted (hex) (block = 16)  :[bdb271ce5235996a0709e09c2d03eefe, 319e9329768724755c56291aecaef88c, d1e6bdf72b8c7b54d75a94e66b0cd3]------ AES GCM Decryption ------
Input (hex)                   :bdb271ce5235996a0709e09c2d03eefe319e9329768724755c56291aecaef88cd1e6bdf72b8c7b54d75a94e66b0cd3
Input (hex) (block = 16)      :[bdb271ce5235996a0709e09c2d03eefe, 319e9329768724755c56291aecaef88c, d1e6bdf72b8c7b54d75a94e66b0cd3]
Key (hex)                     :603d87185bf855532f14a77a91ec7b025c004bf664e9f5c6e95613ee9577f436
Decrypted (plain text)        :Hello World AES-GCM
  1. ------ AES GCM Encryption ------

纯文本: Hello World AES-GCM, Welcome to Cryptography!

Terminal

------ AES GCM Encryption ------
Input (plain text)            :Hello World AES-GCM, Welcome to Cryptography!
Key (hex)                     :ddc24663d104e1c2f81f11aef98156503dafdc435f81e3ac3d705015ebab095c
IV  (hex)                     :b05d6aedf023f73b9e1e2d11
Encrypted (hex)               :b05d6aedf023f73b9e1e2d11f6f5137d971aea8c5cdd5b045e0960eb4408e0ee4635cccc2dfeec2c13a89bd400f659be82dc2329e9c36e3b032f38bd42296a8495ac840b0625c097d9
Encrypted (hex) (block = 16)  :[b05d6aedf023f73b9e1e2d11f6f5137d, 971aea8c5cdd5b045e0960eb4408e0ee, 4635cccc2dfeec2c13a89bd400f659be, 82dc2329e9c36e3b032f38bd42296a84, 95ac840b0625c097d9]------ AES GCM Decryption ------
Input (hex)                   :b05d6aedf023f73b9e1e2d11f6f5137d971aea8c5cdd5b045e0960eb4408e0ee4635cccc2dfeec2c13a89bd400f659be82dc2329e9c36e3b032f38bd42296a8495ac840b0625c097d9
Input (hex) (block = 16)      :[b05d6aedf023f73b9e1e2d11f6f5137d, 971aea8c5cdd5b045e0960eb4408e0ee, 4635cccc2dfeec2c13a89bd400f659be, 82dc2329e9c36e3b032f38bd42296a84, 95ac840b0625c097d9]
Key (hex)                     :ddc24663d104e1c2f81f11aef98156503dafdc435f81e3ac3d705015ebab095c
Decrypted (plain text)        :Hello World AES-GCM, Welcome to Cryptography!
  1. ------ AES GCM Encryption ------

3.基于AES密码的加密和解密。

对于基于密码的加密,我们可以使用定义为RFC 8018的基于密码的密码规范(PKCS)从给定的密码生成密钥。

对于PKCS输入:

  • 密码,您提供。
  • 盐–至少64位(8字节)随机字节。
  • 迭代计数–建议最小迭代计数为1,000。

什么是盐和迭代计数?

  • salt会为给定的密码生成广泛的密钥集。 例如,如果盐是128位,则每个密码将有多达2 ^ 128个密钥。 因此,它增加了彩虹攻击的难度。 此外,攻击者为一个用户的密码构建的彩虹表对于另一用户变得毫无用处。
  • iteration count增加了从密码生成密钥的成本,因此增加了难度并减慢了攻击速度。

3.1对于加密的输出,我们在密文前面加上12 bytes IVpassword salt ,因为我们需要相同的IV和密码盐(用于密钥)进行解密。 此外,我们使用Base64编码器将加密的文本编码为字符串表示形式,以便我们可以以字符串格式(字节数组)发送加密的文本或密文。

如果密码盐是众所周知的,可以吗? 
与IV相同,并且可以公开知道密码盐,唯一的秘诀就是密钥,并对其进行保密和保密。

EncryptorAesGcmPassword.java

package com.mkyong.crypto.encryptor;import com.mkyong.crypto.utils.CryptoUtils;import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;/*** AES-GCM inputs - 12 bytes IV, need the same IV and secret keys for encryption and decryption.* <p>* The output consist of iv, password's salt, encrypted content and auth tag in the following format:* output = byte[] {i i i s s s c c c c c c ...}* <p>* i = IV bytes* s = Salt bytes* c = content bytes (encrypted content)*/
public class EncryptorAesGcmPassword {private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";private static final int TAG_LENGTH_BIT = 128; // must be one of {128, 120, 112, 104, 96}private static final int IV_LENGTH_BYTE = 12;private static final int SALT_LENGTH_BYTE = 16;private static final Charset UTF_8 = StandardCharsets.UTF_8;// return a base64 encoded AES encrypted textpublic static String encrypt(byte[] pText, String password) throws Exception {// 16 bytes saltbyte[] salt = CryptoUtils.getRandomNonce(SALT_LENGTH_BYTE);// GCM recommended 12 bytes iv?byte[] iv = CryptoUtils.getRandomNonce(IV_LENGTH_BYTE);// secret key from passwordSecretKey aesKeyFromPassword = CryptoUtils.getAESKeyFromPassword(password.toCharArray(), salt);Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);// ASE-GCM needs GCMParameterSpeccipher.init(Cipher.ENCRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH_BIT, iv));byte[] cipherText = cipher.doFinal(pText);// prefix IV and Salt to cipher textbyte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length).put(iv).put(salt).put(cipherText).array();// string representation, base64, send this string to other for decryption.return Base64.getEncoder().encodeToString(cipherTextWithIvSalt);}// we need the same password, salt and iv to decrypt itprivate static String decrypt(String cText, String password) throws Exception {byte[] decode = Base64.getDecoder().decode(cText.getBytes(UTF_8));// get back the iv and salt from the cipher textByteBuffer bb = ByteBuffer.wrap(decode);byte[] iv = new byte[IV_LENGTH_BYTE];bb.get(iv);byte[] salt = new byte[SALT_LENGTH_BYTE];bb.get(salt);byte[] cipherText = new byte[bb.remaining()];bb.get(cipherText);// get back the aes key from the same password and saltSecretKey aesKeyFromPassword = CryptoUtils.getAESKeyFromPassword(password.toCharArray(), salt);Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);cipher.init(Cipher.DECRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(TAG_LENGTH_BIT, iv));byte[] plainText = cipher.doFinal(cipherText);return new String(plainText, UTF_8);}public static void main(String[] args) throws Exception {String OUTPUT_FORMAT = "%-30s:%s";String PASSWORD = "this is a password";String pText = "AES-GSM Password-Bases encryption!";String encryptedTextBase64 = EncryptorAesGcmPassword.encrypt(pText.getBytes(UTF_8), PASSWORD);System.out.println("\n------ AES GCM Password-based Encryption ------");System.out.println(String.format(OUTPUT_FORMAT, "Input (plain text)", pText));System.out.println(String.format(OUTPUT_FORMAT, "Encrypted (base64) ", encryptedTextBase64));System.out.println("\n------ AES GCM Password-based Decryption ------");System.out.println(String.format(OUTPUT_FORMAT, "Input (base64)", encryptedTextBase64));String decryptedText = EncryptorAesGcmPassword.decrypt(encryptedTextBase64, PASSWORD);System.out.println(String.format(OUTPUT_FORMAT, "Decrypted (plain text)", decryptedText));}}
  1. package com.mkyong.crypto.encryptor;

输出量

Terminal

------ AES GCM Password-based Encryption ------
Input (plain text)            :AES-GSM Password-Bases encryption!
Encrypted (base64)            :KmrvjnMusJTQo/hB7T5BvlQpvi3bVbdjpZP51NT7I/enrIfSQuDfSK6iXgdPzvUP2IE54mwrKiyHqMkG8224lRZ9tXHcclmdh98I8b3B------ AES GCM Password-based Decryption ------
Input (base64)                :KmrvjnMusJTQo/hB7T5BvlQpvi3bVbdjpZP51NT7I/enrIfSQuDfSK6iXgdPzvUP2IE54mwrKiyHqMkG8224lRZ9tXHcclmdh98I8b3B
Decrypted (plain text)        :AES-GSM Password-Bases encryption!
  1. ------ AES GCM Password-based Encryption ------

3.2如果密码不匹配,Java会抛出AEADBadTagException: Tag mismatch!

// change the password to something elseString decryptedText = EncryptorAesGcmPassword.decrypt(encryptedTextBase64, "other password");System.out.println(String.format(OUTPUT_FORMAT, "Decrypted (plain text)", decryptedText));
  1. // change the password to something else

输出量

Terminal

Exception in thread "main" javax.crypto.AEADBadTagException: Tag mismatch!at java.base/com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:623)at java.base/com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1118)at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1055)at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:855)at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2207)at com.mkyong.crypto.encryptor.EncryptorAesGcmPassword.decrypt(EncryptorAesGcmPassword.java:88)at com.mkyong.crypto.encryptor.EncryptorAesGcmPassword.main(EncryptorAesGcmPassword.java:109)
  1. Exception in thread "main" javax.crypto.AEADBadTagException: Tag mismatch!

4. AES文件加密和解密。

此示例是基于AES密码的文件加密。 想法是相同的,但是我们需要一些IO类来处理资源或文件。

这是resources文件夹中的文本文件。

readme.txt

This is line 1.
This is line 2.
This is line 3.
This is line 4.
This is line 5.
This is line 9.
This is line 10.
  1. This is line 1.

4.1此示例类似于3.1 EncryptorAesGcmPassword.java ,但有一些小的更改,例如返回byte[]而不是base64编码的字符串。

public static byte[] encrypt(byte[] pText, String password) throws Exception {//...// prefix IV and Salt to cipher textbyte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length).put(iv).put(salt).put(cipherText).array();// it works, even if we save the based64 encoded string into a file.// return Base64.getEncoder().encodeToString(cipherTextWithIvSalt);// we save the byte[] into a file.return cipherTextWithIvSalt;}
  1. public static byte[] encrypt(byte[] pText, String password) throws Exception {

添加encryptFiledecryptFile工作与文件。

public static void encryptFile(String fromFile, String toFile, String password) throws Exception {// read a normal txt filebyte[] fileContent = Files.readAllBytes(Paths.get(ClassLoader.getSystemResource(fromFile).toURI()));// encrypt with a passwordbyte[] encryptedText = EncryptorAesGcmPasswordFile.encrypt(fileContent, password);// save a filePath path = Paths.get(toFile);Files.write(path, encryptedText);}public static byte[] decryptFile(String fromEncryptedFile, String password) throws Exception {// read a filebyte[] fileContent = Files.readAllBytes(Paths.get(fromEncryptedFile));return EncryptorAesGcmPasswordFile.decrypt(fileContent, password);}
  1. public static void encryptFile(

4.2从类路径中读取以上readme.txt文件,对其进行加密,然后将加密的数据保存到新文件c:\test\readme.encrypted.txt 。

String password = "password123";String fromFile = "readme.txt"; // from resources folderString toFile = "c:\\test\\readme.encrypted.txt";// encrypt fileEncryptorAesGcmPasswordFile.encryptFile(fromFile, toFile, password);
  1. String password = "password123";

输出量

AES文件加密

4.3读取加密的文件,解密并打印输出。

String password = "password123";String toFile = "c:\\test\\readme.encrypted.txt";// decrypt filebyte[] decryptedText = EncryptorAesGcmPasswordFile.decryptFile(toFile, password);String pText = new String(decryptedText, UTF_8);System.out.println(pText);
  1. String password = "password123";

输出量

Terminal

This is line 1.
This is line 2.
This is line 3.
This is line 4.
This is line 5.
This is line 9.
This is line 10.
  1. This is line 1.

PS AES图像加密是相同的概念。

下载源代码

$ git clone https://github.com/mkyong/core-java

$ cd java-crypto

让我知道文章是否需要改进。 谢谢。

参考文献

  • 维基百科–密码JavaDoc
  • 维基百科–密码块链接(CBC)
  • 维基百科-Galois / Counter Mode(GCM)
  • Oracle – KeyGenerator算法JavaDoc
  • Java –如何生成随机的12个字节?
  • 为什么不应该使用ECB加密?
  • Spring Security加密模块
  • 维基百科– PBKDF2
  • RFC 8018 – PKCS
  • Java –如何连接和分割字节数组
  • Java安全标准算法名称
  • NIST – Galois /计数器模式(GCM)的建议

翻译自: Java AES encryption and decryption - Mkyong.com 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/496436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STL bitset用法总结

c bitset类用法&#xff1a;http://blog.csdn.net/qll125596718/article/details/6901935 C 参考&#xff1a;http://www.cplusplus.com/reference/bitset/bitset/ http://happyboy200032.blog.163.com/blog/static/46903113201291252033712/ http://blog.csdn.net/e68948…

全球智能制造发展现状及前景预测 工业机器人引领行业发展

来源&#xff1a;前瞻产业研究院全球智能制造发展历程智能制造是伴随信息技术的不断普及而逐步发展起来的。1988年&#xff0c;美国纽约大学的怀特教授&#xff08;P&#xff0e;K&#xff0e;Wright&#xff09;和卡内基梅隆大学的布恩教授&#xff08;D&#xff0e;A&#xf…

vb整合多个excel表格到一张_VB合并工作表下载

VB合并工作表最新版是一款功能强大且界面简洁美观的excel表格合并工具&#xff0c;VB合并工作表最新版操作简便且易上手可以运行稳定&#xff0c;能够为大家解决合成打开卡顿等问题&#xff0c;实现多薄多表合并&#xff0c;VB合并工作表官方版还可以有效轻松提升工作效率。软件…

sql server 模糊查询

模糊查询——like select * from 表名where id like %2%select * from 表名where id like d%% escape d 查询时&#xff0c;字段中的内容并不一定与查询内容完全匹配&#xff0c;只要字段中含有这些内容 模糊查询&#xff0d;&#xff0d;is null select * from 表名 where na…

java.security.InvalidKeyException: Illegal key size

来源&#xff1a;https://blog.csdn.net/dling8/article/details/84061948 今天在使用idea打包maven项目时&#xff0c;出现这个错误&#xff1a;java.security.InvalidKeyException: Illegal key size。&#xff08;测试也可能会出现这个问题&#xff09;貌似是因为加密出现了…

NAT 详解

NAT技术(一、二、三、四、五) 系列&#xff1a;https://blog.51cto.com/wwwcisco/category1.html CCNA学习笔记之NAT&#xff1a;http://sweetpotato.blog.51cto.com/533893/1392884 网络地址转换NAT原理及应用&#xff1a;http://blog.csdn.net/xiaofei0859/article/details/…

趋势|人工智能疯狂洗脑,最聪明的钱已转向这16项技术

来源&#xff1a;21世纪商业评论 摘要&#xff1a;Gartner今年发布的技术成熟曲线中&#xff0c;出现了16个处于上升阶段的新兴技术&#xff0c;这些正在崛起的技术&#xff0c;或将成为企业未来几年战略性技术趋势的热点。不久前&#xff0c;信息技术研究公司Gartner发布了201…

OSI七层协议模型和TCP/IP四层模型

TCP/IP 协议栈及 OSI 参考模型详解&#xff1a;https://blog.csdn.net/guobing19871024/article/details/79415846 OSI七层网络模型&#xff0c;TCP/IP四层网络模型与网络协议解析&#xff1a;http://www.360doc.com/content/13/1123/17/7267612_331579105.shtml [网络必学]TCP…

基于java处理ofd格式文件

一、ofd格式介绍 国家发布过一份关于ofd编码格式的资料&#xff0c;本来我想传上去的发现资源重复了&#xff0c;你们可以找找看&#xff0c;没有的话留个邮箱&#xff0c;我看到会发给你们的 ofd本质上其实是一个压缩文件&#xff0c;咱们把他当做一个压缩包来处理就好了&…

一文带你读懂深度学习:AI 认识世界的方式如同小孩

来源&#xff1a;36氪摘要&#xff1a;搞清楚儿童的大脑究竟是如何运转的&#xff0c;然后设计出一个电子版本能够同样有效地运转&#xff0c;可能需要计算机科学家们几十年的努力。如果你经常花时间和小孩子待在一起的话&#xff0c;你会不由得思考小孩子怎么能够学习得如此之…

微信支付PKIX path building failed

异常信息 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification p ath to requested targetat sun.security.ssl…

Nvidia黄仁勋发布了全球最大GPU

来源&#xff1a;凤凰科技花子健摘要&#xff1a;有竞争在&#xff0c;更大的惊喜才有可能会到来。北京时间3月28日凌晨00:00&#xff0c;英伟达GTC 2018&#xff08;GPU Technology Conference 2018&#xff0c;以下简称GTC&#xff09;在美国圣何塞举行。英伟达再一次在提升计…

计算机网络(4):网络层

网络层提供的两种服务 虚电路服务&#xff08;Virtual Circuit Service&#xff09;和数据报服务&#xff08;Datagram Service&#xff09;是在网络层&#xff08;第三层&#xff09;提供的两种不同的通信服务。它们主要区别在于建立连接的方式和数据传输的方式。 虚电路服务…

指针数组下标JAVA_C语言中下标与指针的转换以及指向指针的指针的例子

下标到指针之间和转换以下的程序做了什么。#include int main(){int a[3][3] {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};int i 0;int j 0;for(i 0; i<3; i){for(j0; j<3; j){printf("%d\n", *(*(ai)j));}}}打印了数组中的每个元素&#xff1a;指向指针的指针#inc…

windows 下 Graphviz 安装及入门教程以及 PlantUML

From&#xff1a;http://m.blog.csdn.net/lanchunhui/article/details/49472949 开源工具---使用简单的文字描述画UML图之PlantUML官网&#xff1a;http://plantuml.com PlantUML 支持的工具&#xff1a;http://plantuml.com/running PlantUML语言参考手册中文版.pdf&#xff…

GTC2018八大热点:发布多项黑科技,联合芯片巨头ARM打造AI芯片专用IP

来源&#xff1a;人工智能和大数据丨公众号一年一度的GTC至今已经迎来了第十个年头&#xff0c;虽然它每年或多或少的给网友一些“失望”&#xff0c;但它也终究是代表着GPU行业的高水平技术大会。那么&#xff0c;今年的GTC大会&#xff0c;英伟达又给业界带来了哪些惊喜呢&am…

WPF and Silverlight 学习笔记(十二):WPF Panel内容模型、Decorator内容模型及其他...

由于园子里昨天使用Live Writer上传出现问题&#xff0c;昨天只能使用Web上的文本编辑器上传本文&#xff0c;造成代码、内容等格式的错误&#xff0c;现重发本文。 一、Panel内容模型 Panel内容模型指从System.Windows.Controls.Panel继承的控件&#xff0c;这些控件都是容器&…

Source Insight 教程

From&#xff1a;http://www.cnblogs.com/ningskyer/articles/4038501.html 最经典的Source_Insight完整使用教程&#xff1a;https://wenku.baidu.com/view/6f7dbe87caaedd3382c4d3e4.html Source Insight 使用方法及技巧&#xff1a;https://wenku.baidu.com/view/ddd28da…

GIS最新热点以及未来发展热门

来源&#xff1a;测绘地信、知乎用户测绘小河马GIS是空间技术和信息技术的交叉学科&#xff0c;相关领域的研究热点都有可能成为GIS的发展趋势。GIS的技术环节无外乎数据获取、数据分析、数据呈现三个方面&#xff0c;从近年的发展情况看&#xff0c;GIS可能在这三个方面都有着…

Spring Data JPA 从入门到精通~查询结果的处理

参数选择&#xff08;Sort/Pageable&#xff09;分页和排序 特定类型的参数&#xff0c;Pageable 并动态 Sort 地将分页和排序应用于查询 案例&#xff1a;在查询方法中使用 Pageable、Slice 和 Sort。 Page<User> findByLastname(String lastname, Pageable pageable)…