当前位置: 首页 > news >正文

网站交互性设计制作一个保温杯

网站交互性,设计制作一个保温杯,网站做授权登录,高端网页设计模板除了保护网页和管理访问权限外#xff0c; Apache Shiro还执行基本的加密任务。 该框架能够#xff1a; 加密和解密数据#xff0c; 哈希数据#xff0c; 生成随机数。 Shiro没有实现任何加密算法。 所有计算都委托给Java密码学扩展#xff08;JCE#xff09;API。 使… 除了保护网页和管理访问权限外 Apache Shiro还执行基本的加密任务。 该框架能够 加密和解密数据 哈希数据 生成随机数。 Shiro没有实现任何加密算法。 所有计算都委托给Java密码学扩展JCEAPI。 使用Shiro代替Java中已经存在的主要好处是易于使用和安全的默认值。 Shiro加密模块以更高的抽象级别编写默认情况下实现所有已知的最佳实践。 这是致力于Apache Shiro的系列文章的第三部分。 第一部分介绍了如何保护Web应用程序并添加登录/注销功能。 第二部分介绍了如何在数据库中存储用户帐户以及如何为用户提供通过PGP证书进行身份验证的选项。 这篇文章从Shiro和JCE的简短概述开始并继续介绍一些有用的转换实用程序 。 以下各章介绍了随机数的生成 散列以及如何加密和解密数据。 最后一章介绍了如何自定义密码以及如何创建新密码。 总览 Shiro加密模块位于org.apache.shiro.crypto包中。 它没有手册但是幸运的是所有加密类都是Javadoc繁重的。 Javadoc包含将用手动编写的所有内容。 Shiro严重依赖于Java密码学扩展。 您无需了解JCE即可使用Shiro。 但是您需要JCE基础知识来对其进行自定义或添加新功能。 如果您对JCE不感兴趣请跳到下一章。 JCE是一组高度可定制的API及其默认实现。 它是基于提供程序的。 如果默认实现没有所需的内容则可以轻松安装新的提供程序。 每个密码密码选项哈希算法或任何其他JCE功能都有一个名称。 JCE为算法和算法模式定义了两组 标准名称 。 这些可用于任何JDK。 任何提供程序例如Bouncy Castle 都可以自由地使用新算法和选项扩展名称集。 名称由所谓的转换字符串组成用于查找所需的对象。 例如 Cipher.getInstance(DES/ECB/PKCS5Padding)在ECB模式下以PKCS5填充返回DES密码。 返回的密码通常需要进一步的初始化不能使用安全的默认值也不是线程安全的。 Apache Shiro组成转换字符串配置获取的对象并为其添加线程安全性。 最重要的是它具有易于使用的API并添加了无论如何都应实施的更高级别的最佳实践。 编码解码和ByteSource 加密包对字节数组 byte[] 进行加密解密和散列。 如果需要加密或哈希字符串则必须先将其转换为字节数组。 相反如果需要将散列或加密的值存储在文本文件或字符串数​​据库列中则必须将其转换为字符串。 文本到字节数组 静态类CodecSupport能够将文本转换为字节数组并返回。 方法byte[] toBytes(String source)将字符串转换为字节数组而方法String toString(byte[] bytes)将其转换回来。 例 使用编解码器支持在文本和字节数组之间进行转换 Testpublic void textToByteArray() {String encodeMe Hello, Im a text.;byte[] bytes CodecSupport.toBytes(encodeMe);String decoded CodecSupport.toString(bytes);assertEquals(encodeMe, decoded);} 编码和解码字节数组 从字节数组到字符串的转换称为编码。 反向过程称为解码。 Shiro提供了两种不同的算法 在Base64类中实现的Base64 在Hex类中实现的Hex 。 这两个类都是静态的并且都具有encodeToString和decode实用程序方法。 例子 将随机数组编码为其十六进制表示形式对其进行解码并验证结果 Testpublic void testStaticHexadecimal() {byte[] encodeMe {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};String hexadecimal Hex.encodeToString(encodeMe);assertEquals(020406080a0c0e101214, hexadecimal);byte[] decoded Hex.decode(hexadecimal);assertArrayEquals(encodeMe, decoded);} 将随机数组编码为其Byte64表示形式 对其进行解码并验证结果 Testpublic void testStaticBase64() {byte[] encodeMe {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};String base64 Base64.encodeToString(encodeMe);assertEquals(AgQGCAoMDhASFA, base64);byte[] decoded Base64.decode(base64);assertArrayEquals(encodeMe, decoded);} 字节源 加密程序包通常返回ByteSource接口的实例而不是字节数组。 它的实现SimpleByteSource是字节数组的简单包装提供了其他可用的编码方法 String toHex() –返回十六进制字节数组表示形式 String toBase64() –返回Base64字节数组表示形式 byte[] getBytes() –返回包装的字节数组。 例子 该测试使用ByteSource将数组编码成其十六进制表示形式。 然后解码并验证结果 Testpublic void testByteSourceHexadecimal() {byte[] encodeMe {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};ByteSource byteSource ByteSource.Util.bytes(encodeMe);String hexadecimal byteSource.toHex();assertEquals(020406080a0c0e101214, hexadecimal);byte[] decoded Hex.decode(hexadecimal);assertArrayEquals(encodeMe, decoded);} 使用Bytesource将数组编码成其Base64表示形式。 对其进行解码并验证结果 Testpublic void testByteSourceBase64() {byte[] encodeMe {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};ByteSource byteSource ByteSource.Util.bytes(encodeMe);String base64 byteSource.toBase64();assertEquals(AgQGCAoMDhASFA, base64);byte[] decoded Base64.decode(base64);assertArrayEquals(encodeMe, decoded);} 随机数发生器 随机数生成器由RandomNumberGenerator接口及其默认实现SecureRandomNumberGenerator组成 。 该接口非常简单只有两种方法 ByteSource nextBytes() –生成一个随机的固定长度的字节源 ByteSource nextBytes(int numBytes) –生成具有指定长度的随机字节源。 默认实现实现了这两种方法并提供了一些其他配置 setSeed(byte[] bytes) –自定义种子配置 setDefaultNextBytesSize(int defaultNextBytesSize) – nextBytes()输出的长度。 种子是一个数字实际上是字节数组用于初始化随机数生成器。 它允许您生成“可预测的随机数”。 使用相同种子初始化的同一随机生成器的两个实例始终生成相同的随机数序列。 它对于调试很有用但要非常小心。 如果可以请不要为加密指定自定义种子。 使用默认值。 除非您真的知道自己在做什么否则攻击者可能会猜出定制的那个。 这将超过随机数的所有安全性目的。 在幕后SecureRandomNumberGenerator将随机数生成委托给JCE SecureRandom实现。 例子 第一个示例创建两个随机数生成器并验证它们是否生成两个不同的事物 Testpublic void testRandomWithoutSeed() {//create random generatorsRandomNumberGenerator firstGenerator new SecureRandomNumberGenerator();RandomNumberGenerator secondGenerator new SecureRandomNumberGenerator();//generate random bytesByteSource firstRandomBytes firstGenerator.nextBytes();ByteSource secondRandomBytes secondGenerator.nextBytes();//compare random bytesassertByteSourcesNotSame(firstRandomBytes, secondRandomBytes);} 第二个示例创建两个随机数生成器使用相同的种子对其进行初始化并检查它们是否生成相同的预期20字节长的随机数组 Testpublic void testRandomWithSeed() {byte[] seed {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//create and initialize first random generatorSecureRandomNumberGenerator firstGenerator new SecureRandomNumberGenerator();firstGenerator.setSeed(seed);firstGenerator.setDefaultNextBytesSize(20);//create and initialize second random generatorSecureRandomNumberGenerator secondGenerator new SecureRandomNumberGenerator();secondGenerator.setSeed(seed);secondGenerator.setDefaultNextBytesSize(20);//generate random bytesByteSource firstRandomBytes firstGenerator.nextBytes();ByteSource secondRandomBytes secondGenerator.nextBytes();//compare random arraysassertByteSourcesEquals(firstRandomBytes, secondRandomBytes);//following nextBytes are also the sameByteSource firstNext firstGenerator.nextBytes();ByteSource secondNext secondGenerator.nextBytes();//compare random arraysassertByteSourcesEquals(firstRandomBytes, secondRandomBytes);//compare against expected valuesbyte[] expectedRandom {-116, -31, 67, 27, 13, -26, -38, 96, 122, 31, -67, 73, -52, -4, -22, 26, 18, 22, -124, -24};assertArrayEquals(expectedRandom, firstNext.getBytes());} 散列 哈希 函数将任意长数据作为输入并将其转换为较小的固定长度数据。 哈希函数的结果称为哈希。 散列是一种操作方式。 无法将哈希转换回原始数据。 要记住的最重要的事情是始终存储密码哈希而不是密码本身。 永远不要直接存储它。 Shiro提供了两个与哈希相关的接口都支持安全密码哈希所必需的两个概念盐析和哈希迭代 Hash -表示哈希算法。 Hasher -用此来哈希密码。 盐是散列前与密码连接的随机数组。 它通常与密码一起存储。 没有盐相同的密码将具有相同的哈希。 这将使密码黑客变得更加容易。 指定许多哈希迭代以减慢哈希操作的速度。 操作越慢破解存储密码的难度就越大。 使用很多迭代。 杂凑 哈希接口实现计算哈希函数。 四郎器具六个标准散列函数 MD2 被Md5 SHA1 SHA256 SHA3​​84和SHA512 。 每个哈希实现都从ByteSource扩展。 构造函数获取输入数据盐和所需的迭代次数。 盐和迭代数是可选的。 ByteSource接口方法返回 byte[] getBytes() –哈希 String toBase64() – Base64表示形式的哈希 String toHex() -以十六进制表示形式的哈希。 以下代码不加盐地计算“ Hello Md5”​​文本的Md5哈希值 Testpublic void testMd5Hash() {Hash hash new Md5Hash(Hello Md5);byte[] expectedHash {-7, 64, 38, 26, 91, 99, 33, 9, 37, 50, -22, -112, -99, 57, 115, -64};assertArrayEquals(expectedHash, hash.getBytes());assertEquals(f940261a5b6321092532ea909d3973c0, hash.toHex());assertEquals(UAmGltjIQklMuqQnTlzwA, hash.toBase64());print(hash, Md5 with no salt iterations of Hello Md5: );} 下一个代码段用salt计算Sha256的10次迭代 Testpublic void testIterationsSha256Hash() {byte[] salt {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};Hash hash new Sha256Hash(Hello Sha256, salt, 10);byte[] expectedHash {24, 4, -97, -61, 70, 28, -29, 85, 110, 0, -107, -8, -12, -93, -121, 99, -5, 23, 60, 46, -23, 92, 67, -51, 65, 95, 84, 87, 49, -35, -78, -115};String expectedHex 18049fc3461ce3556e0095f8f4a38763fb173c2ee95c43cd415f545731ddb28d;String expectedBase64 GASfw0Yc41VuAJX49KOHY/sXPC7pXEPNQV9UVzHdso0;assertArrayEquals(expectedHash, hash.getBytes());assertEquals(expectedHex, hash.toHex());assertEquals(expectedBase64, hash.toBase64());print(hash, Sha256 with salt and 10 iterations of Hello Sha256: );} 比较由框架和客户端代码计算出的迭代 Testpublic void testIterationsDemo() {byte[] salt {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//iterations computed by the framework Hash shiroIteratedHash new Sha256Hash(Hello Sha256, salt, 10);//iterations computed by the client code Hash clientIteratedHash new Sha256Hash(Hello Sha256, salt);for (int i 1; i 10; i) {clientIteratedHash new Sha256Hash(clientIteratedHash.getBytes());}//compare resultsassertByteSourcesEquals(shiroIteratedHash, clientIteratedHash);} 在幕后所有具体的哈希类都从SimpleHash扩展后者将哈希计算委托给JCE MessageDigest实现。 如果您希望使用其他哈希函数扩展Shiro请直接对其进行实例化。 构造函数将JCE消息摘要哈希算法名称作为参数。 哈舍尔 Hasher在哈希函数之上工作并实现了与盐腌相关的最佳实践。 该接口只有一种方法 HashResponse computeHash(HashRequest request) 哈希请求提供要哈希的字节源和可选的盐。 哈希响应返回哈希和盐。 响应盐不必与提供的盐相同。 更重要的是它可能不是用于哈希操作的全部盐。 任何哈希器实现均可自由生成自己的随机盐。 仅当请求包含null盐时默认实现才执行此操作。 另外用过的盐可以由“碱盐”和“公共盐”组成。 哈希响应中返回“公共盐”。 要了解为什么要用这种方法必须记得盐通常与密码一起存储。 具有数据库访问权限的攻击者将拥有暴力攻击所需的所有信息。 因此“公共盐”与密码存储在同一位置“基本盐”存储在其他位置。 然后攻击者需要访问两个不同的位置。 默认哈希器是可配置的。 您可以指定基本盐要使用的迭代次数和哈希算法。 使用任何Shiro哈希实现中的哈希算法名称。 它还总是从哈希请求中返回公共盐。 观看演示 Testpublic void fullyConfiguredHasher() {ByteSource originalPassword ByteSource.Util.bytes(Secret);byte[] baseSalt {1, 1, 1, 2, 2, 2, 3, 3, 3};int iterations 10;DefaultHasher hasher new DefaultHasher();hasher.setBaseSalt(baseSalt);hasher.setHashIterations(iterations);hasher.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME);//custom public saltbyte[] publicSalt {1, 3, 5, 7, 9};ByteSource salt ByteSource.Util.bytes(publicSalt);//use hasher to compute password hashHashRequest request new SimpleHashRequest(originalPassword, salt);HashResponse response hasher.computeHash(request);byte[] expectedHash {55, 9, -41, -9, 82, -24, 101, 54, 116, 16, 2, 68, -89, 56, -41, 107, -33, -66, -23, 43, 63, -61, 6, 115, 74, 96, 10, -56, -38, -83, -17, 57};assertArrayEquals(expectedHash, response.getHash().getBytes());} 如果您需要比较密码或数据校验和请向同一哈希器提供一个“公用盐”。 它将重现哈希操作。 该示例使用Shiro DefaultHasher实现 Testpublic void hasherDemo() {ByteSource originalPassword ByteSource.Util.bytes(Secret);ByteSource suppliedPassword originalPassword;Hasher hasher new DefaultHasher();//use hasher to compute password hashHashRequest originalRequest new SimpleHashRequest(originalPassword);HashResponse originalResponse hasher.computeHash(originalRequest);//Use salt from originalResponse to compare stored password with user supplied password. We assume that user supplied correct password.HashRequest suppliedRequest new SimpleHashRequest(suppliedPassword, originalResponse.getSalt());HashResponse suppliedResponse hasher.computeHash(suppliedRequest);assertEquals(originalResponse.getHash(), suppliedResponse.getHash());//important: the same request hashed twice may lead to different results HashResponse anotherResponse hasher.computeHash(originalRequest);assertNotSame(originalResponse.getHash(), anotherResponse.getHash());} 注意由于上面示例中提供的公共盐为null 因此默认的hashher会生成新的随机公共盐。 加密/解密 密码将数据加密为没有密钥的无法读取的密文。 密码分为两组对称和不对称。 对称密码使用相同的密钥进行加密和解密。 非对称密码使用两个不同的密钥一个用于加密另一个用于解密。 Apache Shiro包含两个对称密码 AES和Blowfish 。 两者都是无状态的因此是线程安全的。 不支持非对称密码。 两种密码均能够生成随机加密密钥并且均实现CipherService接口。 该接口定义了两种加密和两种解密方法。 第一组用于字节数组的加密/解密 ByteSource encrypt(byte[] raw, byte[] encryptionKey) ByteSource decrypt(byte[] encrypted, byte[] decryptionKey) 。 第二组加密/解密流 encrypt(InputStream in, OutputStream out, byte[] encryptionKey) decrypt(InputStream in, OutputStream out, byte[] decryptionKey) 。 下一个代码段生成新密钥使用AES密码对秘密消息进行加密对其进行解密并将原始消息与解密结果进行比较 Testpublic void encryptStringMessage() {String secret Tell nobody!;AesCipherService cipher new AesCipherService();//generate key with default 128 bits sizeKey key cipher.generateNewKey();byte[] keyBytes key.getEncoded();//encrypt the secretbyte[] secretBytes CodecSupport.toBytes(secret);ByteSource encrypted cipher.encrypt(secretBytes, keyBytes);//decrypt the secretbyte[] encryptedBytes encrypted.getBytes();ByteSource decrypted cipher.decrypt(encryptedBytes, keyBytes);String secret2 CodecSupport.toString(decrypted.getBytes());//verify correctnessassertEquals(secret, secret2);} 另一个片段显示了如何使用Blowfish加密/解密流。 Shiro密码不会关闭也不刷新输入或输出流。 您必须自己做 Testpublic void encryptStream() {InputStream secret openSecretInputStream();BlowfishCipherService cipher new BlowfishCipherService();// generate key with default 128 bits sizeKey key cipher.generateNewKey();byte[] keyBytes key.getEncoded();// encrypt the secretOutputStream encrypted openSecretOutputStream();try {cipher.encrypt(secret, encrypted, keyBytes);} finally {// The cipher does not flush neither close streams.closeStreams(secret, encrypted);}// decrypt the secretInputStream encryptedInput convertToInputStream(encrypted);OutputStream decrypted openSecretOutputStream();try {cipher.decrypt(encryptedInput, decrypted, keyBytes);} finally {// The cipher does not flush neither close streams.closeStreams(secret, encrypted);}// verify correctnessassertStreamsEquals(secret, decrypted);} 如果使用相同的密钥两次加密相同的文本 则会得到两个不同的加密文本 Testpublic void unpredictableEncryptionProof() {String secret Tell nobody!;AesCipherService cipher new AesCipherService();// generate key with default 128 bits sizeKey key cipher.generateNewKey();byte[] keyBytes key.getEncoded();// encrypt two timesbyte[] secretBytes CodecSupport.toBytes(secret);ByteSource encrypted1 cipher.encrypt(secretBytes, keyBytes);ByteSource encrypted2 cipher.encrypt(secretBytes, keyBytes);// verify correctnessassertArrayNotSame(encrypted1.getBytes(), encrypted2.getBytes());} 前面的两个示例都使用Key generateNewKey()方法生成密钥。 使用方法setKeySize(int keySize)覆盖默认密钥大小128位。 或者方法Key generateNewKey(int keyBitSize)的方法的keyBitSize参数以位为单位指定密钥大小。 有些密码仅支持某些密钥大小。 例如 AES仅支持128、192和256位日志密钥 Test(expectedRuntimeException.class)public void aesWrongKeySize() {AesCipherService cipher new AesCipherService();//The call throws an exception. Aes supports only keys of 128, 192, and 256 bits.cipher.generateNewKey(200);}Testpublic void aesGoodKeySize() {AesCipherService cipher new AesCipherService();//aes supports only keys of 128, 192, and 256 bitscipher.generateNewKey(128);cipher.generateNewKey(192);cipher.generateNewKey(256);} 就基础而言就是这样。 您不需要更多的内容来加密和解密应用程序中的敏感数据。 更新我对此过于乐观。 了解更多信息总是有用的尤其是在处理敏感数据时。 此方法大部分是但不是完全安全的。 问题和解决方案都在我的另一篇文章中进行了介绍。 加密/解密-高级 上一章介绍了如何加密和解密某些数据。 本章将进一步介绍Shiro加密的工作原理以及如何对其进行自定义。 它还显示了如果标准的两个密码不适合您那么如何轻松添加新密码。 初始化向量 初始化向量是在加密期间使用的随机生成的字节数组。 使用初始化向量的密码很难预测因此对于攻击者来说很难解密。 Shiro自动生成初始化向量并将其用于加密数据。 然后将矢量与加密数据连接起来并返回给客户端代码。 您可以通过在密码上调用setGenerateInitializationVectors(false)将其关闭。 该方法在JcaCipherService类上定义。 这两个默认的加密类都对其进行了扩展。 初始化向量大小是特定于加密算法的。 如果默认大小128位不起作用请使用setInitializationVectorSize方法对其进行自定义。 随机发生器 关闭初始化向量不一定意味着密码变得可预测。 河豚和AES都具有随机性。 以下示例关闭了初始化向量但是加密的文本仍然不同 Testpublic void unpredictableEncryptionNoIVProof() {String secret Tell nobody!;AesCipherService cipher new AesCipherService();cipher.setGenerateInitializationVectors(false);// generate key with default 128 bits sizeKey key cipher.generateNewKey();byte[] keyBytes key.getEncoded();// encrypt two timesbyte[] secretBytes CodecSupport.toBytes(secret);ByteSource encrypted1 cipher.encrypt(secretBytes, keyBytes);ByteSource encrypted2 cipher.encrypt(secretBytes, keyBytes);// verify correctnessassertArrayNotSame(encrypted1.getBytes(), encrypted2.getBytes());} 可以自定义或关闭随机性。 但是永远不要在生产代码中这样做。 随机性是安全数据加密的绝对必要条件。 两种Shiro加密算法都从JcaCipherService类扩展。 该类具有setSecureRandom(SecureRandom secureRandom)方法。 安全随机数是标准的Java JCE随机数生成器。 扩展它以创建自己的实现并将其传递给密码。 我们的SecureRandom ConstantSecureRandom实现始终返回零。 我们将其提供给密码并关闭了初始化向量以创建不安全的可预测加密 Testpublic void predictableEncryption() {String secret Tell nobody!;AesCipherService cipher new AesCipherService();cipher.setSecureRandom(new ConstantSecureRandom());cipher.setGenerateInitializationVectors(false);// define the keybyte[] keyBytes {5, -112, 36, 113, 80, -3, -114, 77, 38, 127, -1, -75, 65, -102, -13, -47};// encrypt first timebyte[] secretBytes CodecSupport.toBytes(secret);ByteSource encrypted cipher.encrypt(secretBytes, keyBytes);// verify correctness, the result is always the samebyte[] expectedBytes {76, 69, -49, -110, -121, 97, -125, -111, -11, -61, 61, 11, -40, 26, -68, -58};assertArrayEquals(expectedBytes, encrypted.getBytes());} 持续安全的随机实现是漫长而无趣的。 它在Github上可用 。 自定义密码 开箱即用Shiro仅提供Blowfish和AES加密方法。 该框架没有实现自己的算法。 而是将加密委托给JCE类。 Shiro仅提供安全的默认设置和更简单的API。 这种设计使得可以使用任何JCE分组密码来扩展Shiro。 块密码对每个块的消息进行加密。 所有块具有相等的固定大小。 如果最后一个块太短则添加填充以使其与其他所有块相同。 每个块被加密并与先前加密的块组合。 因此您必须配置 加密方法 块大小 填充 如何结合块 。 加密方式 自定义密码扩展了DefaultBlockCipherService类。 该类只有一个带有一个参数的构造函数算法名称。 您可以提供任何与JCE兼容的算法名称 。 例如这是Shiro AES密码的源代码 public class AesCipherService extends DefaultBlockCipherService {private static final String ALGORITHM_NAME AES;public AesCipherService() {super(ALGORITHM_NAME);}} AES不需要指定其他加密参数块大小填充加密方法。 对于AES默认值足够好。 块大小 默认的块密码服务有两种方法可以自定义块大小。 setBlockSize(int blockSize)方法仅适用于字节数组的编码和解码。 setStreamingBlockSize(int streamingBlockSize)方法仅适用于流编码和解码。 值0表示将使用默认算法特定的块大小。 这是默认值。 分组密码块大小是特定于算法的。 选定的加密算法可能不适用于任意块大小 Test(expectedCryptoException.class)public void aesWrongBlockSize() {String secret Tell nobody!;AesCipherService cipher new AesCipherService();// set wrong block size cipher.setBlockSize(200);// generate key with default 128 bits sizeKey key cipher.generateNewKey();byte[] keyBytes key.getEncoded();// encrypt the secretbyte[] secretBytes CodecSupport.toBytes(secret);cipher.encrypt(secretBytes, keyBytes);} 填充 使用方法setPaddingScheme(PaddingScheme paddingScheme)指定字节数组加密和解密填充。 setStreamingPaddingScheme( PaddingScheme paddingScheme)指定流加密和解密填充。 枚举PaddingScheme代表所有典型的填充方案。 默认情况下并非所有功能都可用您可能必须安装自定义JCE提供程序才能使用它们。 值null表示将使用默认算法特定的填充。 这是默认值。 如果需要PaddingScheme枚举中未包含的填充请使用setPaddingSchemeName或setStreamingPaddingSchemeName方法。 这些方法采用带有填充方案名称作为参数的字符串。 它们的类型安全性较上一类小但更灵活。 填充非常特定于算法。 选定的加密算法可能不适用于任意填充 Test(expectedCryptoException.class)public void aesWrongPadding() {String secret Tell nobody!;BlowfishCipherService cipher new BlowfishCipherService();// set wrong block size cipher.setPaddingScheme(PaddingScheme.PKCS1);// generate key with default 128 bits sizeKey key cipher.generateNewKey();byte[] keyBytes key.getEncoded();// encrypt the secretbyte[] secretBytes CodecSupport.toBytes(secret);cipher.encrypt(secretBytes, keyBytes);} 操作模式 操作模式指定块如何链接组合在一起。 与填充方案一样您可以使用OperationMode枚举或字符串来提供它们。 注意并非每种操作模式都可用。 此外他们并非天生平等。 某些链接模式不如其他链接模式安全。 默认的密码反馈操作模式既安全又适用于所有JDK环境。 设置字节数组加密和解密操作模式的方法 setMode(OperationMode mode) setModeName(String modeName) 设置流加密和解密操作模式的方法 setStreamingMode(OperationMode mode) setStreamingModeName(String modeName) 练习–解密Openssl 假设应用程序发送使用Linux openssl命令加密的数据。 我们知道用于加密数据的密钥和命令的十六进制表示形式 密钥 B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A 。 命令 openssl des3 -base64 -p -K secret key -iv initialization vector 。 每个消息都包含初始化向量的十六进制表示形式和base64编码的加密消息。 样本消息 初始化向量 F758CEEB7CA7E188 。 消息 GmfvxhbYJbVFT8Ad1XcGh38OBmhzXOV 。 使用OpenSSL生成样本 该示例消息已使用以下命令加密 #encrypt yeahh, that worked! echo yeahh, that worked! | openssl des3 -base64 -p -K B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A -iv F758CEEB7CA7E188 使用OpenSSL选项-P可以生成密钥或随机初始向量。 解 首先我们必须找出算法名称填充和操作模式。 幸运的是这三个文件都可以在OpenSSL 文档中找到 。 Des3 是 CBC模式下三重DES加密算法的别名 而OpenSSL 使用 PKCS5填充。 密码块链接 CBC需要与块大小相同大小的初始化向量。 三重DES需要64位长的块。 Java JCE对Triple DES 使用“ DESede”算法名称。 我们的自定义密码扩展并配置了DefaultBlockCipherService public class OpensslDes3CipherService extends DefaultBlockCipherService {public OpensslDes3CipherService() {super(DESede);setMode(OperationMode.CBC);setPaddingScheme(PaddingScheme.PKCS5);setInitializationVectorSize(64);}} Shiro密码decrypt方法需要两个输入字节数组密文和密钥。 密文应同时包含初始化向量和加密密文。 因此在尝试解密消息之前我们必须将它们组合在一起。 该方法combine 两个数组合并为一个 private byte[] combine(byte[] iniVector, byte[] ciphertext) {byte[] ivCiphertext new byte[iniVector.length ciphertext.length];System.arraycopy(iniVector, 0, ivCiphertext, 0, iniVector.length);System.arraycopy(ciphertext, 0, ivCiphertext, iniVector.length, ciphertext.length);return ivCiphertext;} 实际的解密看起来通常是 Testpublic void opensslDes3Decryption() {String hexInitializationVector F758CEEB7CA7E188;String base64Ciphertext GmfvxhbYJbVFT8Ad1XcGh38OBmhzXOV;String hexSecretKey B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A;//decode secret message and initialization vectorbyte[] iniVector Hex.decode(hexInitializationVector);byte[] ciphertext Base64.decode(base64Ciphertext);//combine initialization vector and ciphertext togetherbyte[] ivCiphertext combine(iniVector, ciphertext);//decode secret keybyte[] keyBytes Hex.decode(hexSecretKey);//initialize cipher and decrypt the messageOpensslDes3CipherService cipher new OpensslDes3CipherService();ByteSource decrypted cipher.decrypt(ivCiphertext, keyBytes);//verify resultString theMessage CodecSupport.toString(decrypted.getBytes());assertEquals(yeahh, that worked!\n, theMessage);} 结束 Apache Shiro教程的这一部分介绍了1.2版中可用的加密功能。 所有使用的示例都可以在Github上找到 。 参考 Apache Shiro第3部分–来自JCG合作伙伴 Maria Jurcovicova的“ 密码”来自This is Stuff博客。 翻译自: https://www.javacodegeeks.com/2012/05/apache-shiro-part-3-cryptography.html
http://wiki.neutronadmin.com/news/81466/

