Created
March 24, 2019 16:15
-
-
Save flashultra/498963ec508e9fb099e3e7110fee7f69 to your computer and use it in GitHub Desktop.
BCrypt java source
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Arrays; | |
import java.util.Random; | |
public class BCrypt { | |
public static final String Revision2 = "2"; | |
public static final String Revision2A = "2a"; | |
public static final String Revision2B = "2b"; | |
public static final String Revision2X = "2x"; | |
public static final String Revision2Y = "2y"; | |
private static final int BCRYPT_SALT_LEN = 16; | |
private static final int P_SZ = 18; | |
private static final int S_SZ = 1024; | |
private static final int NUM_ROUNDS = 16; | |
public static final String CHARS = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |
public static final byte[] BYTES = CHARS.getBytes(); | |
private static int[] BF_CRYPT_CIPHERTEXT = { 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944, | |
0x6f756274 }; | |
private static int[] KP = { 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, 0x082EFA98, | |
0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, | |
0x9216D5D9, 0x8979FB1B }; | |
private static int[] KS = { 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, | |
0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, | |
0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, | |
0x286085F0, 0xCA417918, 0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, | |
0x78AF2FDA, 0x55605C60, 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, | |
0x1141E8CE, 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, | |
0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, | |
0xFB21A991, 0x487CAC60, 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, | |
0x0F6D6FF3, 0x83F44239, 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, | |
0xABD388F0, 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, | |
0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, | |
0x85C12073, 0x401A449F, 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, | |
0xDB0FEAD3, 0x49F1C09B, 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, | |
0x04C006BA, 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, | |
0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, | |
0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, | |
0x8EA5E9F8, 0xDB3222F8, 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, | |
0x3E00DF82, 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, | |
0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, | |
0xB6F84565, 0xD28E49BC, 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, | |
0xD07E9EFE, 0x2BF11FB4, 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, | |
0x8E7594B7, 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, | |
0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, | |
0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, | |
0xC75442F5, 0xFB9D35CF, 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, | |
0x57B8E0AF, 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, | |
0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, 0xD60F573F, | |
0xBC9BC6E4, 0x2B60A476, 0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, | |
0xFF34052E, 0xC5855664, 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A, 0x4B7A70E9, 0xB5B32944, 0xDB75092E, | |
0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, | |
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, | |
0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, | |
0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, | |
0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, | |
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, 0xA9446146, | |
0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, 0x4E548B38, 0x4F6DB908, | |
0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, 0xDE9A771F, 0xD9930810, 0xB38BAE12, | |
0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, | |
0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16, 0x12A14D43, | |
0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, 0x043556F1, 0xD7A3C76B, | |
0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, 0x86E34570, 0xEAE96FB1, 0x860E5E0A, | |
0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A, | |
0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960, 0x5223A708, | |
0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, | |
0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, 0x1521B628, 0x29076170, 0xECDD4775, | |
0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, | |
0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50, 0x40685A32, | |
0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, 0xF837889A, 0x97E32D77, | |
0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, 0x57F584A5, 0x1B227263, 0x9B83C3FF, | |
0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, | |
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, 0xC742F442, | |
0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, 0xCF62A1F2, 0x5B8D2646, | |
0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, 0x095BBF00, 0xAD19489D, 0x1462B174, | |
0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, | |
0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, 0xA969A7AA, | |
0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, | |
0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, | |
0xDB83ADF7, 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, | |
0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, | |
0x96B591AF, 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, | |
0xDA2547E6, 0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, | |
0x27A18DEE, 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, | |
0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, | |
0xDD5B4332, 0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, | |
0xFE6BA9B7, 0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, | |
0x9029317C, 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, | |
0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, | |
0x602A9C60, 0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, | |
0x3B240B62, 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, | |
0xE7CCF5F0, 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, | |
0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, | |
0xCC00FFA3, 0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, | |
0x7B9479BF, 0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, | |
0x782EF11C, 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, | |
0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, | |
0xF0F7C086, 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, | |
0xB0804187, 0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, | |
0x8789BDC2, 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, | |
0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, | |
0xE0A9DC09, 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, | |
0xA186F20F, 0x2868F169, 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, | |
0x0DE6D027, 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, | |
0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, | |
0x4B7C0188, 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, | |
0xD83D7CD3, 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, | |
0xDDC6C837, 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0, 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, | |
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, | |
0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, | |
0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, | |
0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, | |
0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, | |
0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, | |
0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, | |
0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, | |
0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, | |
0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, | |
0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, | |
0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, | |
0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, | |
0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, | |
0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, | |
0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, | |
0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, | |
0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, | |
0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, | |
0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, | |
0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, | |
0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, | |
0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, 0xF523F357, 0xA6327623, 0x93A83531, | |
0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, | |
0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, | |
0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, | |
0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, | |
0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, 0xB74E6132, 0xCE77E25B, 0x578FDFE3, | |
0x3AC372E6 }; | |
static private final char base64_code[] = { '.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', | |
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', | |
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', | |
'2', '3', '4', '5', '6', '7', '8', '9' }; | |
static private final byte index_64[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
0, 1, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, | |
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, 28, 29, 30, 31, 32, | |
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1, -1, -1, -1, -1 }; | |
static int[] pBox = new int[KP.length]; | |
static int[] sBox = new int[KS.length]; | |
static int woffset; | |
static Random rand; | |
public static void main(String[] args) | |
{ | |
try { | |
long startTime = System.nanoTime(); | |
String result = BCrypt.encode("The quick brown fox jumps over the lazy dog", "$2a$10$//pCfnG5nwASrIRZg9.hN."); | |
long nanoTime = System.nanoTime() - startTime; | |
System.out.println("Bcrypt: "+result+" , Time: "+nanoTime); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
public BCrypt() { | |
rand = new Random(); | |
} | |
public static String encode(String password, String salt) throws Exception { | |
BCrypt bcrypt = new BCrypt(); | |
String passHashed = bcrypt.hashPassword(password, salt); | |
return passHashed; | |
} | |
private String hashPassword(String password, String salt) throws Exception { | |
int offset = 0; | |
char minor = Character.MIN_VALUE; | |
if (salt.length() < 16) | |
throw new Exception("Salt length is too short"); | |
if (salt.charAt(0) != '$' || salt.charAt(1) != '2') | |
throw new Exception("Invalid salt version"); | |
if (salt.charAt(2) == '$') { | |
offset = 3; | |
} else { | |
minor = salt.charAt(2); | |
if ((minor != 'y' && minor != 'x' && minor != 'a' && minor != 'b') || (salt.charAt(3) != '$')) | |
throw new Exception("Invalid salt revision"); | |
offset = 4; | |
} | |
if ((int) salt.charAt(offset + 2) > 36) | |
throw new Exception("Missing salt rounds"); | |
int rounds = Integer.parseInt(salt.substring(offset, offset + 2)); | |
String realSalt = salt.substring(offset + 3, offset + 25); | |
boolean isMinor = (minor != Character.MIN_VALUE); // .charCodeAt(0) >= 97 | |
String hashedPassword = "$2" + ((isMinor) ? minor : "") + "$"; | |
hashedPassword += ((rounds < 10) ? "0" : "") + rounds + "$"; | |
byte[] saltBytes = decode_base64(realSalt); | |
byte[] passwordBytes = (password + (isMinor ? Character.MIN_VALUE : "")).getBytes(); | |
byte[] hashedBytes = cryptRaw(passwordBytes, saltBytes, rounds); | |
if (hashedBytes == null) | |
return null; | |
String hashed = encode_base64(hashedBytes); | |
String saltString = encode_base64(saltBytes); | |
return (hashedPassword + saltString + hashed); | |
} | |
public static String generateSalt(int rounds, String saltRevision) throws Exception // 10 , BCrypt.Revision2B | |
{ | |
if (rounds < 4 || rounds > 31) | |
throw new Exception("Salt rounds should be between 4 and 31"); | |
byte[] rng = new byte[BCRYPT_SALT_LEN]; | |
for (int i = 0; i < BCRYPT_SALT_LEN; i++) { | |
rng[i] = (byte) (rand.nextInt(256) - 128); | |
} | |
String salt = "$" + saltRevision + "$" + ((rounds < 10) ? "0" : "") + rounds + "$"; | |
salt += encode_base64(rng); | |
return salt; | |
} | |
public static boolean verify(String plaintext, String hash) throws Exception { | |
BCrypt bcrypt = new BCrypt(); | |
String candidate = bcrypt.hashPassword(plaintext, hash); | |
if (candidate.length() != hash.length()) | |
return false; | |
int b = 0; | |
int candidateLen = candidate.length(); | |
for (int i = 0; i < candidateLen; i++) { | |
b |= (int) hash.charAt(i) ^ (int) candidate.charAt(i); | |
} | |
return b == 0; | |
} | |
private byte[] cryptRaw(byte[] passwordBytes, byte[] saltBytes, int numberOfRounds) throws Exception { | |
if (saltBytes.length != 16) | |
throw new Exception("Salt length should be 16 bytes"); | |
if (numberOfRounds < 4 || numberOfRounds > 31) | |
throw new Exception("Number of rounds should be between 4 and 31 (included)"); | |
int rounds = 1 << numberOfRounds; | |
int[] cipherText = { 0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253, 0x63727944, 0x6f756274 }; | |
int clen = cipherText.length; | |
System.arraycopy(KP, 0, pBox, 0, KP.length); | |
System.arraycopy(KS, 0, sBox, 0, KS.length); | |
enhanceKeySchedule(passwordBytes, saltBytes); | |
for (int i = 0; i < rounds; i++) { | |
key(passwordBytes); | |
key(saltBytes); | |
} | |
int hclen = clen >> 1; | |
for (int i = 0; i < 64; i++) { | |
for (int j = 0; j < hclen; j++) { | |
encipher(cipherText, j << 1); | |
} | |
} | |
byte[] b = new byte[clen * 4]; | |
int j = 0; | |
for (int i = 0; i < clen; i++) { | |
b[j++] = (byte) ((cipherText[i] >>> 24) & 0xff); | |
b[j++] = (byte) ((cipherText[i] >>> 16) & 0xff); | |
b[j++] = (byte) ((cipherText[i] >>> 8) & 0xff); | |
b[j++] = (byte) (cipherText[i] & 0xff); | |
} | |
int blen = (b.length > 23) ? 23 : b.length; | |
byte[] dst = Arrays.copyOf(b, blen); | |
return dst; | |
} | |
private static void key(byte[] kBytes) { | |
woffset = 0; | |
int[] lr = { 0, 0 }; | |
for (int i = 0; i < P_SZ; i++) { | |
pBox[i] ^= extractWord(kBytes); | |
} | |
int i = 0; | |
while (i < P_SZ) { | |
encipher(lr, 0); | |
pBox[i] = lr[0]; | |
pBox[i+1] = lr[1]; | |
i += 2; | |
} | |
i = 0; | |
while (i < S_SZ) { | |
encipher(lr, 0); | |
sBox[i] = lr[0]; | |
sBox[i+1] = lr[1]; | |
i += 2; | |
} | |
} | |
private static int extractWord(byte[] data) { | |
int word = 0; | |
for (int i = 0; i < 4; i++) { | |
word = (word << 8) | (data[woffset] & 0xff); | |
woffset = (woffset + 1) % data.length; | |
} | |
return word; | |
} | |
private void enhanceKeySchedule(byte[] password, byte[] salt) { | |
woffset = 0; | |
int[] lr = { 0, 0 }; | |
for (int i = 0; i < P_SZ; i++) { | |
pBox[i] ^= extractWord(password); | |
} | |
int i = 0; | |
woffset = 0; | |
while (i < P_SZ) { | |
lr[0] ^= extractWord(salt); | |
lr[1] ^= extractWord(salt); | |
encipher(lr, 0); | |
pBox[i] = lr[0]; | |
pBox[i+1] = lr[1]; | |
i += 2; | |
} | |
i = 0; | |
while (i < S_SZ) { | |
lr[0] ^= extractWord(salt); | |
lr[1] ^= extractWord(salt); | |
encipher(lr, 0); | |
sBox[i] = lr[0]; | |
sBox[i+1] = lr[1]; | |
i += 2; | |
} | |
} | |
private static int f(int x) { | |
return (((sBox[(x >>> 24)] + sBox[0x100 | ((x >>> 16) & 0xff)]) ^ sBox[0x200 | ((x >>> 8) & 0xff)]) + sBox[0x300 | (x & 0xff)]); | |
} | |
private static void encipher(int[] block, int offset) { | |
int xl = block[offset]; | |
int xr = block[offset + 1]; | |
xl ^= pBox[0]; | |
int i = 0; | |
while (i <= (NUM_ROUNDS - 2)) { | |
i += 1; | |
xr ^= f(xl) ^ pBox[i]; | |
i += 1; | |
xl ^= f(xr) ^ pBox[i]; | |
} | |
block[offset] = xr ^ pBox[NUM_ROUNDS + 1]; | |
block[offset + 1] = xl; | |
} | |
public static String encode_base64(byte d[]) throws IllegalArgumentException { | |
int len = d.length; | |
int off = 0; | |
StringBuffer rs = new StringBuffer(); | |
int c1, c2; | |
if (len <= 0 || len > d.length) | |
throw new IllegalArgumentException("Invalid len"); | |
while (off < len) { | |
c1 = d[off++] & 0xff; | |
rs.append(base64_code[(c1 >> 2) & 0x3f]); | |
c1 = (c1 & 0x03) << 4; | |
if (off >= len) { | |
rs.append(base64_code[c1 & 0x3f]); | |
break; | |
} | |
c2 = d[off++] & 0xff; | |
c1 |= (c2 >> 4) & 0x0f; | |
rs.append(base64_code[c1 & 0x3f]); | |
c1 = (c2 & 0x0f) << 2; | |
if (off >= len) { | |
rs.append(base64_code[c1 & 0x3f]); | |
break; | |
} | |
c2 = d[off++] & 0xff; | |
c1 |= (c2 >> 6) & 0x03; | |
rs.append(base64_code[c1 & 0x3f]); | |
rs.append(base64_code[c2 & 0x3f]); | |
} | |
return rs.toString(); | |
} | |
private static byte char64(char x) { | |
if ((int) x < 0 || (int) x > index_64.length) | |
return -1; | |
return index_64[(int) x]; | |
} | |
private static byte[] decode_base64(String s) throws IllegalArgumentException { | |
int maxolen = 16; // s.length(); | |
StringBuffer rs = new StringBuffer(); | |
int off = 0, slen = s.length(), olen = 0; | |
byte ret[]; | |
byte c1, c2, c3, c4, o; | |
if (maxolen <= 0) | |
throw new IllegalArgumentException("Invalid maxolen"); | |
while (off < slen - 1 && olen < maxolen) { | |
c1 = char64(s.charAt(off++)); | |
c2 = char64(s.charAt(off++)); | |
if (c1 == -1 || c2 == -1) | |
break; | |
o = (byte) (c1 << 2); | |
o |= (c2 & 0x30) >> 4; | |
rs.append((char) o); | |
if (++olen >= maxolen || off >= slen) | |
break; | |
c3 = char64(s.charAt(off++)); | |
if (c3 == -1) | |
break; | |
o = (byte) ((c2 & 0x0f) << 4); | |
o |= (c3 & 0x3c) >> 2; | |
rs.append((char) o); | |
if (++olen >= maxolen || off >= slen) | |
break; | |
c4 = char64(s.charAt(off++)); | |
o = (byte) ((c3 & 0x03) << 6); | |
o |= c4; | |
rs.append((char) o); | |
++olen; | |
} | |
ret = new byte[olen]; | |
for (off = 0; off < olen; off++) | |
ret[off] = (byte) rs.charAt(off); | |
return ret; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Test with:
Execution time : 130607515 nano seconds / 0.130607515 seconds
Second test with:
Execution time : 402475833 nano seconds / 0.402475833 seconds