lua加密教程_我们相信加密! 教程
lua加密教程
许多人认为加密是一个复杂的主题,这很难理解。 可以实现其某些方面,但是每个人都可以理解它在更高层次上的工作方式。
这就是我要处理的这篇文章。 用简单的术语解释它是如何工作的,然后使用一些代码。
是的,我们信任加密。 信任是什么意思? 我们相信,我们的消息仅由授权方读取(机密性),在传输过程中不会更改(完整性),并且确实由我们认为已发送(身份验证)的人发送。
维基百科为加密提供了一个很好的定义:“是以一种只有授权方才能访问的方式对消息或信息进行编码的过程”。
因此,加密通过使用密钥(密码)将我们的消息转换为难以理解的密钥(密文),该密钥只能从授权方转回原始密钥。
有两种类型的加密方案, 对称和非对称密钥加密。
在对称加密中,相同的密钥用于加密和解密消息。 我们希望访问该消息的用户必须具有密钥,但不能有其他密钥,否则我们的消息将受到损害。
我对非对称密钥加密很感兴趣。 非对称密钥方案使用两个密钥:私有密钥和公共密钥。 这些键对很特殊。 它们之所以特别是因为它们是使用称为非对称算法的一类算法生成的。 实际的算法不在此讨论范围之内,但是在本教程的后面,我们将使用RSA。
您现在需要知道的是,这些键具有以下属性。 使用以下内容加密的消息:
看起来足够简单吧? 那么它在实践中如何使用? 让我们考虑两个朋友,爱丽丝和鲍勃。 他们有自己的一对公钥和私钥,并且希望在聊天中保持私密性。 他们每个人都公开提供他们的公钥,但是要小心地隐藏他们的私钥。
当爱丽丝只想发送一条消息以从鲍勃那里读取时,她使用鲍勃的公钥对消息进行加密。 然后Bob和只有他才能使用他的私钥解密消息。 而已。
这就解释了第一个属性的使用,但是第二个呢? 似乎没有理由使用我们的私钥进行加密。 好吧,有。 我们怎么知道爱丽丝是那个发信息的人? 如果我们可以使用Alice的公钥解密消息,则可以确保使用Alice的私钥进行加密,因此确实是从Alice发送的。 简单的说:
使用公钥,以便人们只能将内容发送给您,而私钥则用于证明您的身份。
因此,我们可以使用公钥来确保机密性 ,并使用私钥来保证真实性 。 那么诚信呢? 为了实现这一点,我们使用加密哈希。 良好的加密散列可接收输入消息并生成具有以下属性的消息摘要:
如果我们要确保接收到的消息在过渡期间没有受到破坏,则将哈希值与加密消息一起发送。 在接收端,我们使用相同的算法对解密的消息进行哈希处理,然后进行比较以确保哈希值完全匹配。 如果它们是,那么我们可以确信消息没有被更改。
这些散列或消息摘要也具有其他用途。 您会看到,有时Bob做出承诺,然后否认自己曾经做过。 我们要检查他。 用奇特的术语来说,这称为不可抵赖 ,它可以防止各方拒绝发送消息。 数字签名是众所周知的应用。
在继续学习并享受代码乐趣之前,让我再介绍几件事。
现在,让我们使用一个教程来帮助所有这些问题。我们将允许三个人爱丽丝,鲍勃和保罗与机密性,完整性和身份验证进行通信(进一步将它们称为CIA)。 完整的代码可以在github上找到 。
该项目有几个依赖项,如下所示:
我们将从EncryptedMessage类开始,它将提供确保CIA所需的所有信息。 该消息将包含用于机密性的实际加密消息,该消息的哈希将用于确保发送者的完整性和身份,原始和加密后用于身份验证。 我们还提供了一种破坏消息有效负载的方法,因此我们可以针对摘要测试验证(稍后会进行介绍)。
package com.tasosmartidis.tutorial.encryption.domain;import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter;@AllArgsConstructor @Getter @EqualsAndHashCode public class EncryptedMessage {private String encryptedMessagePayload;private String senderId;private String encryptedSenderId;private String messageDigest;// FOR DEMO PURPOSES ONLY!public void compromiseEncryptedMessagePayload(String message) {this.encryptedMessagePayload = message;}@Overridepublic String toString() {return encryptedMessagePayload;} }现在让我们进入加密部分。 我们将创建一个独立于实际非对称算法和密钥长度的基本加密器类。 它将创建密钥和密码,具有用于加密和解密文本以及提供对密钥的访问的方法。 看起来像这样:
package com.tasosmartidis.tutorial.encryption.encryptor;import com.tasosmartidis.tutorial.encryption.domain.EncryptorProperties; import com.tasosmartidis.tutorial.encryption.exception.DecryptionException; import com.tasosmartidis.tutorial.encryption.exception.EncryptionException; import com.tasosmartidis.tutorial.encryption.exception.EncryptorInitializationException; import com.tasosmartidis.tutorial.encryption.exception.UnauthorizedForDecryptionException; import org.apache.commons.codec.binary.Base64;import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.nio.charset.StandardCharsets; import java.security.*;public class BaseAsymmetricEncryptor {private final KeyPairGenerator keyPairGenerator;private final KeyPair keyPair;private final Cipher cipher;private final EncryptorProperties encryptorProperties;protected BaseAsymmetricEncryptor(EncryptorProperties encryptorProperties) {this.encryptorProperties = encryptorProperties;this.keyPairGenerator = generateKeyPair();this.keyPairGenerator.initialize(this.encryptorProperties.getKeyLength());this.keyPair = this.keyPairGenerator.generateKeyPair();this.cipher = createCipher(encryptorProperties);}protected PrivateKey getPrivateKey() {return this.keyPair.getPrivate();}public PublicKey getPublicKey() {return this.keyPair.getPublic();}protected String encryptText(String textToEncrypt, Key key) {try {this.cipher.init(Cipher.ENCRYPT_MODE, key);return Base64.encodeBase64String(cipher.doFinal(textToEncrypt.getBytes(StandardCharsets.UTF_8)));} catch (InvalidKeyException | BadPaddingException | IllegalBlockSizeException ex) {throw new EncryptionException("Encryption of message failed", ex);}}protected String decryptText(String textToDecrypt, Key key) {try {this.cipher.init(Cipher.DECRYPT_MODE, key);return new String(cipher.doFinal(Base64.decodeBase64(textToDecrypt)), StandardCharsets.UTF_8);}catch (InvalidKeyException | BadPaddingException ex){throw new UnauthorizedForDecryptionException("Not authorized to decrypt message", ex);} catch (IllegalBlockSizeException ex) {throw new DecryptionException("Decryption of message failed", ex);}}private Cipher createCipher(EncryptorProperties encryptorProperties) {try {return Cipher.getInstance(encryptorProperties.getAsymmetricAlgorithm());} catch (NoSuchAlgorithmException | NoSuchPaddingException ex) {throw new EncryptorInitializationException("Creation of cipher failed", ex);}}private KeyPairGenerator generateKeyPair() {try {return KeyPairGenerator.getInstance(this.encryptorProperties.getAsymmetricAlgorithm());} catch (NoSuchAlgorithmException ex) {throw new EncryptorInitializationException("Creation of encryption keypair failed", ex);}}}为了实现我们的功能,我们需要处理很多异常,但是由于万一它们发生,我们将不对其进行任何处理,因此我们将在语义上有意义的运行时异常包装起来。 我不会在这里展示异常类,因为它们只有一个构造函数。 但是您可以在github.com.tasosmartidis.tutorial.encryption.exception包下的项目中检出它们。
您将在代码的不同部分看到它们的实际用法。 BaseAsymmetricEncryptor的构造BaseAsymmetricEncryptor将EncryptorProperites实例作为参数。
package com.tasosmartidis.tutorial.encryption.domain;import lombok.AllArgsConstructor;@AllArgsConstructor public class EncryptorProperties {private final AsymmetricAlgorithm asymmetricAlgorithm;private final int keyLength;public String getAsymmetricAlgorithm() {return asymmetricAlgorithm.toString();}public int getKeyLength() {return keyLength;} }我们将创建一个基于RSA的加密器实现。 该代码应该说明一切:
package com.tasosmartidis.tutorial.encryption.encryptor;import com.tasosmartidis.tutorial.encryption.domain.AsymmetricAlgorithm; import com.tasosmartidis.tutorial.encryption.domain.EncryptedMessage; import com.tasosmartidis.tutorial.encryption.domain.EncryptorProperties; import org.bouncycastle.jcajce.provider.digest.SHA3; import org.bouncycastle.util.encoders.Hex;import java.security.PublicKey;public class RsaEncryptor extends BaseAsymmetricEncryptor {private static final int KEY_LENGTH = 2048;public RsaEncryptor() {super(new EncryptorProperties(AsymmetricAlgorithm.RSA, KEY_LENGTH));}public String encryptMessageForPublicKeyOwner(String message, PublicKey key) {return super.encryptText(message, key);}public String encryptMessageWithPrivateKey(String message) {return super.encryptText(message, super.getPrivateKey());}public String decryptReceivedMessage(EncryptedMessage message) {return super.decryptText(message.getEncryptedMessagePayload(), super.getPrivateKey());}public String decryptMessageFromOwnerOfPublicKey(String message, PublicKey publicKey) {return super.decryptText(message, publicKey);}public String hashMessage(String message) {SHA3.DigestSHA3 digestSHA3 = new SHA3.Digest512();byte[] messageDigest = digestSHA3.digest(message.getBytes());return Hex.toHexString(messageDigest);} }对于我们的演示,我们将需要演员,互相交流信息的人。 每个人都将具有唯一的身份,姓名以及与之通信的受信任联系人的列表。
package com.tasosmartidis.tutorial.encryption.demo;import com.tasosmartidis.tutorial.encryption.domain.EncryptedMessage; import com.tasosmartidis.tutorial.encryption.message.RsaMessenger; import lombok.EqualsAndHashCode;import java.security.PublicKey; import java.util.HashSet; import java.util.Set; import java.util.UUID;@EqualsAndHashCode public class Person {private final String id;private final String name;private final Set<Person> trustedContacts;private final RsaMessenger rsaMessenger;public Person(String name) {this.id = UUID.randomUUID().toString();this.name = name;this.trustedContacts = new HashSet<>();this.rsaMessenger = new RsaMessenger(this.trustedContacts, this.id);}public PublicKey getPublicKey() {return this.rsaMessenger.getPublicKey();}public String getName() {return name;}public String getId() {return id;}public void addTrustedContact(Person newContact) {if(trustedContacts.contains(newContact)) {return;}trustedContacts.add(newContact);}public EncryptedMessage sendEncryptedMessageToPerson(String message, Person person) {return this.rsaMessenger.encryptMessageForPerson(message, person);}public void readEncryptedMessage(EncryptedMessage encryptedMessage) {this.rsaMessenger.readEncryptedMessage(encryptedMessage);}}接下来,让我们创建一个RsaMessanger类,该类将允许人们使用RsaEncryptor发送加密的消息。 发送加密的消息时,我们将提供所有必要的信息,以确保机密性,完整性和身份验证。 阅读时,我们将解密邮件,我们将尝试验证邮件是由受信任的联系人发送的,并确保邮件没有受到破坏或更改。
package com.tasosmartidis.tutorial.encryption.message;import com.tasosmartidis.tutorial.encryption.demo.Person; import com.tasosmartidis.tutorial.encryption.domain.EncryptedMessage; import com.tasosmartidis.tutorial.encryption.encryptor.RsaEncryptor; import com.tasosmartidis.tutorial.encryption.exception.PayloadAndDigestMismatchException;import java.security.PublicKey; import java.util.Optional; import java.util.Set;public class RsaMessenger {private final RsaEncryptor encryptionHandler;private final Set<Person> trustedContacts;private final String personId;public RsaMessenger(Set<Person> trustedContacts, String personId) {this.encryptionHandler = new RsaEncryptor();this.trustedContacts = trustedContacts;this.personId = personId;}public PublicKey getPublicKey() {return this.encryptionHandler.getPublicKey();}public EncryptedMessage encryptMessageForPerson(String message, Person person) {String encryptedMessage = this.encryptionHandler.encryptMessageForPublicKeyOwner(message, person.getPublicKey());String myEncryptedId = this.encryptionHandler.encryptMessageWithPrivateKey(this.personId);String hashedMessage = this.encryptionHandler.hashMessage(message);return new EncryptedMessage(encryptedMessage, this.personId, myEncryptedId, hashedMessage);}public void readEncryptedMessage(EncryptedMessage message) {String decryptedMessage = this.encryptionHandler.decryptReceivedMessage(message);Optional<Person> sender = tryIdentifyMessageSender(message.getSenderId());if(!decryptedMessageHashIsValid(decryptedMessage, message.getMessageDigest())) {throw new PayloadAndDigestMismatchException("Message digest sent does not match the one generated from the received message");}if(sender.isPresent() && senderSignatureIsValid(sender.get(), message.getEncryptedSenderId())) {System.out.println(sender.get().getName() +" send message: " + decryptedMessage);}else {System.out.println("Unknown source send message: " + decryptedMessage);}}private boolean senderSignatureIsValid(Person sender, String encryptedSenderId) {if(rawSenderIdMatchesDecryptedSenderId(sender, encryptedSenderId)) {return true;}return false;}private boolean rawSenderIdMatchesDecryptedSenderId(Person sender, String encryptedSenderId) {return sender.getId().equals(this.encryptionHandler.decryptMessageFromOwnerOfPublicKey(encryptedSenderId, sender.getPublicKey()));}private Optional<Person> tryIdentifyMessageSender(String id) {return this.trustedContacts.stream().filter(contact -> contact.getId().equals(id)).findFirst();}private boolean decryptedMessageHashIsValid(String decryptedMessage, String hashedMessage) {String decryptedMessageHashed = this.encryptionHandler.hashMessage(decryptedMessage);if(decryptedMessageHashed.equals(hashedMessage)) {return true;}return false;} }好的! 现在是演示时间!
我们将创建一些测试以确保一切正常。 我们要测试的方案是:
当爱丽丝(鲍勃的受信任联系人)向他发送加密的消息时,鲍勃可以解密该消息,并且知道来自鲍勃。 还要确保有效载荷没有被更改。
从Alice到Bob的相同消息不可用于Paul解密,并且将引发UnauthorizedForDecryptionException 。 当Paul(鲍勃不知道)发送加密消息时,鲍勃将能够读取该消息,但不知道是谁发送了该消息。 最后,当我们破坏加密消息的有效负载时,带有消息摘要的验证将识别出该消息并引发异常。
运行测试将产生以下结果:
就是这样! 再次感谢您的阅读,您可以在github上找到代码。
翻译自: https://www.javacodegeeks.com/2017/11/encryption-trust-tutorial.html
lua加密教程
总结
以上是生活随笔为你收集整理的lua加密教程_我们相信加密! 教程的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: json-tree api_什么是JSO
- 下一篇: jax-rs jax-ws_什么是JAX