{"id":1213,"date":"2012-05-25T01:00:00","date_gmt":"2012-05-25T01:00:00","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/2012\/10\/apache-shiro-part-3-cryptography.html"},"modified":"2012-10-22T05:03:43","modified_gmt":"2012-10-22T05:03:43","slug":"apache-shiro-part-3-cryptography","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html","title":{"rendered":"Apache Shiro Part 3 &#8211; Cryptography"},"content":{"rendered":"<div dir=\"ltr\" style=\"text-align: left\">Besides securing web pages and managing access rights               <a href=\"http:\/\/shiro.apache.org\/\">Apache Shiro<\/a> does also basic cryptography tasks. The framework is able to:<\/p>\n<ul>\n<li>encrypt and decrypt data, <\/li>\n<li>hash data,<\/li>\n<li>generate random numbers.<\/li>\n<\/ul>\n<p>Shiro does not implement any cryptography algorithms. All calculations are delegated to Java Cryptography Extension (JCE) API. The main benefit of using Shiro instead of what is already present in Java is ease of use and secure defaults. Shiro crypto module is written in higher abstraction level and by default implements all known best practices.              <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"more\"><\/a>             <\/p>\n<p>This is third part of series dedicated to Apache Shiro.               <a href=\"http:\/\/meri-stuff.blogspot.com\/2011\/03\/apache-shiro-part-1-basics.html\">First part<\/a> showed how to secure web application and add log in\/log out functionality.               <a href=\"http:\/\/meri-stuff.blogspot.com\/2011\/04\/apache-shiro-part-2-realms-database-and.html\">Second part<\/a> showed how to store user accounts in database and give users an option to authenticate themselves via PGP certificates.              <\/p>\n<p>This post begins with a short Shiro and JCE               <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#overview\">overview<\/a> and continues with description of few useful               <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#ByteSource\">conversion utilities<\/a>. Following chapters explain               <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CryptoRandomGenerator\">random number generation<\/a>,               <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CryptoHashing\">hashing<\/a> and how to               <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CryptoEncryption\">encrypt and decrypt<\/a> data. The               <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CryptoAdvancedEncryption\">final chapter<\/a> shows how to customize a cipher and how to create a new one.              <\/p>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"#overview\"><\/a>            <strong>Overview<\/strong><\/p>\n<p>Shiro cryptography module resides in               <code>org.apache.shiro.crypto<\/code> package. It does not have manual, but fortunately all crypto classes are Javadoc heavy. Javadoc contains everything that would be written in manual.              <\/p>\n<p>Shiro relies heavily on java cryptography extension. You do not need to understand JCE to use Shiro. However, you need JCE basics to customize it or add new features to it. If you are not interested in JCE,               <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#ByteSource\">skip<\/a> to the next chapter.              <\/p>\n<p>JCE is a set of highly customizable APIs and their default implementation. It is provider-based. If the default implementation does not have what you need, you can               <a href=\"http:\/\/download.oracle.com\/javase\/1.4.2\/docs\/guide\/security\/CryptoSpec.html#ProviderInstalling\">easily install<\/a> a new provider.              <\/p>\n<p>Each cipher, cipher option, hash algorithm or any other JCE feature has a name. JCE defines               <a href=\"http:\/\/download.oracle.com\/javase\/1.4.2\/docs\/guide\/security\/CryptoSpec.html#AppA\">two sets<\/a> of               <a href=\"http:\/\/download.oracle.com\/javase\/1.4.2\/docs\/guide\/security\/jce\/JCERefGuide.html#AppA\">standard names<\/a> for algorithms and algorithm modes. Those are available with any JDK. Any provider, for example               <a href=\"http:\/\/www.bouncycastle.org\/\">Bouncy Castle<\/a>, is free to extend the names sets with new algorithms and options.              <\/p>\n<p>Names are composed into so-called transformations strings which are used to look up needed objects. For example,               <code>Cipher.getInstance('DES\/ECB\/PKCS5Padding')<\/code> returns DES cipher in ECB mode with PKCS#5 padding. Returned cipher usually requires further initialization, may not use safe defaults and is not thread safe.<\/p>\n<p>Apache Shiro composes transformation strings, configures acquired objects and adds thread safety to them. Most importantly, it has easy to use API and adds higher level best practices that should be implemented anyway.              <\/p>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"ByteSource\"><\/a>            <strong>Encoding, Decoding and ByteSource<\/strong><\/p>\n<p>Crypto package encrypts, decrypts and hashes byte arrays (             <code>byte[]<\/code>). If you need to encrypt or hash s string, you have to convert it to byte array first. Conversely, if you need to store hashed or encrypted value in text file or string database column, you have to convert it to string.              <\/p>\n<p><strong>Text to Byte Array<\/strong><\/p>\n<p>Static class              <a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/codec\/CodecSupport.html\">CodecSupport<\/a> is able to convert the text to byte array and back. The method              <code>byte[] toBytes(String source)<\/code> converts a string to byte array and the method              <code>String toString(byte[] bytes)<\/code> converts it back.             <\/p>\n<p><strong>Example<\/strong><\/p>\n<p>Use codec support              <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncodingTestCase.java#L14\">to convert<\/a> between text and byte array:             <\/p>\n<pre class=\"brush:java\">@Test\r\n public void textToByteArray() {\r\n  String encodeMe = 'Hello, I'm a text.';\r\n\r\n  byte[] bytes = CodecSupport.toBytes(encodeMe);\r\n  String decoded = CodecSupport.toString(bytes);\r\n\r\n  assertEquals(encodeMe, decoded);\r\n }\r\n<\/pre>\n<p><strong>Encode and Decode Byte Arrays<\/strong><\/p>\n<p>Conversion from byte array to string is called encoding. The reverse process is called decoding. Shiro provides two different algorithms:             <\/p>\n<ul>\n<li>Base64 implemented in class <code><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/codec\/Base64.html\">Base64<\/a><\/code>,<\/li>\n<li>Hexadecimal implemented in class <code><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/codec\/Hex.html\">Hex<\/a><\/code>.<\/li>\n<\/ul>\n<p>Both classes are static and both have              <code>encodeToString<\/code> and              <code>decode<\/code> utility methods available.             <\/p>\n<p><strong>Examples<\/strong><\/p>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncodingTestCase.java#L47\">Encode a random array<\/a> into its Hexadecimal representation, decode it and verify the result:             <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testStaticHexadecimal() {\r\n  byte[] encodeMe = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};\r\n  \r\n  String hexadecimal = Hex.encodeToString(encodeMe);\r\n  assertEquals('020406080a0c0e101214', hexadecimal);\r\n  \r\n  byte[] decoded = Hex.decode(hexadecimal);\r\n  assertArrayEquals(encodeMe, decoded);\r\n }<\/pre>\n<p>Encode a random array              <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncodingTestCase.java#L59\">into its Byte64 representation<\/a>, decode it and verify the result:             <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testStaticBase64() {\r\n  byte[] encodeMe = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};\r\n  \r\n  String base64 = Base64.encodeToString(encodeMe);\r\n  assertEquals('AgQGCAoMDhASFA==', base64);\r\n  \r\n  byte[] decoded = Base64.decode(base64);\r\n  assertArrayEquals(encodeMe, decoded);\r\n }\r\n<\/pre>\n<p><strong>ByteSource<\/strong><\/p>\n<p>Cryptography package often returns an instance of              <code><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/util\/ByteSource.html\">ByteSource<\/a><\/code> interface instead of byte array. Its implementation              <code>SimpleByteSource<\/code> is a simple wrapper around byte array with additional encoding methods available:              <\/p>\n<ul>\n<li><code>String toHex()<\/code> &#8211; returns Hexadecimal byte array representation,<\/li>\n<li><code>String toBase64()<\/code> &#8211; returns Base64 byte array representation,<\/li>\n<li><code>byte[] getBytes()<\/code> &#8211; returns wrapped byte array.<\/li>\n<\/ul>\n<p><strong>Examples<\/strong><\/p>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncodingTestCase.java#L23\">The test<\/a> uses ByteSource to encode an array into its Hexadecimal representation. It then decodes it and verifies the result:             <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testByteSourceHexadecimal() {\r\n  byte[] encodeMe = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};\r\n  \r\n  ByteSource byteSource = ByteSource.Util.bytes(encodeMe);\r\n  String hexadecimal = byteSource.toHex();\r\n  assertEquals('020406080a0c0e101214', hexadecimal);\r\n  \r\n  byte[] decoded = Hex.decode(hexadecimal);\r\n  assertArrayEquals(encodeMe, decoded);\r\n }<\/pre>\n<p>Use Bytesource to              <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncodingTestCase.java#L35\">encode an array into its Base64<\/a> representation. Decode it and verify the result:             <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testByteSourceBase64() {\r\n  byte[] encodeMe = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};\r\n  \r\n  ByteSource byteSource = ByteSource.Util.bytes(encodeMe);\r\n  String base64 = byteSource.toBase64();\r\n  assertEquals('AgQGCAoMDhASFA==', base64);\r\n  \r\n  byte[] decoded = Base64.decode(base64);\r\n  assertArrayEquals(encodeMe, decoded);\r\n }\r\n<\/pre>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CryptoRandomGenerator\"><\/a>            <strong>Random Number Generator<\/strong><\/p>\n<p>Random number generator is composed of               <a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/crypto\/RandomNumberGenerator.html\">RandomNumberGenerator<\/a> interface and its default implementation               <a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/crypto\/SecureRandomNumberGenerator.html\">SecureRandomNumberGenerator<\/a>.              <\/p>\n<p>The interface is fairly simple, it has only two methods:                          <\/p>\n<ul>\n<li><code>ByteSource nextBytes()<\/code> &#8211; generates a random fixed length byte source,<\/li>\n<li><code>ByteSource nextBytes(int numBytes)<\/code> &#8211; generates a random byte source with specified length.<\/li>\n<\/ul>\n<p>The default implementation implements these two methods and provides some additional configuration:                           <\/p>\n<ul>\n<li><code>setSeed(byte[] bytes)<\/code> &#8211; custom seed configuration,<\/li>\n<li><code>setDefaultNextBytesSize(int defaultNextBytesSize)<\/code> &#8211; the length of <code>nextBytes()<\/code> output.<\/li>\n<\/ul>\n<p>The seed is a number (byte array in fact) that initializes random number generator. It allows you to generate &#8216;predictable random numbers&#8217;. Two instances of the same random generator initialized with the same seed always generate the same random numbers sequence. It is useful for debugging, but be very careful with it.               <\/p>\n<p>If you can, do not specify custom seed for cryptography. Use the default one. Unless you really know what you are doing, the attacker may be able to guess the custom one. That would beat all security purposes of random numbers.              <\/p>\n<p>Under the hood: SecureRandomNumberGenerator delegates random number generation to JCE SecureRandom implementation.              <\/p>\n<p><strong>Examples<\/strong><\/p>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/RandomNumberGeneratorTestCase.java#L13\">First example<\/a> creates two random number generators and verifies whether they generate two different things:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testRandomWithoutSeed() {\r\n  \/\/create random generators\r\n  RandomNumberGenerator firstGenerator = new SecureRandomNumberGenerator();\r\n  RandomNumberGenerator secondGenerator = new SecureRandomNumberGenerator();\r\n  \r\n  \/\/generate random bytes\r\n  ByteSource firstRandomBytes = firstGenerator.nextBytes();\r\n  ByteSource secondRandomBytes = secondGenerator.nextBytes();\r\n \r\n  \/\/compare random bytes\r\n  assertByteSourcesNotSame(firstRandomBytes, secondRandomBytes);\r\n }<\/pre>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/RandomNumberGeneratorTestCase.java#L32\">Second example<\/a> creates two random number generators, initializes them with the same seed and checks whether they generate the same expected 20 bytes long random array:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testRandomWithSeed() {\r\n  byte[] seed = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\r\n  \r\n  \/\/create and initialize first random generator\r\n  SecureRandomNumberGenerator firstGenerator = new SecureRandomNumberGenerator();\r\n  firstGenerator.setSeed(seed);\r\n  firstGenerator.setDefaultNextBytesSize(20);\r\n\r\n  \/\/create and initialize second random generator\r\n  SecureRandomNumberGenerator secondGenerator = new SecureRandomNumberGenerator();\r\n  secondGenerator.setSeed(seed);\r\n  secondGenerator.setDefaultNextBytesSize(20);\r\n\r\n  \/\/generate random bytes\r\n  ByteSource firstRandomBytes = firstGenerator.nextBytes();\r\n  ByteSource secondRandomBytes = secondGenerator.nextBytes();\r\n \r\n  \/\/compare random arrays\r\n  assertByteSourcesEquals(firstRandomBytes, secondRandomBytes);\r\n\r\n  \/\/following nextBytes are also the same\r\n  ByteSource firstNext = firstGenerator.nextBytes();\r\n  ByteSource secondNext = secondGenerator.nextBytes();\r\n\r\n  \/\/compare random arrays\r\n  assertByteSourcesEquals(firstRandomBytes, secondRandomBytes);\r\n\r\n  \/\/compare against expected values\r\n  byte[] expectedRandom = {-116, -31, 67, 27, 13, -26, -38, 96, 122, 31, -67, 73, -52, -4, -22, 26, 18, 22, -124, -24};\r\n  assertArrayEquals(expectedRandom, firstNext.getBytes());\r\n }\r\n<\/pre>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CryptoHashing\"><\/a>            <strong>Hashing<\/strong>            <\/p>\n<p>A               <a href=\"http:\/\/en.wikipedia.org\/wiki\/Hash_function\">hash<\/a>               <a href=\"http:\/\/en.wikipedia.org\/wiki\/Cryptographic_hash_function\">function<\/a> takes an arbitrary long data as an input and converts it to a smaller fixed length data. Hash function result is called hash. Hashing is one way operation. It is not possible to convert hash back to original data.              <div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>The most important thing to remember is: always store passwords hash instead of password itself. Never ever store it directly.               <\/p>\n<p>Shiro provides two hash related interfaces, both support two concepts necessary for secure password hashing: salting and hash iterations:              <\/p>\n<ul>\n<li><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CryptoHashingHash\"><code>Hash<\/code><\/a> &#8211; represents hash algorithm. <\/li>\n<li><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CryptoHashingHasher\"><code>Hasher<\/code><\/a> &#8211; use this to hash passwords.<\/li>\n<\/ul>\n<p>A salt is a random array concatenated to the password before hashing. It is usually stored together with the password. Without salt, identical passwords would have the same hash. That would make password hacking much easier.               <\/p>\n<p>Specify a number of hash iterations to slow down the hash operation. The slower the operation, the more difficult it is to crack stored passwords. Use               <a href=\"http:\/\/www.katasoft.com\/blog\/2011\/04\/04\/strong-password-hashing-apache-shiro\">a lot<\/a> of iterations.              <\/p>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CryptoHashingHash\"><\/a>             <strong>Hash<\/strong><\/p>\n<p><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/crypto\/hash\/Hash.html\">Hash<\/a> interface implementations compute hash functions. Shiro implements six standard hash functions:               <a href=\"http:\/\/en.wikipedia.org\/wiki\/MD2_%28cryptography%29\">Md2<\/a>,               <a href=\"http:\/\/en.wikipedia.org\/wiki\/MD5\">Md5<\/a>,               <a href=\"http:\/\/en.wikipedia.org\/wiki\/SHA-1\">Sha1<\/a>,               <a href=\"http:\/\/en.wikipedia.org\/wiki\/SHA-2\">Sha256<\/a>,               <a href=\"http:\/\/en.wikipedia.org\/wiki\/SHA-2\">Sha384<\/a> and               <a href=\"http:\/\/en.wikipedia.org\/wiki\/SHA-2\">Sha512<\/a>.              <\/p>\n<p>Each hash implementation extends from               <a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#ByteSource\">ByteSource<\/a>. The constructor takes input data, salt and number of required iterations. Salt and iterations number are optional.              <\/p>\n<p>ByteSource interface methods return:               <\/p>\n<ul>\n<li><code>byte[] getBytes()<\/code> &#8211; hash,<\/li>\n<li><code>String toBase64()<\/code> &#8211; hash in Base64 representation,<\/li>\n<li><code>String toHex()<\/code> &#8211; hash in Hexadecimal representation.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/HashTestCase.java#L13\">Following code<\/a> computes Md5 hash of &#8216;Hello Md5&#8217; text with no salt:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testMd5Hash() {\r\n  Hash hash = new Md5Hash('Hello Md5');\r\n  \r\n  byte[] expectedHash = {-7, 64, 38, 26, 91, 99, 33, 9, 37, 50, -22, -112, -99, 57, 115, -64};\r\n  assertArrayEquals(expectedHash, hash.getBytes());\r\n  assertEquals('f940261a5b6321092532ea909d3973c0', hash.toHex());\r\n  assertEquals('+UAmGltjIQklMuqQnTlzwA==', hash.toBase64());\r\n\r\n  print(hash, 'Md5 with no salt iterations of 'Hello Md5': ');\r\n }<\/pre>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/HashTestCase.java#L25\">Next snippet<\/a> calculates 10 iterations of Sha256 with salt:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testIterationsSha256Hash() {\r\n  byte[] salt = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\r\n\r\n  Hash hash = new Sha256Hash('Hello Sha256', salt, 10);\r\n  \r\n  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};\r\n  String expectedHex = '18049fc3461ce3556e0095f8f4a38763fb173c2ee95c43cd415f545731ddb28d';\r\n  String expectedBase64 = 'GASfw0Yc41VuAJX49KOHY\/sXPC7pXEPNQV9UVzHdso0=';\r\n  \r\n  assertArrayEquals(expectedHash, hash.getBytes());\r\n  assertEquals(expectedHex, hash.toHex());\r\n  assertEquals(expectedBase64, hash.toBase64());\r\n\r\n  print(hash, 'Sha256 with salt and 10 iterations of 'Hello Sha256': ');\r\n }<\/pre>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/HashTestCase.java#L42\">Compare iterations<\/a> calculated by the framework and by the client code:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void testIterationsDemo() {\r\n  byte[] salt = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};\r\n  \r\n  \/\/iterations computed by the framework \r\n  Hash shiroIteratedHash = new Sha256Hash('Hello Sha256', salt, 10);\r\n\r\n  \/\/iterations computed by the client code \r\n  Hash clientIteratedHash = new Sha256Hash('Hello Sha256', salt);\r\n  for (int i = 1; i &lt; 10; i++) {\r\n   clientIteratedHash = new Sha256Hash(clientIteratedHash.getBytes());\r\n  }\r\n  \r\n  \/\/compare results\r\n  assertByteSourcesEquals(shiroIteratedHash, clientIteratedHash);\r\n }<\/pre>\n<p>Under the hood: all concrete hash classes extend from               <code><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/crypto\/hash\/SimpleHash.html\">SimpleHash<\/a><\/code> which delegates hash computation to JCE MessageDigest implementation. If you wish to extend Shiro with another hash function, instance it directly. The constructor takes JCE message digest (hash) algorithm name as a parameter.              <\/p>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CryptoHashingHasher\"><\/a>             <strong>Hasher<\/strong><\/p>\n<p>Hasher works on top of hash functions and implements best practices related to salting. The interface has only one method:              <\/p>\n<ul>\n<li><code>HashResponse computeHash(HashRequest request)<\/code><\/li>\n<\/ul>\n<p>Hash request provides byte source to be hashed and an optional salt. Hash response returns a hash and a salt. The response salt is not necessary the same as supplied salt. More importantly, it may not be the whole salt used for hashing operation.               <\/p>\n<p>Any hasher implementation is free to generate its own random salt. The default implementation does that only if the request contains               <code>null<\/code> salt. Additionally, used salt may be composed of &#8216;base salt&#8217; and &#8216;public salt&#8217;. &#8216;Public salt&#8217; is returned in the hash response.               <\/p>\n<p>To understand why it is done this way, you have to recall that salt is usually stored together with the password. The attacker with access to the database would have all information needed for brute-force attack.               <\/p>\n<p>Therefore, the &#8216;public salt&#8217; is stored at the same place as the password and &#8216;base salt&#8217; is stored elsewhere. The attacker then needs to get access to two different places.              <\/p>\n<p>Default hasher is configurable. You can specify base salt, number of iterations and hash algorithm to be used. Use hash algorithm name from any Shiro hash implementation. It also always returns public salt from the hash request.               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/HasherTestCase.java#L37\">See the demo<\/a>:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void fullyConfiguredHasher() {\r\n  ByteSource originalPassword = ByteSource.Util.bytes('Secret');\r\n\r\n  byte[] baseSalt = {1, 1, 1, 2, 2, 2, 3, 3, 3};\r\n  int iterations = 10;\r\n  DefaultHasher hasher = new DefaultHasher();\r\n  hasher.setBaseSalt(baseSalt);\r\n  hasher.setHashIterations(iterations);\r\n  hasher.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME);\r\n  \r\n  \/\/custom public salt\r\n  byte[] publicSalt = {1, 3, 5, 7, 9};\r\n  ByteSource salt = ByteSource.Util.bytes(publicSalt);\r\n  \r\n  \/\/use hasher to compute password hash\r\n  HashRequest request = new SimpleHashRequest(originalPassword, salt);\r\n  HashResponse response = hasher.computeHash(request);\r\n  \r\n  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};\r\n  assertArrayEquals(expectedHash, response.getHash().getBytes());\r\n }<\/pre>\n<p>If you need compare passwords or data check-sums, provide a &#8216;public salt&#8217; back to the same hasher. It will reproduce the hash operation.               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/HasherTestCase.java#L16\">The example<\/a> uses Shiro               <code>DefaultHasher<\/code> implementation:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void hasherDemo() {\r\n  ByteSource originalPassword = ByteSource.Util.bytes('Secret');\r\n  ByteSource suppliedPassword = originalPassword;\r\n  Hasher hasher = new DefaultHasher();\r\n  \r\n  \/\/use hasher to compute password hash\r\n  HashRequest originalRequest = new SimpleHashRequest(originalPassword);\r\n  HashResponse originalResponse = hasher.computeHash(originalRequest);\r\n  \r\n  \/\/Use salt from originalResponse to compare stored password with user supplied password. We assume that user supplied correct password.\r\n  HashRequest suppliedRequest = new SimpleHashRequest(suppliedPassword, originalResponse.getSalt());\r\n  HashResponse suppliedResponse = hasher.computeHash(suppliedRequest);\r\n  assertEquals(originalResponse.getHash(), suppliedResponse.getHash());\r\n  \r\n  \/\/important: the same request hashed twice may lead to different results \r\n  HashResponse anotherResponse = hasher.computeHash(originalRequest);\r\n  assertNotSame(originalResponse.getHash(), anotherResponse.getHash());\r\n }<\/pre>\n<p>Note: as the supplied public salt in the above example was               <code>null<\/code>, default hasher generated new random public salt.              <\/p>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CryptoEncryption\"><\/a>            <strong>Encryption \/ Decryption<\/strong>            <\/p>\n<p>A cipher encrypts the data into ciphertext unreadable without a secret key. Ciphers are divided into two groups: symmetric and asymmetric. A symmetric cipher uses the same key for encryption and decryption. Asymmetric cipher uses two different keys, one is used for encryption and another for decryption.               <\/p>\n<p>Apache Shiro contains two symmetric ciphers:               <a href=\"http:\/\/en.wikipedia.org\/wiki\/Advanced_Encryption_Standard\">AES<\/a> and               <a href=\"http:\/\/en.wikipedia.org\/wiki\/Blowfish_%28cipher%29\">Blowfish<\/a>. Both are stateless and thus thread-safe. Asymmetric ciphers are not supported.              <\/p>\n<p>Both ciphers are able to generate random encryption key and both implement               <code><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/crypto\/CipherService.html\">CipherService<\/a><\/code> interface. The interface defines two encryption and two decryption methods. First group serves for encryption\/decryption of byte arrays:                          <\/p>\n<ul>\n<li><code>ByteSource encrypt(byte[] raw, byte[] encryptionKey)<\/code>,<\/li>\n<li><code>ByteSource decrypt(byte[] encrypted, byte[] decryptionKey)<\/code>.<\/li>\n<\/ul>\n<p>Second group encrypts\/decrypts streams:                          <\/p>\n<ul>\n<li><code>encrypt(InputStream in, OutputStream out, byte[] encryptionKey)<\/code>,<\/li>\n<li><code>decrypt(InputStream in, OutputStream out, byte[] decryptionKey)<\/code>.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncryptionTestCase.java#L23\">Next code snippet<\/a> generates new key, encrypts secret message with AES cipher, decrypts it and compares original message with decryption result:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void encryptStringMessage() {\r\n  String secret = 'Tell nobody!';\r\n  AesCipherService cipher = new AesCipherService();\r\n  \r\n  \/\/generate key with default 128 bits size\r\n  Key key = cipher.generateNewKey();\r\n  byte[] keyBytes = key.getEncoded();\r\n  \r\n  \/\/encrypt the secret\r\n  byte[] secretBytes = CodecSupport.toBytes(secret);\r\n  ByteSource encrypted = cipher.encrypt(secretBytes, keyBytes);\r\n  \r\n  \/\/decrypt the secret\r\n  byte[] encryptedBytes = encrypted.getBytes();\r\n  ByteSource decrypted = cipher.decrypt(encryptedBytes, keyBytes);\r\n  String secret2 = CodecSupport.toString(decrypted.getBytes());\r\n  \r\n  \/\/verify correctness\r\n  assertEquals(secret, secret2);\r\n }<\/pre>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncryptionTestCase.java#L45\">Another snipped<\/a> shows how to encrypt\/decryption streams with Blowfish. Shiro ciphers do not close nor flush neither input nor output stream. You have to do it by yourself:                           <\/p>\n<pre class=\"brush:java\">@Test\r\n public void encryptStream() {\r\n  InputStream secret = openSecretInputStream();\r\n  BlowfishCipherService cipher = new BlowfishCipherService();\r\n\r\n  \/\/ generate key with default 128 bits size\r\n  Key key = cipher.generateNewKey();\r\n  byte[] keyBytes = key.getEncoded();\r\n\r\n  \/\/ encrypt the secret\r\n  OutputStream encrypted = openSecretOutputStream();\r\n  try {\r\n   cipher.encrypt(secret, encrypted, keyBytes);\r\n  } finally {\r\n   \/\/ The cipher does not flush neither close streams.\r\n   closeStreams(secret, encrypted);\r\n  }\r\n\r\n  \/\/ decrypt the secret\r\n  InputStream encryptedInput = convertToInputStream(encrypted);\r\n  OutputStream decrypted = openSecretOutputStream();\r\n  try {\r\n   cipher.decrypt(encryptedInput, decrypted, keyBytes);\r\n  } finally {\r\n   \/\/ The cipher does not flush neither close streams.\r\n   closeStreams(secret, encrypted);\r\n  }\r\n\r\n  \/\/ verify correctness\r\n  assertStreamsEquals(secret, decrypted);\r\n }<\/pre>\n<p>If you               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncryptionTestCase.java#L77\">encrypt the same text<\/a> with the same key twice, you will get two different encrypted texts:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void unpredictableEncryptionProof() {\r\n  String secret = 'Tell nobody!';\r\n  AesCipherService cipher = new AesCipherService();\r\n\r\n  \/\/ generate key with default 128 bits size\r\n  Key key = cipher.generateNewKey();\r\n  byte[] keyBytes = key.getEncoded();\r\n\r\n  \/\/ encrypt two times\r\n  byte[] secretBytes = CodecSupport.toBytes(secret);\r\n  ByteSource encrypted1 = cipher.encrypt(secretBytes, keyBytes);\r\n  ByteSource encrypted2 = cipher.encrypt(secretBytes, keyBytes);\r\n\r\n  \/\/ verify correctness\r\n  assertArrayNotSame(encrypted1.getBytes(), encrypted2.getBytes());\r\n }<\/pre>\n<p>Both previous examples used               <code>Key generateNewKey()<\/code> method to generate keys. Use the method               <code>setKeySize(int keySize)<\/code> to override the default key size (128 bits). Alternatively, the               <code>keyBitSize<\/code> parameter of the method               <code>Key generateNewKey(int keyBitSize)<\/code> specifies a key size in bits.               <\/p>\n<p>Some ciphers support only some key sizes. For               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncryptionTestCase.java#L133\">example<\/a>, AES supports only 128, 192, and 256 bits log keys:                          <\/p>\n<pre class=\"brush:java\">@Test(expected=RuntimeException.class)\r\n public void aesWrongKeySize() {\r\n  AesCipherService cipher = new AesCipherService();\r\n  \r\n  \/\/The call throws an exception. Aes supports only keys of 128, 192, and 256 bits.\r\n  cipher.generateNewKey(200);\r\n }\r\n\r\n @Test\r\n public void aesGoodKeySize() {\r\n  AesCipherService cipher = new AesCipherService();\r\n  \/\/aes supports only keys of 128, 192, and 256 bits\r\n  cipher.generateNewKey(128);\r\n  cipher.generateNewKey(192);\r\n  cipher.generateNewKey(256);\r\n }<\/pre>\n<p>As far as basics go, this is it. You do not need more to encrypt and decrypt sensitive data in your applications.               <\/p>\n<p><strong>Update:<\/strong> I was overly optimistic here. Learning more is always useful, especially if you are handling sensitive data. This method is mostly, but not entirely secure. Both the problem and the solution are described in my               <a href=\"http:\/\/meri-stuff.blogspot.com\/2012\/04\/secure-encryption-in-java.html\">other post<\/a>.              <\/p>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CryptoAdvancedEncryption\"><\/a>            <strong>Encryption \/ Decryption &#8211; Advanced<\/strong>            <\/p>\n<p>Previous chapter showed how to encrypt and decrypt some data. This chapter shows little bit more about how Shiro encryption works and how to customize it. It also shows how to easily add a new cipher if the standard two are not suitable for you.              <\/p>\n<p><strong>Initialization Vector<\/strong><\/p>\n<p>Initialization vector is randomly generated byte array used during ecryption. The cipher that uses initialization vector is less predictable and thus harder to decrypt for an attacker.               <\/p>\n<p>Shiro automatically generates initialization vector and uses it to encrypt the data. The vector is then concatenated with encrypted data and returned to client code. You can turn it off by calling               <code>setGenerateInitializationVectors(false)<\/code> on the cipher. The method is defined on               <code>JcaCipherService<\/code> class. Both default encryption classes extend it.              <\/p>\n<p>Initialization vector size is encryption algorithm specific. If the default size (128 bits) does not work, use the method               <code>setInitializationVectorSize<\/code> to customize it.              <\/p>\n<p><strong>Random Generator<\/strong><\/p>\n<p>Turning off an initialization vector does not necessary mean that the cipher becomes predictable. Both Blowfish and AES have an element of randomness in them.              <\/p>\n<p><a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncryptionTestCase.java#L95\">Following example<\/a> turns off the initialization vector, but encrypted texts are still different:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void unpredictableEncryptionNoIVProof() {\r\n  String secret = 'Tell nobody!';\r\n  AesCipherService cipher = new AesCipherService();\r\n  cipher.setGenerateInitializationVectors(false);\r\n\r\n  \/\/ generate key with default 128 bits size\r\n  Key key = cipher.generateNewKey();\r\n  byte[] keyBytes = key.getEncoded();\r\n\r\n  \/\/ encrypt two times\r\n  byte[] secretBytes = CodecSupport.toBytes(secret);\r\n  ByteSource encrypted1 = cipher.encrypt(secretBytes, keyBytes);\r\n  ByteSource encrypted2 = cipher.encrypt(secretBytes, keyBytes);\r\n\r\n  \/\/ verify correctness\r\n  assertArrayNotSame(encrypted1.getBytes(), encrypted2.getBytes());\r\n }<\/pre>\n<p>It is possible to customize or turn off the randomness. However, never ever do it in a production code. The randomness is absolute necessity for secure data encryption.               <\/p>\n<p>Both Shiro encryption algorithms extend from               <code>JcaCipherService<\/code> class. The class have               <code>setSecureRandom(SecureRandom secureRandom)<\/code> method. Secure random is standard java JCE random number generator. Extend it to create own implementation and pass it to the cipher.              <\/p>\n<p>Our               <code>ConstantSecureRandom<\/code> implementation of               <code>SecureRandom<\/code> always returns zero. We supplied it to the cipher and turned off the initialization vector to create an               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncryptionTestCase.java#L114\">unsecure predictable encryption<\/a>:                           <\/p>\n<pre class=\"brush:java\">@Test\r\n public void predictableEncryption() {\r\n  String secret = 'Tell nobody!';\r\n  AesCipherService cipher = new AesCipherService();\r\n  cipher.setSecureRandom(new ConstantSecureRandom());\r\n  cipher.setGenerateInitializationVectors(false);\r\n\r\n  \/\/ define the key\r\n  byte[] keyBytes = {5, -112, 36, 113, 80, -3, -114, 77, 38, 127, -1, -75, 65, -102, -13, -47};\r\n\r\n  \/\/ encrypt first time\r\n  byte[] secretBytes = CodecSupport.toBytes(secret);\r\n  ByteSource encrypted = cipher.encrypt(secretBytes, keyBytes);\r\n\r\n  \/\/ verify correctness, the result is always the same\r\n  byte[] expectedBytes = {76, 69, -49, -110, -121, 97, -125, -111, -11, -61, 61, 11, -40, 26, -68, -58};\r\n  assertArrayEquals(expectedBytes, encrypted.getBytes());\r\n }<\/pre>\n<p>Constant secure random implementation is long and uninteresting. It is               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/EncryptionTestCase.java#L185\">available on Github<\/a>.               <\/p>\n<p><strong>Custom Cipher<\/strong><\/p>\n<p>Out of the box Shiro provides only Blowfish and AES encryption methods. The framework does not implement its own algorithms. Instead, it delegates the encryption to JCE classes.               <\/p>\n<p>Shiro provides only secure defaults and easier API. This design makes it possible to extend Shiro with any JCE block cipher.               <\/p>\n<p>Block ciphers encrypt messages per blocks. All blocks have equal fixed size. If the last block is too short, a padding is added to make it the same size as all other blocks. Each block is encrypted and combined with previously encrypted blocks.               <\/p>\n<p>Therefore, you have to configure:               <\/p>\n<ul>\n<li><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CustomEncryptionEncryptionMethod\">encryption method<\/a>,<\/li>\n<li><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CustomEncryptionBlockSize\">block size<\/a>,<\/li>\n<li><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CustomEncryptionPadding\">padding<\/a>,<\/li>\n<li><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986#CustomEncryptionOperationMode\">how to combine blocks<\/a>.<\/li>\n<\/ul>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CustomEncryptionEncryptionMethod\"><\/a>             <strong>Encryption Method<\/strong><\/p>\n<p>A custom cipher extends a               <code><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/crypto\/DefaultBlockCipherService.html\">DefaultBlockCipherService<\/a><\/code> class. The class has only one constructor with one parameter: algorithm name. You may supply any               <a href=\"http:\/\/download.oracle.com\/javase\/1.4.2\/docs\/guide\/security\/jce\/JCERefGuide.html#AppA\">JCE compatible algorithm name<\/a>.               <\/p>\n<p>For example, this is source code of Shiro               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/AesCipherService.java#L23\">AES cipher<\/a>:                          <\/p>\n<pre class=\"brush:java\">public class AesCipherService extends DefaultBlockCipherService {\r\n\r\n    private static final String ALGORITHM_NAME = 'AES';\r\n\r\n    public AesCipherService() {\r\n        super(ALGORITHM_NAME);\r\n    }\r\n\r\n}<\/pre>\n<p>AES does not need to specify no other encryption parameter (block size, padding, encryption method). Defaults are good enough for AES.              <\/p>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CustomEncryptionBlockSize\"><\/a>             <strong>Block Size<\/strong><\/p>\n<p>Default block cipher service has two methods for block size customization. The method               <code>setBlockSize(int blockSize)<\/code> works only for byte array encoding and decoding. The method               <code>setStreamingBlockSize(int streamingBlockSize)<\/code> works only for stream encoding and decoding.               <\/p>\n<p>The value               <code>0<\/code> means that the default algorithm specific block size will be used. This is the default value.               <\/p>\n<p>Block cipher block size is very algorithm-specific. Selected encryption algorithm may not work with an               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/CustomEncryptionTestCase.java#L21\">arbitrary block size<\/a>:                          <\/p>\n<pre class=\"brush:java\">@Test(expected=CryptoException.class)\r\n public void aesWrongBlockSize() {\r\n  String secret = 'Tell nobody!';\r\n  AesCipherService cipher = new AesCipherService();\r\n  \/\/ set wrong block size \r\n  cipher.setBlockSize(200);\r\n\r\n  \/\/ generate key with default 128 bits size\r\n  Key key = cipher.generateNewKey();\r\n  byte[] keyBytes = key.getEncoded();\r\n\r\n  \/\/ encrypt the secret\r\n  byte[] secretBytes = CodecSupport.toBytes(secret);\r\n  cipher.encrypt(secretBytes, keyBytes);\r\n }\r\n<\/pre>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CustomEncryptionPadding\"><\/a>             <strong>Padding<\/strong><\/p>\n<p>Use the method               <code>setPaddingScheme(PaddingScheme paddingScheme)<\/code> to specify byte array encryption and decryption padding. The method               <code>setStreamingPaddingScheme( PaddingScheme paddingScheme)<\/code> specifies stream encryption and decryption padding.              <\/p>\n<p>The enumeration               <code><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/crypto\/PaddingScheme.html\">PaddingScheme<\/a><\/code> represents all typical padding schemes. Not all of them are available by default, you might have to install custom JCE provider to use them.               <\/p>\n<p>The value               <code>null<\/code> means that the default algorithm specific padding will be used. This is the default value.               <\/p>\n<p>If you need a padding not included in the               <code>PaddingScheme<\/code> enumeration, use either               <code>setPaddingSchemeName<\/code> or               <code>setStreamingPaddingSchemeName<\/code> methods. These methods take a string with padding scheme name as a parameter. They are less type-safe but more flexible than the above ones.               <\/p>\n<p>Padding is very algorithm-specific. Selected encryption algorithm may not work with an               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/CustomEncryptionTestCase.java#L37\">arbitrary padding<\/a>:                          <\/p>\n<pre class=\"brush:java\">@Test(expected=CryptoException.class)\r\n public void aesWrongPadding() {\r\n  String secret = 'Tell nobody!';\r\n  BlowfishCipherService cipher = new BlowfishCipherService();\r\n  \/\/ set wrong block size \r\n  cipher.setPaddingScheme(PaddingScheme.PKCS1);\r\n\r\n  \/\/ generate key with default 128 bits size\r\n  Key key = cipher.generateNewKey();\r\n  byte[] keyBytes = key.getEncoded();\r\n\r\n  \/\/ encrypt the secret\r\n  byte[] secretBytes = CodecSupport.toBytes(secret);\r\n  cipher.encrypt(secretBytes, keyBytes);\r\n }\r\n\r\n<\/pre>\n<p><a href=\"http:\/\/www.blogger.com\/blogger.g?blogID=8574118689743302986\" name=\"CustomEncryptionOperationMode\"><\/a>             <strong>Operation Mode<\/strong><\/p>\n<p>Operation mode specifies how are blocks chained (combined) together. As it was with a padding scheme, you might use either an               <code><a href=\"http:\/\/shiro.apache.org\/static\/1.1.0\/apidocs\/org\/apache\/shiro\/crypto\/OperationMode.html\">OperationMode<\/a><\/code> enumeration or a string to supply them.               <\/p>\n<p>Be careful, not each operation mode might be available. Additionally, they are not born equal. Some chaining modes are less safe than others. The default               <a href=\"http:\/\/en.wikipedia.org\/wiki\/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29\">Cipher Feedback<\/a> operation mode is both safe and available on all JDK environments.              <\/p>\n<p>Methods to set the operation mode for byte array encryption and decryption:              <\/p>\n<ul>\n<li><code>setMode(OperationMode mode)<\/code><\/li>\n<li><code>setModeName(String modeName)<\/code><\/li>\n<\/ul>\n<p>Methods to set the operation mode for stream encryption and decryption:              <\/p>\n<ul>\n<li><code>setStreamingMode(OperationMode mode)<\/code><\/li>\n<li><code>setStreamingModeName(String modeName)<\/code><\/li>\n<\/ul>\n<p><strong>Exercise &#8211; Decrypt Openssl<\/strong>            <\/p>\n<p>Suppose that an application sends data encrypted with Linux               <a href=\"http:\/\/linux.die.net\/man\/1\/enc\">openssl<\/a> command. We know both hexadecimal representation of the key and command used to encrypt the data:                          <\/p>\n<ul>\n<li>The key: <code>B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A<\/code>.<\/li>\n<li>The command: <code>openssl des3 -base64 -p -K &lt;secret key&gt; -iv &lt;initialization vector&gt;<\/code>.<\/li>\n<\/ul>\n<p>Each message contains both hexadecimal representation of the initialization vector and base64 encoded encrypted message.              <\/p>\n<p>Sample message:              <\/p>\n<ul>\n<li>The initialization vector: <code>F758CEEB7CA7E188<\/code>.<\/li>\n<li>The message: <code>GmfvxhbYJbVFT8Ad1Xc+Gh38OBmhzXOV<\/code>.<\/li>\n<\/ul>\n<p><strong>Generate Sample With OpenSSL<\/strong><\/p>\n<p>The sample message was encrypted with the command:                          <\/p>\n<pre class=\"brush:java\">#encrypt 'yeahh, that worked!' \r\necho yeahh, that worked! | openssl des3 -base64 -p -K B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A -iv F758CEEB7CA7E188<\/pre>\n<p>Use OpenSSL option -P to generate either a secret key or a random initial vector.               <\/p>\n<p><strong>Solution<\/strong><\/p>\n<p>First, we have to find out algorithm name, padding and operation mode. Fortunately, all three are available in OpenSSL               <a href=\"http:\/\/www.openssl.org\/docs\/apps\/enc.html\">documentation<\/a>. Des3               <a href=\"http:\/\/www.openssl.org\/docs\/apps\/enc.html#SUPPORTED_CIPHERS\">is an alias<\/a> for               <a href=\"http:\/\/en.wikipedia.org\/wiki\/Triple_DES\">triple DES<\/a> encryption algorithm in               <a href=\"http:\/\/en.wikipedia.org\/wiki\/Cipher_block_chaining#Cipher-block_chaining_.28CBC.29\">CBC<\/a> mode and OpenSSL               <a href=\"http:\/\/www.openssl.org\/docs\/apps\/enc.html#NOTES\">uses<\/a> PKCS#5 padding.              <\/p>\n<p><a href=\"http:\/\/en.wikipedia.org\/wiki\/Cipher_block_chaining#Cipher-block_chaining_.28CBC.29\">Cipher-block chaining<\/a> (CBC) requires an initialization vector of the same size as the block size.               <a href=\"http:\/\/en.wikipedia.org\/wiki\/Triple_DES\">Triple DES<\/a> requires 64 bit long blocks. Java JCE               <a href=\"http:\/\/download.oracle.com\/javase\/1.4.2\/docs\/guide\/security\/jce\/JCERefGuide.html#AppA\">uses &#8216;DESede&#8217;<\/a> algorithm name for Triple DES.               <\/p>\n<p>Our               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/CustomEncryptionTestCase.java#L88\">custom cipher<\/a> extends and configures               <code>DefaultBlockCipherService<\/code>:                          <\/p>\n<pre class=\"brush:java\">public class OpensslDes3CipherService extends DefaultBlockCipherService {\r\n\r\n  public OpensslDes3CipherService() {\r\n   super('DESede');\r\n   setMode(OperationMode.CBC);\r\n   setPaddingScheme(PaddingScheme.PKCS5);\r\n   setInitializationVectorSize(64);\r\n  }\r\n  \r\n }<\/pre>\n<p>Shiro cipher               <code>decrypt<\/code> method expects two input byte arrays, ciphertext and key. Ciphertext should contain both initialization vector and encrypted cipher text. Therefore, we have to combine them together before we try to decrypt the message. The method               <code>combine<\/code>               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/CustomEncryptionTestCase.java#L81\">combines two arrays<\/a> into one:                          <\/p>\n<pre class=\"brush:java\">private byte[] combine(byte[] iniVector, byte[] ciphertext) {\r\n  byte[] ivCiphertext = new byte[iniVector.length + ciphertext.length];\r\n\r\n  System.arraycopy(iniVector, 0, ivCiphertext, 0, iniVector.length);\r\n  System.arraycopy(ciphertext, 0, ivCiphertext, iniVector.length, ciphertext.length);\r\n\r\n  return ivCiphertext;\r\n }<\/pre>\n<p>The actual decryption               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/blob\/cryptography_demo\/src\/test\/java\/org\/meri\/shiro\/cryptographydemo\/CustomEncryptionTestCase.java#L72\">looks as usually<\/a>:                          <\/p>\n<pre class=\"brush:java\">@Test\r\n public void opensslDes3Decryption() {\r\n  String hexInitializationVector = 'F758CEEB7CA7E188';\r\n  String base64Ciphertext = 'GmfvxhbYJbVFT8Ad1Xc+Gh38OBmhzXOV';\r\n  String hexSecretKey = 'B9FAB84B65870109A6E8707BC95151C245BF18204C028A6A';\r\n\r\n  \/\/decode secret message and initialization vector\r\n  byte[] iniVector = Hex.decode(hexInitializationVector);\r\n  byte[] ciphertext = Base64.decode(base64Ciphertext);\r\n\r\n  \/\/combine initialization vector and ciphertext together\r\n  byte[] ivCiphertext = combine(iniVector, ciphertext);\r\n  \r\n  \/\/decode secret key\r\n  byte[] keyBytes = Hex.decode(hexSecretKey);\r\n\r\n  \/\/initialize cipher and decrypt the message\r\n  OpensslDes3CipherService cipher = new OpensslDes3CipherService();\r\n  ByteSource decrypted = cipher.decrypt(ivCiphertext, keyBytes);\r\n  \r\n  \/\/verify result\r\n  String theMessage = CodecSupport.toString(decrypted.getBytes());\r\n  assertEquals('yeahh, that worked!\\n', theMessage);\r\n }\r\n\r\n<\/pre>\n<p><strong>End<\/strong><\/p>\n<p>This part of Apache Shiro tutorial covered cryptography features available in 1.2 version. All used examples are               <a href=\"https:\/\/github.com\/SomMeri\/SimpleShiroSecuredApplication\/tree\/cryptography_demo\">available on Github<\/a>.                <\/p>\n<p><strong><i>Reference: <\/i><\/strong><a href=\"http:\/\/meri-stuff.blogspot.com\/2011\/12\/apache-shiro-part-3-cryptography.html\">Apache Shiro Part 3 &#8211; Cryptography<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/p\/jcg.html\">JCG partner<\/a> Maria Jurcovicova at the <a href=\"http:\/\/meri-stuff.blogspot.com\/\">This is Stuff<\/a> blog.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Besides securing web pages and managing access rights Apache Shiro does also basic cryptography tasks. The framework is able to: encrypt and decrypt data, hash data, generate random numbers. Shiro does not implement any cryptography algorithms. All calculations are delegated to Java Cryptography Extension (JCE) API. The main benefit of using Shiro instead of what &hellip;<\/p>\n","protected":false},"author":203,"featured_media":79,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[295,362,297],"class_list":["post-1213","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-apache-shiro","tag-cryptography","tag-security"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Apache Shiro Part 3 - Cryptography - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Besides securing web pages and managing access rights Apache Shiro does also basic cryptography tasks. The framework is able to: encrypt and decrypt data,\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Apache Shiro Part 3 - Cryptography - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Besides securing web pages and managing access rights Apache Shiro does also basic cryptography tasks. The framework is able to: encrypt and decrypt data,\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2012-05-25T01:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2012-10-22T05:03:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-shiro-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Maria Jurcovicova\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Maria Jurcovicova\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html\"},\"author\":{\"name\":\"Maria Jurcovicova\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/fe8c21d37cb06cac89667ce9e690d6da\"},\"headline\":\"Apache Shiro Part 3 &#8211; Cryptography\",\"datePublished\":\"2012-05-25T01:00:00+00:00\",\"dateModified\":\"2012-10-22T05:03:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html\"},\"wordCount\":2667,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/apache-shiro-logo.jpg\",\"keywords\":[\"Apache Shiro\",\"Cryptography\",\"Security\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html\",\"name\":\"Apache Shiro Part 3 - Cryptography - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/apache-shiro-logo.jpg\",\"datePublished\":\"2012-05-25T01:00:00+00:00\",\"dateModified\":\"2012-10-22T05:03:43+00:00\",\"description\":\"Besides securing web pages and managing access rights Apache Shiro does also basic cryptography tasks. The framework is able to: encrypt and decrypt data,\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/apache-shiro-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/apache-shiro-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2012\\\/05\\\/apache-shiro-part-3-cryptography.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Apache Shiro Part 3 &#8211; Cryptography\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/fe8c21d37cb06cac89667ce9e690d6da\",\"name\":\"Maria Jurcovicova\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/036cc830ddb6b2d9385310d0eda5091365721bd14304c113c8548d6e508b5feb?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/036cc830ddb6b2d9385310d0eda5091365721bd14304c113c8548d6e508b5feb?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/036cc830ddb6b2d9385310d0eda5091365721bd14304c113c8548d6e508b5feb?s=96&d=mm&r=g\",\"caption\":\"Maria Jurcovicova\"},\"sameAs\":[\"http:\\\/\\\/meri-stuff.blogspot.com\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/Maria-Jurcovicova\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Apache Shiro Part 3 - Cryptography - Java Code Geeks","description":"Besides securing web pages and managing access rights Apache Shiro does also basic cryptography tasks. The framework is able to: encrypt and decrypt data,","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html","og_locale":"en_US","og_type":"article","og_title":"Apache Shiro Part 3 - Cryptography - Java Code Geeks","og_description":"Besides securing web pages and managing access rights Apache Shiro does also basic cryptography tasks. The framework is able to: encrypt and decrypt data,","og_url":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2012-05-25T01:00:00+00:00","article_modified_time":"2012-10-22T05:03:43+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-shiro-logo.jpg","type":"image\/jpeg"}],"author":"Maria Jurcovicova","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Maria Jurcovicova","Est. reading time":"21 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html"},"author":{"name":"Maria Jurcovicova","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/fe8c21d37cb06cac89667ce9e690d6da"},"headline":"Apache Shiro Part 3 &#8211; Cryptography","datePublished":"2012-05-25T01:00:00+00:00","dateModified":"2012-10-22T05:03:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html"},"wordCount":2667,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-shiro-logo.jpg","keywords":["Apache Shiro","Cryptography","Security"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html","url":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html","name":"Apache Shiro Part 3 - Cryptography - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-shiro-logo.jpg","datePublished":"2012-05-25T01:00:00+00:00","dateModified":"2012-10-22T05:03:43+00:00","description":"Besides securing web pages and managing access rights Apache Shiro does also basic cryptography tasks. The framework is able to: encrypt and decrypt data,","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-shiro-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-shiro-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2012\/05\/apache-shiro-part-3-cryptography.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Apache Shiro Part 3 &#8211; Cryptography"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/fe8c21d37cb06cac89667ce9e690d6da","name":"Maria Jurcovicova","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/036cc830ddb6b2d9385310d0eda5091365721bd14304c113c8548d6e508b5feb?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/036cc830ddb6b2d9385310d0eda5091365721bd14304c113c8548d6e508b5feb?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/036cc830ddb6b2d9385310d0eda5091365721bd14304c113c8548d6e508b5feb?s=96&d=mm&r=g","caption":"Maria Jurcovicova"},"sameAs":["http:\/\/meri-stuff.blogspot.com\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/Maria-Jurcovicova"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/1213","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/203"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=1213"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/1213\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/79"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=1213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=1213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=1213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}