{-# LANGUAGE Safe #-}--------------------------------------------------------------------------------moduleData.SHS.SHA.SHA1(sha1bytes)where--------------------------------------------------------------------------------importData.Bits(Bits,bitSizeMaybe,complement,shiftL,shiftR,xor,(.&.),(.|.))importData.Maybe(fromMaybe)importData.Word(Word32,Word8)--------------------------------------------------------------------------------typeByteString=[Word8]--------------------------------------------------------------------------------sha1bytes::ByteString->ByteString--------------------------------------------------------------------------------sha1bytes=compute--------------------------------------------------------------------------------(.-.)::Bitsa=>a->a(.<.)::Bitsa=>a->Int->a(.>.)::Bitsa=>a->Int->a(.+.)::Bitsa=>a->a->arotl::(Bitsa)=>Int->a->a{- Outcommented cos of -Wall -Werror flags
rotr
:: (Bits a)
=> Int
-> a
-> a
shr
:: (Bits a)
=> Int
-> a
-> a
-}choice::(Bitsa)=>a->a->a->aparity::(Bitsa)=>a->a->a->amajority::(Bitsa)=>a->a->a->af::(Bitsa)=>Int->a->a->a->ak::Int->Word32pad::Integer->ByteStringparse::ByteString->[ByteString]h::[Word32]compute::ByteString->ByteString--------------------------------------------------------------------------------{-
* [§1] Figure 1: Secure Hash Algorithm Properties
+-------------+--------------+------------+-----------+---------------------+
| Algorithm | Message Size | Block Size | Word Size | Message Digest Size |
| | (bits) | (bits) | (bits) | (bits) |
+-------------+--------------+------------+-----------+---------------------+
| SHA-1 | < 2^064 | 0512 | 32 | 160 |
| SHA-224 | < 2^064 | 0512 | 32 | 224 |
| SHA-256 | < 2^064 | 0512 | 32 | 256 |
| SHA-384 | < 2^128 | 1024 | 64 | 384 |
| SHA-512 | < 2^128 | 1024 | 64 | 512 |
| SHA-512/224 | < 2^128 | 1024 | 64 | 224 |
| SHA-512/256 | < 2^128 | 1024 | 64 | 256 |
+-------------+--------------+------------+-----------+---------------------+
-}---------------------------------------------------------------------------------- [§2.2.2] Symbols and Operations(.-.)x=complementx(.<.)xy=x`shiftL`y(.>.)xy=x`shiftR`y(.+.)xy=x`xor`yrotlnx=(x.<.n).|.(x.>.(w-n))wherew=fromMayben$bitSizeMaybex{- Outcommented cos of -Wall -Werror flags
rotr n x =
(x .>. n) .|. (x .<. (w - n))
where
w = fromMaybe n $ bitSizeMaybe x
shr n x =
x .>. n
-}---------------------------------------------------------------------------------- [§4.1] Functionschoicexyz=(x.&.y).+.((.-.)x.&.z)parityxyz=x.+.y.+.z-- [§4.1.1] SHA-1 Functionsmajorityxyz=(x.&.y).+.(x.&.z).+.(y.&.z)ftxyz|t<20=choicexyz|t<40=parityxyz|t<60=majorityxyz|t<80=parityxyz|otherwise=error$"Shouldn't be possible (f): "++showt---------------------------------------------------------------------------------- [§4.2] Constantskt-- constants [§4.2.1]|t<20=0x5A827999|t<40=0x6ED9EBA1|t<60=0x8F1BBCDC|t<80=0xCA62C1D6|otherwise=error$"Shouldn't be possible (k): "++showt---------------------------------------------------------------------------------- [§5.1] Padding the Message-- [§5.1.1] SHA-1, SHA-224 and SHA-256padl=-- length m + 1 bit + k zeros ≡ 448 mod 512---- m = [ 'a', 'b', 'c' ]-- l = 3 x 8 (bits) = 24---- 448 - (24 + 1) = 423-- 423 64-- ------- ------------- 01100001 01100010 01100011 1 00...00 00...011000-- -------- -------- -------- -------- 'a' 'b' 'c' 24---- (8 * 3) + 1 + 423 + 64 = 512---- Note: 1 bit is represented as 128 (dec) which is 1000 0000 (bin)128:aux(((448-(len+1)).&.511).>.3)wherelen=l*8aux0=-- length as 64 bytes (8 * Word8 of 8 bytes each)(fromIntegral$len.>.56):(fromIntegral$len.<.08.>.56):(fromIntegral$len.<.16.>.56):(fromIntegral$len.<.24.>.56):(fromIntegral$len.<.32.>.56):(fromIntegral$len.<.40.>.56):(fromIntegral$len.<.48.>.56):(fromIntegral$len.<.56.>.56):[]auxi=000:aux(i-1)---------------------------------------------------------------------------------- [§5.2] Parsing the Message-- [§5.2.1] SHA-1, SHA-224 and SHA-256parse=-- 512 bits = 64 byteschunksOf64---------------------------------------------------------------------------------- [§5.3] Setting the Initial Hash Value (H(0))-- [§5.3.1] SHA-1h=[0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0]---------------------------------------------------------------------------------- [§6] SECURE HASH ALGORITHMS-- [§6.1] SHA-1-- [§6.1.2] SHA-1 Hash Computationcompute=aux0Falseh.parsewhereaux_Truehv[ ]=tail$toHex$000000000000000001.<.161.|.-- toHex doesn't pad 0s((fromIntegralh0).<.128).|.((fromIntegralh1).<.096).|.((fromIntegralh2).<.064).|.((fromIntegralh3).<.032).|.((fromIntegralh4))where(h0:h1:h2:h3:h4:_)=hvauxlFalsehv[ ]=auxlTruehv$parse$pad0auxlFalsehv(x:[])=auxlenTruehv$parse$x++padlenwherelen=l+(fromIntegral$lengthx)auxlipdhv(x:xs)=len`seq`hv'`seq`auxlenipdhv'xswherelen=l+64sch=schedulexhv'=sch`seq`roundshvsch-- 1. Prepare the message schedule, {W t}:schedule::ByteString->Scheduleschedule=msg16.sch.chunksOf4wheresch=aux0emptywhereaux_acc[ ]=accauxtacc(x:xs)=aux(t+1)(ins(w32x)tacc)xsw32=aux240whereaux_acc[ ]=accauxiacc(b:bs)=aux(i-8)(x.<.i.|.acc)bswherex=fromIntegralbmsg=auxwhereauxtacc|80>t=aux(t+1)$ins(rotl1$idx(t-03)acc.+.idx(t-08)acc.+.idx(t-14)acc.+.idx(t-16)acc)tacc|otherwise=acc-- 3. For t=0 to 79:rounds::[Word32]->Schedule->[Word32]roundshv@(h0:h1:h2:h3:h4:_)ws=aux0hvwhereauxt(a:b:c:d:e:_)|80>t=lett'=rotl05a+ftbcd+e+(kt)+(idxtws)e'=dd'=cc'=rotl30bb'=aa'=t'inaux(t+1)$a'`seq`b'`seq`c'`seq`d'`seq`e'`seq`[a',b',c',d',e']|otherwise=leth0'=h0+ah1'=h1+bh2'=h2+ch3'=h3+dh4'=h4+einh0'`seq`h1'`seq`h2'`seq`h3'`seq`h4'`seq`[h0',h1',h2',h3',h4']aux______________=error$"Shouldn't be possible (rounds -> aux)"rounds_______________________=error$"Shouldn't be possible (rounds)"---------------------------------------------------------------------------------- HELPERSchunksOf::Int->ByteString->[ByteString]chunksOf_[]=[ ]chunksOfnbs=x:chunksOfnxswhere(x,xs)=splitAtnbstoBase::Int->(Integer->Integer)->Integer->ByteStringtoBasebasefn=aux[]whereauxacc0=accauxaccn=aux(r:acc)cwherec=n.>.baser=toEnum.fromIntegral$fn(n-c*1.<.base)toHex'::Bool->Integer->ByteStringtoHex'cap=toBase4{- 2^4 = 016 -}auxwhereauxx|x<0x0A=48+x|x<0x10=cc+x|otherwise=error"Shouldn't be possible to reach (toHex')"cc=ifcapthen55else87toHex::Integer->ByteStringtoHex=toHex'False-- F U N C T I O N A L P E A R L S-- Red-Black Trees in a Functional Setting---- CHRIS OKASAKI-- School of Computer Science, Carnegie Mellon University-- 5000 Forbes Avenue, Pittsburgh, Pennsylvania, USA 15213-- (e-mail: cokasaki@cs.cmu.edu)-- Red-Black TreesdataColor=R|BdataTreea=E|TColor(Treea)a(Treea)-- Simple Set OperationstypeSeta=Treeaempty::Setaempty=E{- Outcommented cos of -Wall -Werror flags
member :: Ord a => a -> Set a -> Bool
member x E = False
member x (T _ a y b)
| x < y = member x a
| x == y = True
| x > y = member x b
-}-- Insertionsinsert::Orda=>a->Seta->Setainsertes=blk$auxswhereblk(T_ayb)=TBaybblk___________=error$"Shouldn't be possible (insert -> blk)"auxE=TREeEaux(Tcayb)|e<y=balc(auxa)yb|e==y=Tcayb|e>y=balcay(auxb)aux___________=error$"Shouldn't be possible (insert -> aux)"balB(TR(TRaxb)yc)zd=TR(TBaxb)y(TBczd)balB(TRax(TRbyc))zd=TR(TBaxb)y(TBczd)balBax(TR(TRbyc)zd)=TR(TBaxb)y(TBczd)balBax(TRby(TRczd))=TR(TBaxb)y(TBczd)balcaxb=TcaxbtypeSchedule=Set(Int,Word32)-- O(log n) insertionsins::Word32->Int->Schedule->Scheduleinsxis=insert(i,x)s-- O(log n) lookupsidx::Int->Schedule->Word32idxi=auxwhereaux(T_ayb)|i<fsty=auxa|i==fsty=sndy|i>fsty=auxbaux___________=error$"Shouldn't be possible (idx -> aux)"instanceShowColorwhereshowR="Red"showB="Black"instanceShowa=>Show(Treea)whereshow=aux0whereauxlE=replicatel' '++"nil"auxl(Tcltxrt)=replicatel' '++showc++": "++showx++"\n"++replicaten' '++auxnlt++"\n"++replicaten' '++auxnrtwheren=l+1