相关文章:

  • 性能网站建设网站建设设计策划
  • 湖南建设厅网站不良记录个人微信公众号收费吗
  • 网站移动端自适应腾讯公司做的购物网站
  • 顺德手机网站设计信息开发一个手游需要多少钱
  • 网站底部留言代码ftp上传文件到网站
  • 怎样建设学校网站山东建设厅网站 高英
  • 如何注册国外网站天津建设工程合同备案网站
  • 长沙做痔疮东大医院de网站手机网站知识
  • 重庆建设银行官方网站首页怎么在拼多多上开网店卖东西
  • 金溪网站建设推广网站建设与管理课程的目标
  • 外贸网站 海外推广网站网页怎么设计
  • 梅州正规的免费建站深圳网站搜索排名
  • 建设网站的调研报告东莞做网站网站
  • 免费自助站制作在线深圳最新消息
  • 网站设计公司佛山深圳app开发公司有哪些
  • 做网站 做应用海口网站公司
  • 空包网站做红章底单做网站一定要实名认证吗
  • 界面简洁的网站vr全景网站开发
  • 成都市建网站公司滁州新橙科技网站建设
  • 网站设计 色彩wordpress进入有点卡
  • 江门做网站那家公司好音乐网站怎么做外链
  • 阿里云建站视频全部网站
  • 做qq头像的网站wordpress 本地头像
  • 专业的wap网站开发个人兼职网站制作
  • 9377将军网站优化原理
  • wordpress站群是什么那里有网站建设
  • 福州网站制作公司wordpress 文章全部显示
  • 做外贸需要关注国外哪些网站专业的网站服务公司
  • 创意视觉网站crm客户管理系统简历
  • 商务网站建设与维护课程做网站运维