JCA/JCE Java Crypto Architecture / Java Crypto Extensions Dušan Klinec deadcode.me CRvvCS Centre for Re Cryptography arv www.fi.muni.cz/crocs Provider architecture Message SHA-l .SHA-25B Message DtCj&st 5HA-513. Msseaga MD5 SH A-35S. PrauirinfA Prnii iriflfC Provider architecture Application ("MD5") Iran PravidcrB MessageDigest. getlnstance("MD5"); Provider Framework Message SHA-1 3HA-25E Message DtCj&st MOS SHA-513. IVcssag^ MD5 SH A-35S. PraiudfirA Provider!! PrniiidwH Provider architecture Application rMD5'.l Prx?virJorCr) from ProvidorC MessageDigest. getlnstance("MD5", "ProviderC"); Provider Framework •Igeel MD5 SHA-2&5. PrcuridrrA Providern PrcuririrrC JCA • Java.security.* • SecureRandom - PRNG • MessageDigest - SHA256, MD5, • Signature - RSA, DSA • KeyStore-PKCS12 • KeyPairGenerator, KeyFactory, CertificateFactory, CRvvCS JCE • iavax.crypto.* • Cipher-AES, RSA, EIGamal, RC4, Salsa20 • Mac - HMACWithSHA256 • KeyGenerator o) www.fi.muni.cz/crocs Provider architecture • Implementation independence • Implementation interoperability • Algorithm extensibility CRvvCS Bouncy Castle www.fi.muni.cz/crocs CRvvCS Bouncy Castle (J MD5") Iran PravidcrB Message SHA-1 3HA-25E Message 5HA-513. IVcssag^ MD5 SH A-35S. PrauidRfA Providers Providers BouncyCasf' www.fi.muni.cz/crocs CRvvCS Bouncy Castle • Implements a LOT OF ciphers, cipher suites, algorithms, modes, ASN.1, PEM, Certs, ... • Origin: Australian, former advantage (crypto regulations) • Android o) www.fi.muni.cz/crocs CRvvCS Provider architecture ¥ MessageDfgest • JEfl * Delegate tm) ? MessageDigest(String) getlnstance(String): MessageDigest getlnstancefStrfng, String): MessageDigest ^•"b getlnstance(String, Provfder): MessageDigest getProviderQ: Provider update(byte)^ void •m.^ update(byte[], int, int}" void ^"fe update(byte[]): void ©"b update(Byteßuffer)- void (nj)"b digestO: byte[] tm)"b digest(byte[], int, int): int r i> digest(byte[]}: byte[] toStrings String TObjec" 4P "b is£quaf(byte[], byte[]): boolean >p; "fe resetO: void 5p;'"b getAlgonthrnQ: String ©"b getDigestLengthQ- int Engine classes • getlnstance() • update() • digest() • reset() www.fi.muni.cz/crocs CRvvCS Provider architecture - Engine classes <£) it Cipher Jjjj'b getlnstance(String): Cipher J y ' b getfnstance(String, String): Cipher ' J y ' b getlnstancefString, Provider): Cipher tSy 'b getProviderQ: Provider ©•fc getAlgorithmO: String ^11 ö getBlockSizeO; in* V b getOutputSize(int): int ö getlVO: byte[] ' getParametersQ: AfgorithrnParameters % * b getExemptionMechanismQ: ExernptionMechanism t(int, Key): void * [(int, Key, SecureRandom): void t(int, Key, AlgorithmParameterSpec): void t(int, Key, AlgorithmParameterSpec, SecureRandom): w( [(int, Key, AfgorfthmParameters): void ;( -i:. 24] A T2[var7 » > 16 & 255] * T3[var8 > » 8 & 255] * T4[VÍ int v a ř i l = Tl[ var7 > » 24] A T2[ var3 » > 16 & 255] * T3[ var9 » > 8 & 255] varl2 = Tl[ var3 > » 24] A T2[ var9 > » 16 & 255] * T3 [var6 8 & 255] * T4[ VÍ var9 = Tl[var9 » > 2^] * T2[ var6 1£ & 255] * T3[ var7 > » 8 & 255] * T4[ va var6 = varlO; var7 = v a ř i l ; > varlB = this.K[varl3-H-]; var3[var4n] = (byle)(S[ var6 » > 24] A varle » > 2^)j var3[var4+»K] = (byte)(S[ var7 » > 16 & 255] A varlO » > 16); var3[var4+"r-] = (byte)(S[ var8 » > 8 & 255] * varle » > 8); var3[var4++-] = (byte)(S[ var& & 255] * varlG); varle = this.K[ varl3++]; var3[var4ii] = i by le) (S[var7 » > 24] A varle » > 2^)j var3[var4+"r-] = (byte) (S[var8 » > 16 & 255] * varle » > 16) • var3[var4+»r-] = (byte)(S[ var9 » > 8 & 255] * varle » > 8); var3[var4++-] = (byte)(S[ var6 & 255] * varlG); Strong cryptography • Limits the strength of your crypto • the size of the Key • AES-256, RSA-2048 not available by default • Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files CRvvCS Sign In/Register Help Country v Communities v lama,., v Iwantto,., v I Search Products Solutions Downloads Store Support Training Partner Oracle Technology Network JavaSE > Downloads Java S E Java EE Java M E Java S E Support Java S E Advanced & Suite Java Embedded Java DE Web Tier Java Card Java TV New Ho Java Connrn unity Java Magazine Overview Downloads Documentation Community Technologies Training Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 7 Download Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files You must accept the Oracle Binary Code License Agreement for the Java SE Platform Products to download this software. Accept License Agreement Q Decline License Agreement Product / File Description File Size Download Java Cryptography Extension (JCE) Unlimited Strength Ju risdi eti on Pol icy Fi les 7 7.3 K UnliniitedJCEPoli www.fi.muni.cz/crocs CRvvCS Strong cryptography A l g o r i t h m K e y s i z e DES DESede * RC2 RC4 128 RSA * (KeyPairGenerator 1024) other < N < www.fi.muni.cz/crocs Download NetBeans project Visit study materials Pis open / download NetBeans 12 CRvvCS Pis open M N e t B e a n s • E d i t V i e w N a v i g a t e S o u r c e • •• t n s ] H N e w P r o j e c t . . . S N e w F i l e . . . E N P r o j e c t s Q Files O p e n P r o j e c t . . . O p e n R e c e n t P r o j e c t C l o s e P r o j e c t [ P V 1 8 1 J C A ) o) www.fi.muni.cz/crocs CRvvCS Getting started T a s k 0 0 A E S S t r e n g t h j a v a Q p v l 6 1 j c a . t a s k s rig. T a s k Q 1 5 e c u r e R a n d o r n J a v a rfg. T a s k O Z M e s s a g e D i g e s t j a v a rf& T a s k 0 3 A E 5 j a v a rfg. T a s k 0 4 5 i g n a t u r e J a v a www.fi.muni.cz/crocs CRvvCS Cipher - import missing System.out.printlnj"Maximum allowed AES key size is " + getMsxAUowedKeyLengtfri "AES")); o) www.fi.muni.cz/crocs CRvvCS Cipher - import missing System*out*printlnj"Maximum allowed AES key size is " + getMsxAUowedKeyLengtfri "AES") ); o) www.fi.muni.cz/crocs CRvvCS Lighbulb helps 21 ft 23 24 25 26 System*out.println("Maximum allowed AES key size i s getMaxAllowedKeyLengthi "AES")); • i ? Add import for javax.crypto.Cipher 9 Create class "Cipher" in package pvlfiljca/tasks (Source Packages) 9 Create class "Cipher" in pvlBl.jca.tasks.TaskOOAESStrength 9 Create field "Cipher11 in pvlfil.jca.tasks.TaskGOAESStrength 9 Flip operands of '+' (may alter semantics} www.fi.muni.cz/crocs CRvvCS Getting started C T R L + S H I F T + I System.out.println{"Maximum allowed AES key size i s " + getMaxAllQwedKeyLengtft{"f\LS")); ? Add import for javaxxryptoXipher 9 Create class "Cipher11 in package pvlSljca/tasks {Source Packages) 9 Create class "Cipher11 in pvlBl.jca.tasks.TaskOOAESStrength 9 Create field "Cipher" in pvlfil.jca.tasks.TaskGOAESStrength 9 Flip operands of V (may alter semantics) • www.fi.muni.cz/crocs CRvvCS Problem again 23 25 System*out*printlnf"Maximum allowed AES key size i s " + Cipher* getMsxAIIowedKeyLength ] • o) www.fi.muni.cz/crocs CRvvCS Problem again public class TaskOBAESStrength { public static void main{String argsM) th^ws^oSuchA^oj^^hmE^ 0) www.fi.muni.cz/crocs CRvvCS The web o) www.fi.muni.cz/crocs CRvvCS Pis open - the guide goo.gl/4Ztqen Case sensitive www.fi.muni.cz/crocs CRvvCS TaskOI - SecureRandom • SecureRandom rnd = new SecureRandom() • rnd.nextDouble() • rnd.nextByte() • rnd o) www.fi.muni.cz/crocs CRvvCS TaskOI - SecureRandom 1. SecureRandom Generate 1024 random bytes using SecureRandom and print it with Globals.bytesToHexQ o SecureRandom uses PRNG implementations from Cryptography Service Providers. It may be: o SHA1PRNG default on Windows. o NativePRNG which reads /dev/urandom on Linux & Solaris. o Something completely different, depending on the architecture, provider, configuration, ... o SecureRandom is automatically seeded by OS means before a first call for a random data. o This seeding mechanism is bypassed if java.security.SecureRandom.setSeed(byte[]) is called. o You should not explicitly seed SecureRandom with your own data unless you are sure seed is not predictable. o For long term SecureRandom object is is recommended to re-seed it from time to time: rand.setSeed(java.security.SecureRandom.generateSeed(int)). CRvvCS Task 01 • You can work now www.fi.muni.cz/crocs CRvvCS SecureRandom - solution • SecureRandom rnd = new SecureRandom(); • rnd.nextBytes(buffer); • System.out.println(Globals.bytesToHex(buffer)); o) www.fi.muni.cz/crocs CRvvCS Task02 - MessageDigest 2. MessageDigest Verify digest of the following file and find the corrupted one. If digest does not match, find a difference (i position of a character wich differs). SHA-256 checksum MD5 checksum file_a.bin 230cb8e5f966c9d4618040fee7e010f8350794d0029df32c40fe8796d872bf29 e64db39c582fe33b35df742e8c23bd55 C1627b1968253cbc8595b1 b4c951 f949acbd1 d6001 ae366e108c20cfbb5232f3 3bf834b2853fbbace062cfe 1 f93f3776 file_c.bin aeeddl 72bcbc5c16a161844b689a465b96739a554d85b96138423aefec701 a18 bec261 a2d2a8921 Cb4cf78cc87c3d565 73cf8ba20aa05ba3c81387669e9c4b300742cfc5297569157712b4d6e2658638 79f2807a930062c358ecb65a484bd4d1 Hint: You may use Globals.bytesToHex(buffer, false); to encode byte[] byte array to a hex-coded string. Hint 2: You may use InputStream to read from URL directly: InputStream is01 = new URL("http://www.fi.muni.cz/~xklinec/java/file_a.bin").open$tream(); Hint 3: Boiler plate code for InputStream processing is here. Hint 4: Getting different hashes? Pay attention to URL and count number of bytes already hashed vs. file size. www.fi.muni.cz/crocs CRvvCS Task02 - MessageDigest • MessageDigest md5 = MessageDigest.getlnstance("MD5"); o) www.fi.muni.cz/crocs MessageDigest • MessageDigest md5 = MessageDigest.getlnstance("MD5"); • md5.update(inputBuffer, 0, bytesRead); • md5.update(inputBuffer, 0, bytesRead); • md5.update(inputBuffer, 0, bytesRead); • byte[] md5hash = md5.digest() CRvvCS MessageDigest - incremental API md5.update(data) MD5 md5.digest() md5.update(data) MD5 md5.digest() md5.update(data) MD5 md5.digest() md5.update(data) MD5 md5.digest() md5.update(data) md5.update(data) md5.update(data) byte[] hash www.fi.mu n i.cz/crocs CRvvCS www.fi.muni.cz/crocs CRvvCS Task 02 • You can work now www.fi.muni.cz/crocs CRvvCS MessageDigest - solution p u b l i c s t a t i c v o i d main ( S t r i n g a r g s M ) throws E x c e p t i o n { InputStream i s f l l = new URL{ " h t t p : //www, f i.muni. c z / ^ x k l i n e c / j a v a / f i l e _ a . b l i n " ^ openStreaml); byte[] b u f f e r = new byte[1624]; MessageDigest md5 = MessageDigest.getInst3nce{"MD5"}; MessageDigest sha = MessageDigest*getlnstancei"SHA 256"); i n t bytesRead = - l j w h i l e U b y t e s R e a d = i s 0 1 * r e a d { b u f f e r ] ) >= 0 H md5*update!buffer, 0, bytesRead); sha*update^buffer, 0, bytesRead); } System*out*printingGlobaIs*bytesToHex{mdS*digest{), f a l s e ) ) ; S y s t e m * o u t * p r i n t i n g G l o b a I s * b y t e s T o H e x { s h a * d i g e s t { ) , f a l s e ) ) ; www.fi.muni.cz/crocs CRvvCS Task03 - Cipher 3. AES Encryption Decrypt the following ciphertexts. Cipher used: AES/CBC/PKCS5Padding Question: How many bits does IV have? How many bits does key have? KEY AAAAAAAAAAAAAAAAAAAAAA-- AAAAAAAAAAAAAAAAAAAAAA-- 6VMSY9xFduwNsiyn8mGZdLG6/NXb3ziw81MBSfaKozs= FiikDkkW+k+oW2biRnC1 zQ== ellaq9at/s29sw0s5EEWv8Q== vDoRZgpnJ2/yCnW7ogatKoBIR3XBsViSz5Dfj2ExLI8= tPlljl_HaDSa8vXwrnDZiCg== 0y4bBloL0Ppbuy3o8AK6Vw== N2HNL2GCfEahFJ+9ieUuKzns4zp10nsWqN3SKN5s0x1uOn2BNn1s7bkqbQuTSYLFf/ow3kUQL Hintl: You may use javax.xml.bind.DatatypeConverter class for Base64 encoding & decoding. Java 10+ may need JVM param: -add-modules java.xml.bind Hint2: To construct AES encryption key you may use: new SecretKeySpec(keyO, "AES"); Hint2: To construct IV you may use: new IvParamelerSpec(ivO); www.fi.muni.cz/crocs CRvvCS Task03 - Cipher • getlnstance( "algorithm/mode/padding"); • Default mode: ECB • Default padding: PKCS5 2 bytes 6 5 e 5 www.fi.muni.cz/crocs CRvvCS www.fi.muni.cz/crocs CRvvCS Cipher • init(mode, key, algorithmParameterSpec) • Cipher. DECRYPT_MODE • new SecretKevSpecfaesKev, "AES") • new IvParameterSpec(iv) o) www.fi.muni.cz/crocs Cipher - Key vs KeySpec • Key - opaque key, used in engine • getAlgoritm(), getEncoded() • KeySpec - key specification, transport & storage • getP(), getQQ, getNQ CRvvCS Cipher - Key vs KeySpec • SecretKeySpec = Spec & Key in the same time o) www.fi.muni.cz/crocs Cipher - Key vs KeySpec public class RSAPrivateCrtKeySpcc extends RSAPrivateKeySpet { private final Diglnteger publicExponent; private final Diglnteger prifneP; private final Diglnteger prifneQ; private final Diglnteger primeExponentP; private final Diglnteger primeExponentQ; private final Diglnteger ertCoeffieient; www.fi.muni.cz/crocs Cipher - Key vs KeySpec • Why separated? CRvvCS Cipher - Key vs KeySpec • Why separated? Cipher.init(Cipher.DECRYPT_MODE, key) 0) www.fi.muni.cz/crocs CRvvCS Cipher - Key vs KeySpec • Why separated? Cipher.init(Cipher.DECRYPT_MODE, key) www.fi.muni.cz/crocs CRvvCS Cipher - Key vs KeySpec • Why separated? Cipher.init(Cipher.DECRYPT_MODE, key) Cloud encryption HSM Handle=0x123330, endpoint=https://... www.fi.muni.cz/crocs CRvvCS Cipher - Key materials • String vs. char[] • String is immutable, cannot zero out • Zero-out mutable byte[] after use to prevent key leakage to swap files (or Heartblead) o) www.fi.muni.cz/crocs Cipher - Key materials • GC deallocates but does not zero-out - key still there • Modern GC can copy, reorder mem (heap defrag), unable to properly delete keys from memory nowadays (Java does not specify behaviour, can differ). Key Factories • KeySpec -> Key • Key -> KeySpec • KeyFactory - asymetrie keys • SecretKeyFactory - symmetric keys Key generators • KeyGenerator - symmetric • generateSecret() -> SecretKey • KeyPairGenerator - asymmetric • generateKeyPair() -> KeyPair CRvvCS Task 03 • You can work now www.fi.muni.cz/crocs Cipher - Solution byte[] key = DatatypeConverter*par£eflaseG4Sirjary{ •'MAAAAAAAAAAAAAAAAAAAA=="); byte[] i v = DatatypeConverter*parseflase54i5.ir?ary{ "AAAAAAAAAAAAAAAAAAAAAA=="); byte[] ciphertext = DatatypeConverter*parseflaseG4Sinary{ ,, 6\/MSY9xFduwNsiyn8mGZdLG6/NXb3ziw81MBSf aKozs="); Cipher aes = Cipher*gfetl/?stance{ "AES/CBC/PKCSSPadding"); Key aesKey = new SecretKeySpecfkey, "AES"); aes-init{Cipher*DECRYPT_MQDE, aesKey, new IvParameterSpec{ i v ) ) ; byte[] p l a i n t e x t = a e s * d o F i n a U c i p h e r t e x t ) ; System*out*printIn{GlobaIs*bytesToHex(plaintext, f a l s e ) ) ; System*out*println{new S t r i n g { p l a i n t e x t ) ) ; p^L' www.fi.muni.cz/crocs CRvvCS Task04 - Signature 4. Signature verification Verify the following digital signatures. Signature scheme used: SHA1 WithRSA. Two signatures are swapped, find them and verify them. file_a.bin file_a.sig file_c.bin file_c.sig You will need a certificate: PEM encoded X509 certificate and DER encoded X509 certificate. Note: Signature files are base64 encoded. You have to perform base64 decoding before signature verification. Hint 1: You will need to construct X509Certificate object. Here is how. Hint 2: You may use InputStrem to read from URL directly: InputStream is01 = new URL("http://www.fi.muni.cz/-xkiinec/java/file_a.bin").openStream(); Hint 3: In order to convert a stream to a byte array you may use the following snippet. Hint 4: This snippet was used to generate a signature. By changing it you can produce a signature verifier. www.fi.muni.cz/crocs CRvvCS Certificate Builder • X509V3CertificateGenerator • goo.gl/l9WLUD 0) www.fi.muni.cz/crocs Diffie Hellman • KeyPairGenerator • KeyAgreement • goo.gl/Lus40Y CRvvCS Homework Check study materials for the assignment. Homework assignment #1 Hash collision generator. o In this assignment you are supposed to create a Java application which computes a message digest of a specific form, o The principle is very similar to the Bitcoin hash computation, o Use SHA-256 hash function. o Let denote UCO your university number identifier. Suppose mine is 987654. o Task is to find a string of a form "UCO:number", where "number" is an arbitrary number in a decimal representation, such that byte[] digest = md.digest("UCO:number".getBytes()); hashes to a byte array for which holds: o digest[0] == (byte)0x98, thus first byte of the digest is 1st part of your UCO. o dige$t[1] == (byte)0x76, thus second byte of the digest is 2nd part of your UCO. o digest[2] == (byte)0x54, thus third byte of the digest is 3rd part of your UCO. ° (digest[3] & ((byte)OxFO)) == 0, thus fourth byte has upper half byte zero. o BONUS: digest[3] == 0. For each additional full zero byte you receive 0.25 points up to 1 extra points. o BONUS: Write your reasoning to uco_reasoning.txt to explain why the given task worked (i.e., such hash exists) and why it took given amount of time benchmark hashes per second, compare to search space and match probability). Also explain why 0x98 != (byte)0x98. 0.25 Extra point. www.fi.muni.cz/crocs CRvvCS Thank you for your attention! Questions ? o) www.fi.muni.cz/crocs