├── .gitignore ├── 1024datafile.txt ├── 2048datafile.txt ├── Makefile ├── README.md ├── data ├── 1024-1024encrypt.txt ├── 2048-1024encrypt.txt ├── 512-1024encrypt-oaep.txt ├── 512-1024encrypt.txt ├── 768-1024encrypt-oaep.txt ├── 768-1024encrypt.txt ├── rsa1024.txt ├── rsa2048.txt ├── rsa512.txt └── rsa768.txt ├── include ├── main.cpp ├── sample.txt ├── src ├── BigInt.cpp ├── Key.cpp ├── Makefile ├── OAEP.cpp ├── PrimeGen.cpp ├── RSA.cpp ├── StringTrans.cpp └── include │ ├── BigInt.h │ ├── Key.h │ ├── OAEP.h │ ├── PrimeGen.h │ ├── RSA.h │ ├── StringTrans.h │ ├── globalData.h │ └── utils.h └── 密码学_实验报告.doc /.gitignore: -------------------------------------------------------------------------------- 1 | simplersa 2 | *.o 3 | *~ 4 | *.swp 5 | libRSA.a 6 | -------------------------------------------------------------------------------- /1024datafile.txt: -------------------------------------------------------------------------------- 1 | 973DFF6C47DA3D50C15868CB2EF9F2C329C561725C1BDE5BE6BCE7A8E1957C0601F0B7F315BB5285699669C1DB38F4F4255BE1D1FB4A184623F5DA6C616432C9536011782A808C5CC06584956671916300D1403737321E6AE43908CFEC34956A1A13379D476C9FE3080801F28AC07BEFEE0762EBB1E963B163A9714754BA8F19D69EC1F58C00046662A93EEFC76F511DA3123B8CADB7C0EF2605786CDD016F50A8E444242D941891845004ECCB848D2D013EF9690FC3F7148D791C739F27748E1F731D91130FFF4056083F2B86F5AA86527A2FDC8E1342CD795B5EC7ADDCF2672AC8BD73B8EAA185740995D46FF104F0928DB746946F0CEB6D8F03EE932D206AAF3876BD9181A0187D347426423E775D09FCE7CE4873C1109AF5C4383A13A02882B91950C7306ECAE1742820F480D60A57723455DCB42A7BFFF4B388F5B14253BCA6DD7345118DCF017A36F852B56469194FF887423BF414777117EB31F5B97E1F51A8F4B16FA3816EF44A62AA02AB2A37CE086F5F6DC0A4ACD63DFFB0167B86868A37A521AFABBBC37CF8CB68BAE8C5E23304E89E63AD2020146D45250ACDF8A345E7695251F88C973B3D2537EE1510B1AD66F83D4AC414F9520440F1405178CDA37764B1C94B8C9DBB1A649BC7A19FEF4803C4532AB30EC5F37882F4ECEFB3C6C9201CF94815B314F8B883E7E74F1052BE3070A40DB91E6CDF9EB403333613 2 | C7A503BF752C38D197AA4AE1D034FEB3983E1C9ECE15F8EBAE3F9AD1CFFE19885120702F933EF19A76473088D52E5F000CAC9599CA6FDBC4773AF45CDB21CA544474F6B475E9B567762C022653FB8B7841B6DA018D90A22B99CDC994CAA4AEA330CF4D90791EF352DDA42761696DFA1655B34B4AA92E054C4EE36FA65EEC3B3CC584F007A28F768DAC30B765046A9746E39C1268D494F0023FACE53154AEF34B7B5AFDA9E59B0B68E53181BBAA1E470CE340EB3DFD5A7CAB821FCACA9C6676A23F7DEA9AA0FA4AE8499CA3365E4329269A76E60A8850247DB1A2E259C26F942579035FE147C9A36194F8951595E7865A19C7299CA77A8B90615984D5DDFA1B52FDC9EC36F4141B440F879429D9BFAE388D33796F87557F3D1BF5084346A37D3423C8CBB3DECC03B638004008DAB68D6C4B93EE32A4FB56F501BD45FAB7B77435E3A8F66F88374FF62340B6071860B1F82817593EB16A60E96ABD25C7F5CC7EADB82185962968160598014DA44179984EACCD961D9235A3B95CB52C077668A8A9A6F265A8FD46DAA04C1724ED0A031198393EB46AE5B5F220FFE13691ADFED38B62DB4F94971F2B7B2ED75EF3E35E6CCD90EB895558B2B0D502B3A348B437D33E21AB5284A612CA2E3FAEF43436C85C6DA7B80C6B0A46B4323B2F9DC32214172696DAC719E8194CB7AB0E8239E9EFE8F9EC9BFB5A89A6A35929129354896232FF 3 | 94436DDBBD152C8EC54ACCC73AB3F51C76603FEF7B04D296FC8C8826F0F24F091EF772D7A0E2016876D4C437F2CCE7ACB1F31C3C1D2436720588D75487C0921C12E1DD754E3608893709700C192240C5D2D7282BBE115C109B25E8443348705ADEC0E7E293489AAE15ADEB0043DEC1B286FC57AEF6ED6039E8A5591F72305962E7BD9D25BFE3E1B8A3D1C7B86006655F603E4CCEE7645179302DA6A2FFE45729E02A232155F837F664C20D841B9154C25B729AD6837FDE541CE45B1034D5295E195B2CF6AD562F6DEB39596C4B4618D9BA9A9037EAFEB702A5691D29D0B981F39A14BD2B436B72C23197BA73314F23E463D0C73F35D609C691AF0087337CE9C6E1D125D17776022AD4F6121CCD435B3578A04047172ADF96050D716CE24590734E90EFD5628F3E1FEE0ED4ACF12D5C578BBEB1FD67CA9DAA208D11D49A74B9C67A0EFAA53BDBF619C2F55116DA87E23E69367C97C1AAF0B4F8ABE52CC2EF412665DE7468F676C7F6CF511EA31FB3F67C4D869261155F7F8D45A7038FAD0BFA83FCE4FDD879F7F6AA77F8F3981D35740007DE520BC07B8B9172170E774F6D7F83DFDE9E760C3D8BBDCF7CD5E84756EC8B2538DFCE06957195FD5BCD34185E965BCBDB1B01B00ABD84A45C6C170E5F6CE57400C55399687F44BB9D49A500174235FD9DEC67F288577BE6269E46158B7FA11AD88728FF92ECE9F46B923DD9AE80A8 4 | AEDD33D7941695CEBC46EA8E324696AEF9309C5B970904E293DADCAFD26CAFBE4AE02C073CB7C5F935DE6F24E6E2A8026FE5D21FC4AC61BC15B980F71BB4433EB163C8C6D0309FFE7AC0FBA998B245705E2B625B1B2194DA2B3470DC80088982A5991977027DA171DB1AD7D12F597A6601979CC25F50E775625ABC35F5299B67ABC9B2739038B0BD885D854F2544AF47B80CFAD0ACA3D22546BE4AB45415CDD5DB79BF2A45DF19D0FF6D012435B6C56B9DDA3A92FB1F9AA917A8768F0C92263669F4D78B6B2628CDFA689909FC0BE500BEA843F5720F15E09B7F5F26A242DA49283024F61225AA4F34EAF97B107B88F1FF3A3F41FEAB7AFE33B264536EF580DADC4CA58023C390C0F5FB51A1C430F968E29AD5ADC0FE35AFD6FD941EFF5441B081F3439CB238C7B949668352F364A88ED4B97846A787D8AF6C5EC89BED8782A18D29CC3950260AB21ED1C77CEC9ADC6E4F8E71F3DC825F3C99100B4E892B911EEE28ACBB55FA48432521048EB9560755EA6B2BA8A63AC73AB7D5E08D0EC4EEB7AB95F4F627448F47A2956231C61DFD4D358DBB16CD250AC996E49ACFCE9B71B491AEB9D41F203D789FF2688C14D0F959FBC6AC42A29CB98ABFE89DE76049B0CBAF0279E8048B20A2F486DC52916C2A5F4E113E8CDA4E0E2F1750D1C31880ACDF8E4B2D939C2FF49FA91CF6B92BE6A2C136644BFE7297AA2FBB63B8C6576E706F 5 | FFD19538A35C87F2EF039A30F7D57FF1123C444016F157D6635F587D316848EC4B7C6E12E478BD1C65789B49FFDE96DB21FBF5FAACB27B36000FBDFA0740C4F6C67EE3E29B2D6138C5619F14E4D3ECAC4A81D01AF1DC28B6E65E1A3096997A2FB47D0A2165BABBE19301BDAA23CF629D89D87D3228EB18C757EC3EA1EAF14C04A844D5DF28569611011D5594D64613B9A8013B4FD2F04458680F94B56F85AC68D71A473587D80D491E63A62B6950C8E41D25076C5565A4A8AC9A054B22E3927D964656445A0BD56F6E285203CB570706AB1D109E72490D8F5B7B5EC181DE17879AEF67CBB4D326D3E9273A76A154288228DAE6D51A00B992E1C1E30F5C4F00AB9B7590450A3FA08AFB1BD3B28B6431B912CFE4BE690856B08CF03202A83F62EC12F6AE33FA21CF6DF5B131EE9621294D04536E55B871F3BD9419135A2DF4044768DFBF18EF749F2415189F25B6E42C9E3E94F145521B17B0834E4DE306D98CCC319BC3DF914DE57ECA7292EC5B2BB4ADA885E2EEFDB1F6E17184B61762A9F806B89A4BAB25627E49E8FB1450631DB4D47856CF8A1E62C3EA5A27BE40A0418CDBDDDE4AF6A9F5A1DD77995F989E8821340BCB3882C540D617D537C802A58CE4F931ECBEA3C1E36145C159B9870259C3201C03BF021EDF0DFBF5D710EAEA039B35BCCFBB961C225A5A84AB29A4EF909CA82B36EF88A64C3CC8965FF17CA04658F4 6 | A0455296B10332B8FDFC8ECBCE2AF8D068F2252BA8F19584A52E3595FA86508630A716CA2929C47D89E69B59B29C0E85C56BD30F185E471233DC0AFD7958FD9DDD09E66A99ABEF52DA095052F8952471C360AD13788888EB56B0FE765B824A936AF4AE41662B1B89574E8180545944F1A07BAA471F91572A4CF121F039066DF7A2BCBD926E07D15A3FDDE3FEFF8AE52E8CC98258369688C3FEF5699C17BB2C1817F5AB1356AF51012EBDE851A597207D8A93E2C2B48C6A9B999A1CB7871EEA89B7AF011212EE193464FC27F934842FC1A4784A211B2E87CFBE9B986F962A5792DE7A182B1F02514D011204882924E74A2C464B51A449151039E0C30B98B4104DA75B6365CED3F9AA0C89F96BC89FF6F2E05734B1E5A7E15698B018E2F9E6F6207C80F6C6E9E7920743215E4D70752F7C59ED5A84A8D68E652E76E2CC4533373C6279A8F8D1BBCD65F95F87CF5245EDA924BFFDE65DDD9F4E98A2A9EEA08AEE06D11C216C0F29BC619C14266EE1B1080801844904DC8D981D71B6F0C297DF6BAEE1F98529D32EA7AA8064E60E61BF1903CFE5DD20FC0138BFD98932759FDBD3506EA1E6A760318B18DBDAA7CCE7B446A0073F70CD5090944C808852D426AF7CE9E918B8071EED75C499B4D35C143B998C2C061F620F5A976DC4D579E7FA30D9228AACB73C186B74EA0ACA683EC13EA32D6AAA0450F7E4CF48CCDADDA307D9275A 7 | C385BF0CE35594B975B9EC53811469A4A36D878909949E543324C800BE5EEB86DB5B2BC18E184FFEFD0B25BD8859D9B6C15E853D47EB9D3E402279E2C250D493C7373C78FE411D54E6E824485A7AD4756FE075CC0829929689A1576AE00E2AC0DF67ED3E7854076FE5FCFF6E2E31FC22C646464F95CE690291FFFC09F99C5C30F7DA11782527D700E6C26DA694616E176A7B194A85BDDA87706BC57AA972707F8D62540912A6D1CC061721C2A958586B210B49FCDF1BA680E67A483DAECD557576B848EFF64B8569ED66910499B6973534045B7DBE0EC08B50E9A213921C2B9C11C5E762C7BB42C92A5AE6685994A786760298D9074CB3012775F688A84A6753B25132723A16ADACAF1E04830B1623555624F8AD6B22AD8F634CD451AA3FFEDCD58113EE5F5238FAD745A88B93EAF22107DBC1BB20714580D7965BBA83EEABFA0470EC477A01761AFE24013CE20B383CAEFED22A6EB1499A33BE0D8C646A86C9CCB259D1AE86C618B8FC299759F858A87FB16BF3627020A5D7D59062864F139BDF99564ABFFA2E8E732F8880099A40F650E525720EFB885094BD650CD714985A7FD8298323E76AF85FF5887389C08309CBC746DAC6B99AE1A34FD69ACD9F07DC3DCB6CFBD363C06FB6CFA67F64207331D6E33A48951885A8A09C541717616D4F4A68FF28CB03C014656FA27FB5461FA3EDD0DDA8608D1680547AA0906FA12331 8 | CD2F124109F9E9B6DC3C1B381D6E06866DF4554E0DD4D90889E20932D87DA4D0A8C4867EEBB925DE0C9E1DE9345CD649E31D257AF4F5A08009F2BEF59853FDCAD44E1626F7296D2B5D942C3F39EF4B854E6B5E02C7A8A34CEED374E65FCF5F9F43B52928056C4BE3045873AE2918334229408B7A39CFBC3AF5542308A687A048EA5451996D57D03BB68AD5B12ABBAA237CBD3B48A2919F71BFFCBB63B790889A1B58B1C8DD7E5DEA742183C806C27E9BEC9CC7D939F339AEE22BB62AB0E56708C30726D523975505C8A332AB19D6C1F442E1ECC74C9D45EBD970A129AF6CB30180281D6883F63D1ECC059D31F886DE0AC5C2D6782E4D3AA42DCF96E39B31B7E4EE37EE8763F55C33446CA7A7B44DE033C940B43715ED537AE3CAE851081BC8970622B8FE3B4E1A1FE7A13093538B73C163B431DC3A9D0D0264208163D97E1066AE18F234A7F9ED25E4F94B0FB42DA4DE528FD3C99C8A82C7C97A7F29BF8706FE3BCE2D80F1B2ACC807C3E3AFCE931F29C5FA41D56A010E95EEA1E83A5B53F0B8C2BA8D26ECD0B2584BE391220E18E2A7C536B85A0D49B60CA1E33423CEB5525FCA7F5C957F53FF4B0964522B60968CA67EC5F5BE28A47354768CD4D414F5A686A028B680DD88F7C868F5E8FB68ED79B22F5AB7B6143FB5E232A3292AD6596CACACD0ACA8197E665B52E61A939980C256B1823023A937B73378DB73D251DA46E3 9 | C6830E08F3200450711B703479F8BC5BCAFD5B9377589B8F3326EB25F04F67B6E99958E811BD08B2C6D342EE3A26B543A13603147CAF2D22C32BE142141592CAF0A24BFC303199885C32A6955FAFCCA29A7E552F2F17486FB480BD6BC1CF3A7227A807D0D1C96FAB8D9048D284A126980A2D5C5D04B283BD214E8231C67C955CE7BCF59EEEEC9016A87F6DFA07E27FBB4692B7537170106B175F1ACEBE671A259B8AB2DC3771496C5EF3F2B121C346ED9643ED3FAABADCED9854D31124E91A64AF41AFD6BAAD664584025C6FF726FF8E237B03A2D8CCCF2BBAE7BB8B6A1BFC214BED3BC43140320B65962185271DCFC84E2F35050900E190CA028C9F0C930F8CECE64CDDC3D015D1425AA9BE0B8EDD7B37B3BB6AD7D8B375438257A572CA28441F216DFED714186C83470CC2654F30DDE1A5D1DFC0D5A655A3EEBB956929CAAE7A44E6652C8331C9E78FD9C98681C4055A1740A7A7A2E966EB2061DB2D68AA704AFEBF8F6B17D205D2CC265317FBC053EEBD644125CCE01A579412555CF32B2DF362EB0CDF6EBF22174F15B885D28D9B3E12D9E47C3BE4D2FDF7049CB7B15BD371B72F005431CABA1B9AD759552A2C97E1BE5C76EA3F4E8EEB69F6147FEB2238C61D0116FD2BEC5D81252876E8E0EAB4BA184CB9C8481CB42BDC80E25E55B537059A79137A07E308D07D9145DB92D95B5048FBBAC384265D627C32F415316134 10 | 93BCBE21DE7C140B5496A25C40629CAFAE7D17ECBF7355005BF83E2BFE3745D6681D92191D6F3E252033455BB8B84BEA754922D401AFFF5D42540A30E20916B7FF10C874AF2BD0E406EE39EF866CE158678CC612AD1DFBBAD5FD59DFF947F5C05CE582B4388BE3FE605E98C07605EBC673E963FADFFD1E5AE9C3899EB5A7CC6E9877B674A1F1BC984719894CA9D4F2563667398C0E544AECDD018415620E4858EEFD7FD0C457D57586270B213631DB026C5AB2FA0B3054E4F27F7B716991DAAEFB1A4FC4A56ADB62262D734A9B5900D205D8BB7EB684D271A66B0BB84F2085FC49187B29E730EF8A536E893B9487527C4D95C8A0460E07A11D9176C45E1A2A42AD76E683F37236516D495FAD52BB74E98B50BF9675158312C8F23617DD0DE6497B015A21947846AE4C6F27DB40D9B55382B66F3E4DAF802C1B9BDCFEB649AAAEB15C364701A32AE1B4A10D0E60C0021C0AE7BA520DAB5A4342DD6EA80F22F6BB6CA336EDA4D95CDD11585CC86301B0BC50B8DD89F34EF3A4F75369DEC83EEDAEE43032238AA7FE34323E8A0F4844FB901F466C38C3CEA5B6C894485DDADBDF476F54AADB10E9280AF6A520B9437AAEA77C6A77AD0CFC3522A8BCBF2B0ED66074BC8EA9C764361AF0EA2ED6F598313327BCE0F9385696FE55B0B6356E6A7A9C5D78FC78DDCE8E70A62855150C772D6F5F4E7248A6094A440D965F04CA92AADA1E 11 | 99BA944C68FAEA6BA0CD20A7EBFF0C61665C7B7C853D6FC916635F35D1874E339764D087A429407C2F4055B55DCC30EDC07A274A465D10C1F8D3CC9D945FAC329C9637DB047B3A6D234FF4CEEA40067E9CBCC5BDD68E179FAD852524896EBB30AD6BE08FC2E396DC191FA8B445A579BECF789110E80A7E1567022BB7D5362A9DA99AF519C9BF656EF2BF8CCA8A872120775B8E2C503FE98374671279F7D1FCB674242CB9642032B5B162AF788A6254D357BC523875476731B3C13E05B55DA5C4B9A2772E7A30A176FE365803B153EEA7F6F12D83CA92DA2D08EAFFDCC7B5980C6A35DD0619DFB729292E01510EAE004D1CF5D393911FE441520C89A51A124A07C4C6057509970DA35BE5F8A557520108D24431BB02F92544F6B14EE422E38D7B103652CE6E69B566C914A2C428651E3B1838FB0534700675CBA5910F537746007426D313B86ED1176C8E0200DB24C0144A90942740A2DCB9BF2141D114B7D4CA4A77681F95CB21A5EDC8017C8AB86F9D02668EFC3AEEA8760B26BAB4645CC572FBC5EEDE57FC0D8F1B2C6683ACC35EDE47FAF133E3380FD82298C232AEC70731B57EAD1933C88EAB32F35CFB90178A903B00C4A5C54555C865CE9B3FF43776C85844ED655D88F89D385E076B954AD3C100288A9AC0865ADC69D8428720F981819B5583AD984D6C4C58BBF991C7EB56B79B621B993D552698BFF8763A98959AD6 12 | CBF54D3C9E4470ACF8FA8E55959325967846478A4917E6A5ECDB9C68B6CA09F55EEC3E1D020629037D7F08712291D53F3BBDE24B953AA0F2FC12B434E02E9185068B743FA9E60693646FAD4941EEF195EA1EE618FF7492334993EE7533322729BC24B1AE23E53326009969123149D1EA1A9EEA03244B4513F592E987C68680A8BF962F32021AF4BED45AF6223EB225D1F527368F5979B7A972AB1AD2AB283A6E8AA8CEF4C816F1CA76930680DF550323A370A994C0DDD0D6BA1D70796C9BB33D9C9CB6DFB4E1DA68B95C69A8C9D9D31BDFD0A2815158D14FBA02B236D7DF53A7C0CFCF80755F939AABF6B17D316701FF4987D376D077F2B8C599F6BBF7A40D90944FB9ABBA2A6F2641FE03BD5963DB3B40C5C663F60AD079A4D403670E6F394D3DB73BA7D92E52C06E2D63D551883474F897F5A49B45B5A0C2FA6DEA90631B54600F145A711E88180974061EBC75DB2EED835065E7BC8B5FF1C5227041BF4287F7DC4918C2C164D8E86BE39790F871A8FB993F91B2EEB9B50AFE2E9AD2649C3D9C18F931DD267024FAD4F81999B87F32257D4BBDE3FAEEA093336419D9C0D0ED76DD6EC1747E6D182DCFC892946047DF6A7AAF5AD6EEAC476B8EDAC6D6D3066F201F3990AC31BE93B80C2784B34B59173DE03EEEE6AC50F4A4398908BA140C063AB6897D3E647619D356AF67B7CDF2DFF3EBF765C4F15824426E3185DB6C11E0 13 | E4BC17334CCD28B0FB4849AAF610B556210F72829F1A110A755B98D90A1B8AB837DA9AF31A9FDAE01F33E66C6BD9ECA889B07ED1043D2FD1ADAC3713F19F4CB46599C16132ACE8D7ED45E84BBE95B9538679225E98BE64DD3D5B594CC104A698E5D80DCFC5293DFDBAC0AE190C86521D7FC3A091D61423573C212B04FA1CC4C7CA1EFE42081B89B7DF07D3ECCFA99CC2F546CD01030E3BFAFDBBA005EF3A43C8B67AB4CEB464E201739D328FEA061BBCDFC502993A3A0C41DA2F524D53CCE8141D604EC132AC568BE604C85545C65779EC59428CA710A0BD88A289BFD27D4443FE23ADE672D961CCF34106ABBE55F5E7EE4021B0BDD64C127255C6ECFF38402BFB65629097DC3BF906D197AF30DD7D32CBE0EE41CFC061295D740201A552340BB2122A3F80A5A8A513510F3E7ADA1A3800C414D1F0AC1D04D6F10042C990A2D3E8C20216FA4F11D124047FB4121563ADA71F6EFBB0784B0F48172F972837C51B647EC90E55DB9AB773ABB053EB6FC5A7BF042CCD7B8D83F82DCCC4811767F87EFA940FA6846BF7E85F2131872B77EC83EE0AC64F0EF982EA87748AAC269C606B209015D9A58B49D6581BFA5992EFF361A3F30AB10A7F97A2B3468AF6236DCA7A5A2D415566DCD28672877DCFB39CA056415C380D217333212FE111DC5A8C708FFA57E0415ECB15E53FCAE1ED75217F399A4E24C7597537D63EE9081C5F39CFF5 14 | CD7A01A1212A95F6466E7710BCC5242689988D8F287CBB5F3A4E7C159397E32F464A2A59436DCEB5038C458F60092E78385273A7E6DCCB3C138A3AE02B6CCF348A917D8B2674AE384BD1D650D73B2B596E7F6BFDAAC5C5B61982BABA071BAAB132345D927955A031ACA260BC718A2EA1CDB5299F62583BD3EFA68349008080D3FDA9FCF0270131A511A5BBEA82925E522C511743EDB350C7804A93C92751BC2B59303C5DED695905A9AC960DFA64104A99439D6142DD6E9EF3A13E714B89DE6A1240DAD960ED688624014C91300FB7C2FA872C8D5CF0FCC30B7D520E2EED011558C29DDCDE3862B4A5C794DFA85689A4B3B0E37D4E7D0230CC1C8509BB013D66AE9C6BBF33ECC3DB0952C793CD11D4170181EC787F9DDF1535BFF002A157C0EE96103A91263A0C30D186A1FE70A83FD0AA6AA94D9168856E7BF13E1F6FA0C31AD331770063C7EB342DC0E144E5927ACA78FBDCE9870D9F1FEBC674DB7718A65F2E7D0716B4FE9A44FF240DE3DDFC60D3F8C4F53A71456864A1B42579E1BCA2D2BD84C244B8D25CDECFF110A7E7C8F8E8D1BBA9E759DC5FC076D852F05B9DAF5C06A8888EF85AFF67FAF723EB6D21352CB8CAF898B7BA62049864CF6CEA260100028F4D7350382F565731688FA7DA36026EFD20AC48D43D5C079CAAD2C5C3EE420A4C2AC04E27C134A5923CC3996EF70CFB40E903160B785AEAA697339B19E4BB 15 | FD734970BF34772DD64401A1F9ED10BEECAEE23CF5B31944450AA533F2EA8D162D97270C9B30135DC4DEFF0C4F063AC232FB3DEC7863092B24467890C98256F3AF4DABB41DEA14DA7CF4C2EDE247B4F24B519D7A67DA4D29E0AE5B760DF5925D80B0D136F00BDA9C546603CAE7FF5E71A087BFDD2FD966D0F062169148B0D80ECA00948C20107303A60824E5DA891B3BC0200C8C979681B88AAA79149F6CE1E6E92ED9EA723D47E0F5898694802B08F9E48AA7FB87745038A40B02B0EB4884A02A2F9819E85D33F2018CDF9BAC3A441C3917B5CE8A3B1FCB22ABBF2C2025DF003753E1CD005F7A6C9A964D6DF802C86D97F21A388A5A68387AD3AE9F815E8EFBCFFABD7188AA3ADF76CE2C3E7BB45973CD5C2DEC4BB536B250B74ED501D95B229EFB4F0F9084A8DA4BCCEF79316341005818C38F4DB02F3C1C9DFD7544B92545E172FEAD6B5939793E5ED2F56F3B4680D3BEFC06838CBF917D13B18D141B8DDE0F8A9EB1E525C44072413F6296B531131B2DB781FF4B5848A877C5F71EB0382097E01741810E105CA306B79908929302E1B6E524A5C57326DDF410C80E8A649B6A3040A8A52C6E486ECB9EA6C530769B0963A71CAADC87575DCE27CAF0D7477A0BDF22D361338A9DD4368163202EE1D863A7AD5F3349AA6F50B206174CA579D3536309A3E15FF5EC79868D2B07BB41787C6F742CF27F6107F7A9C8A2F53779F3 16 | 8BDA462CA9D5ED4690F1CD79E20951E20538633C7970F12F9BAA441D6353C90DEEB29AD6980346528151BAB99C0F93747E108FDD822441A9397F0A36DEF272E46916D4A32D13A80DCD16C5635848E527C2CAE484AB6938EA3DED60F15A287ABD9C70D8F9D17ED133A8A05D5BD52E039A03C4BA5153028B9B4962EA49DF2694E785EFD1CCADD9D255D01C5C5EEC57AD67F6B17F454551E4B64747103C1A87AFFDB9DB60BAABD1314454BCDD7C514C9C5EB2CBD30BE1373B395B3B1A2D84C7DC79DFCCF23AEA2619CF6A5248FA81610CDFC63990DA0BC82CDF84F61B89D97A77BD468A5CF020BC923E2A23B6AE08974F871FA683CF9DCE8250DA72EDBD0061C278F8E79AC7734C845440C1BECD2E7201B0B6697B362AD25904BB8C3EC27C3F7F07763A9A8A642BAC9DFECBA4FC2B92D3AD30A5D7F3623380886B7CEFF5FB3789DB5E937B2FB45988B7A1509846A0B0CD67D2AB35D84D19B7DAA5AC0A6B5AFD20ACA6D369CA7D64B8E359BCF272625D9EB450BC60BF041AA64F5256B8B832D5487D92028BE6184280020521796C34B7BD56AE1DB0F1FE06CFF1E3AD5B8130A351F12E7B380AB262B4C800CF89719D8236FA123E22D9FAD7A07558850AD2FFB38E42BFBB52D33668D7FCF8412DC80A08CA5E0D30328D4D59DDA4293533630011665DFF4340BCD9AF0AACE9AAB9BCD4392D42F284FB75C7296B75F8698AD023E7BAD6 17 | 85B49ACAED1147E674248DD6B02544AF0F0CE0847898E15EE7A5CDC9277DE87589FF80721123C5CAD93F5CFCB1AAF4226BEF532A55A5C54D6DFEC11A17780F963FD38DECEC379BACC4212E00C7D8B6A837A6E2DADD1EDA8DBFFF7005D641D8DC12B1E29027F9AF75ECE00C30615792638619014F81774E4B69C5BF976ACB27F1D021D7A19416165417DD3616B3A0F0C8E1AAABA8B4E91ED2B939BC6E3E733FCB358CC86525E974E127E577771402E7A560404509FB79C9D30C701905E1763E830E9EE71C3E444D8A0265B0AF438B00F9C1E2B07891332382ED5B2C150E82138BBCFEF7061BB2FBFC6AA0B269D382416F43A7C67893179215D4ED9814A7D64614C7E51C7D45074E0E6639225A8A8A8759E1D9A56ED812663C555393B9A5FC3D10E863B69E679EE1886A74016CB26FD67F0A0398544B45D20E4E4F0C38FF1E5F2EFD7385E34DD2B68AE3CBD818DDEAAC102D8C4B56946C685F102752795D3008B5B9A3DA9B944BA49EFFCE3AB3EDA98949A0DC9960FDB46EF9999057ABA0EC1209E12F2E9B7275958A22972DB9E93311D0FE6425501D231A31DF34CE1BBA0EB9ADCBD937813C7DE15FB6AD23829466C0E5ED4702E759AD07FE6F26CEBE7B4080AB73FA856A0E0B0AF3FB25050B3C281487D3A0B38073BC2B7838AEA456448B720269C6492B13F4C17532EB886B697A9550FDFE0D915C284C8F842D1793885EE558 18 | C1EC7CC8DD57EA3699F7F51A84E18CF63CE183324F8442489A309C8633B380111DA4C79C3AE558F6AC3C6604B79D3521912E8EC0FC6E919242B41A09CF946744B5CC76679BAB3F641209F38A9DAA1229CA8D15DF8AA9F3B5E2D9A6AA96F41A34D3549AD62440FD14510A9C981524076806C6F45711FEA1E903DF87BA72EF107AA5FCC12EA1B0B3AA4991805D5201F2BBF9178DFE617A67EDF12E8B7123566B98BB0C853068CC95F19264015104214741A05DA02A2C33B311FB6719F656569FB2ABD7B586FF77C9E30E82C2BC096638D03A51B5BC059DFA1D593D12679784EC6DF5EA725FE9BFB081902B002C5238472C5C90EAB18AF5ED9C8C58B35C4B993489ADAE45E3C81293DEC65A7D42C5B5A5D1202B4C603406BD41B7B6781C593A8A341F77658CA8F2A23E047FB4D10EC431B30CB793A5958944C516D743BA8C7E49475620B53C4786D491654D8D48591A3FB577153657BFC8A74A24AFCFD29C64771FEC94E76D0FA126AAAC4C226F2B12EE44960717D9036CEEA9E3157286E2CC5C428F3EE196E4A19984A48F625374C73629A79ACF2B74F59976167F17D1C67FA46564CBF2D0BD5D45DB187D255A1CEF0726AB3B85A91A71FEA9660EBD517F4F8FF5597CE2ED5F097176791FF7D61B402CC2EF495B01ADB4AE07F132988260A8DAC285043E6F9E781C438854A46EA6335FD20B816702A89D9353D137C25A5A4105D2 19 | AE8489FB30EA5298300EA8F43650902BB47126A6C5CED2E2C5DA328C3FCC0F7E8C099A89359D3A402603D6CC96BFCBD1230326770D70A0E23D8915C0965D7DEB6CB453BAA6179880DC7A8EF4908BA71C68CDFE0C0638224AEFA61C0709D9BE796587AEA454FB3E87E701D599BAF299234BC74AAEFB07CE0240617EA9759EFCDCF949E74F5347DF0B27D2663A8DAAAF1CD64C2FC7D0CC95914D19378C14E3859773B858FDA3C8DEE7DF36E4C1E6385B152CC1A7567D358F47B1903C14330DE1F7DEAD5A72A6FE04AB4E74CAD93EB42F190B07DDB20D563E1C6926C16E8DE9C07C12D13D41F1A515743ABD2D0EE441C59888A7306CD2F22F0DDC1EEBDAE93CCDBBC8C9A97CBDF8DE3417D2BF21E063E16D1E625DCF7E825532D8F3616AA008D351FD767B24206DC35BBBD5745CBAC8089DA98F271CE45DF0FA8BFF8170BA397D72424A3DA6A6F832C036B720B4BE7525885F84E6CC72E85FD5AA2AC5CBC697E994BD27ED8A80829380A7831A18A43FC0CF63E54A63F4CEA1601C4098BBF5F56AD8DC7D5514838EEEA481675D9E017CE84A3B03E5327005762088ACDBF3A496353BA55D242F0C7F539601076212E2EE7C49B4BA271F56009F310AE8702A18AB9162D5BADBC35DB45E4F249A979770320A23FE307855279DAF6AB5C08EA9EA23F08A6544EE41B43B27FD2CD9D7ED088914828A22F0323122D7745605B03C5489B9B6 20 | 887603A5E8B81EDDEF82620ABAA08BF4ED91478C04C9A62D7EDE4A395A564B665C29C48514533F72FA23E03F690771AFBBA0CF94E56EA663E56993FED8A31C200A5F17AE249EE7771C781B49D93F21CD85371F3CC2ABB54C6D004C641404DA67B984E6FA35E2C2BBD35FDEFCA7D64B384E01193011A320E3C5E28A616238412EA7A81E58DFD887F5EAAC93EE337DA780B1D7BF0E7D02BBB8A5783B76709BB255F0D7D8C4216308A28360F7A8BC775A7E70806C998B24EE84124300089CD12F746F2EAD35A3ECD2E755A20C88ABAB3E069BA94FA800F95A02BF2541C7FCEDE522351A24DFA4FE4BADDF9C0D28D0EA8EEDBF68EA0675305BB81EE1050A14A29ABDEAFCB5D7EE39515957C3E66DC6A018F71327CA945D7E735ABAF77F53F81746FF63020B547EB51099A5BA1B5867717943D3075187C7149B8CC0385FAB01FD435E1BDEDA1282BA353C244A54DC63BE0974D1E2A5D0CACD5710F8DA10A8B05D949655AC9324E7CDB25DA799B0799824A8528454750CC726CB0281039D01E0FC5C20C1A55C0A142CBD0938EB9F06E0CC5117A0D21D6F8AC1B2AF46D72A6C0E746BB4CE6DABF2294877C464094FE18698ED4F2DF744AEDB6D456CE940D431F00077BB1CA2DE81A8136CF8D21BC37898BA9EABE013247B25691FA644723B5AD96E6E19127B121B24C8D047177F97F63A3DD490375AF2F6270540C261A50D834F13B0E2 21 | 946447916157CC0A74E32C9D2C0FDFCCC53489892C266CC927F7EA8BD7DCB1B09B00A4DBE6A2115373EBCCAE34656B3059A340F6BA5CD62DF286DAFF7B886219276826CC1ABAE3B06C3BC4912BEA51B63D25AC9BF7D8684789E6C1465A9618EB89CF4AB9F22B37144F37A29EC7841F3F48959AD8ADA5452CDF2F8643A2F88987E30804F330D217CBC244DAC22A28286AD417B92B5EB9C103552B134F8B5BD0403C156E593B3380CF60BA1D10D4CC9174FC6C391EF0F502BD3E7B21A1B0992A9CEDA7DCBE3B4E61CEA701DED4B53DF1BC3E9673B22850810406325527AC4F9E5FDD82B015A1EF22096FB032F2EC2FC9E48D9A9C3261C772B8197EAAE4ED3A2575FACA225128198A222B3F12A991D36ED0F8D099A02F647B5A734639309A4FAAC0D06916E5B6D6BC96F86D888E09D3AA85AEF1B426AC9424A1A200DEEBBA6B518AF96343616DF5B1BBD9A57AED8BD9746196E9C157BF85FFFF5EAC5183BF1EC42BA246E441DFD230C47190548AAB2DB134AF2796B0DB90E2F5C0B5631072654D22A9F334CFCB2E1B3E28E14A34DF06836AF2D1A4823C29235F8FCFED5A5BF0939FA7BA7C8D43C72CD3BCD06B3778848CF9A67C7B398FE1795F3C41FEDFA1CC6136118CEC3CDEEF7B5667EF2F99F224B7808428CFA4B005C6529C142096BC7C6A117A50E171160F86BB3108086B0C1FA252050B70343BFB41503F5EC11464063E53 22 | A4BF8A06B5F7B68E7A87D5166DE28DA16616AB6697F41325DA997AAC4EFE5E9302511A51B86A8A97E176C1FE21852CF3D0DB4EE2ABB1FAFEF538C61234E92327C44897001371A84BE624581B9A9245471F2E838B95079794942E51CD2A7DFAB2D3CDC29FE017E339B3463BF790DE62BFFE8D7620E643EF6216F9C61E848D57FF99EBB6D55ED6A26643584C0069939E102CC90E88D6FEE6E2EDAD520302F3C24AB0B78C4D5F049CEE3341797EDE6FC3695E3C6062FA3EC5D1D10031B8C0F9772DF94F4744CE51A7044AC7D05B39C4A021D7037F560F0EC5AFFBC21B1402893A4304379FAF6BC5B3C2A50324B18571F7C439466A6AE068995FC78E48AF5DDB159BBC10D0C2A823A6B74231445C4E17D7B9B1EBA9F80ED218B32174D7E0803E4978FE655EEEC4EB3160E6226ECF5F1554E97F0C576DE704D96563BD615516C42BD9A1DCD8930AC6A1A98083556B42197CA45635D01BEE88A8C1C04A364191B1D87C8BC010229F62177AD0D9D37A1D9A09DB816B1AEF908752F2A5EB8D383C23D1FDFDF789794DD4CA4A871F7FF485EF5AC18E3189EEF7C466C48074ACECDA2A84AF52F84409DC0BD25353EE57A83A638A9991020C2E92DEAB0F59D6F86486D59F519ACC4867AEB81A395ED7B37B946AE84AAD90E01F9F84F94EE9C1DE6C4A2E12D86A93C67F5C6650985F5F7AE5E1C96CEB57E41687224F603B702D769523E84FBA 23 | 89C732BF9FF7A9D252FF17719B2447847A6FB094A30E885C8DE14EE3B4F6A9608A1D0DED158E15C6D6D713F6F3C983D2197121566BBE1A2F96C416B3601F8C4736CC6EBF87EC130EF9A980CE052F18B20FAC924C6A6DD372B697289D5FBDA98FB852762120CC950FAF6A27E719FB1BD3F5EDAA4EE6D982CA8D5F2A5B07B53415D52913C40240AF8823481E929A768448DE04ADF94DF6F1CD975238541EEE3A0E6A5D4661D68ED4F2D5A196DDB29EE2CAE369AAC65273D90D28E459AF72F1A8D7172AA52AA9CF3481941D402D75F13BE61882B8EDF3E1A43C0E647D0562DC2A95E19A1AA1203279B5680E1F34596B61923BFBCAAFEEEEC577C2DE2A079DCADC8CDBEE123F33B9CEC7EA659133A111E4448295B4368CB0517F9C179D8F165714141D660721634F84E250C15501C6C93D6C5B0BF7CF36F8AF2A84EDCCA892486D837BA0E6ECEE835FDBC2097E9C83419A641B030E03DF7CA4F53C911F15BC4F407846325035E658AA098E5FD0F7DB6B9A5CEBDDEBA19F864B138E5699785EDF7540C219C8F92E4708A55BF2F8B3D9BEA40ACBBDF873FE37272486C29EF5C44E7B9A344708DC49FBF5406951A33F7BF4FEB9647C0094BF9723EB3C8513BD147A929CEC6DA8BF8D61A6FA7268C0A3093C8835D63816C9EAD80C838514EAC721AB1728A59783B331598B6688620F31EE61CE9C1D2479742E5165B19386C258715AF513 24 | EFBBEC019A5CC779CF29AEE6632CA63C944DE49234446135E71D2378D31987532C779450F504234EA5F895507B086ECB3FEAA6DBAAA3483951E0AFB2B9ABDE847D88D423DDE26C9F9E339438A9FDB85914D73047515A54FCED2065E8DEECDACE50859CE857129FB46D7CF86D721B8FEDBF52E27F23CB64BA1721076CAAF1FC01874AFFDFC5AAD3F7C3CD70EF1B4AB2E15C62ADD1ECBA9A46FD28C9542A7C94C4E06A1804EAAAF1E16221FEE173B3B7B3F2E88807EABC4C92B5346FFDD74A8385110FE051B7E13E2179DDED4B9D5A0F42A4CACFEBB24FC2A027B153335AF3C947373FF4906B37801F09BC060033E0AB68991DD377E260DE69A22ED3DC666823E496373B8424F4BF06FDEB7023F63C864E869F01B1E9640E545ABE3B4CBF62D5B0BAED2FB560A4AF17B35C8A78889A2D1CFFF17F032EB78E47B2C85C04187030936CC883E0C51509696C1D51288A9AD79D0F79BC7242DCC186AAE1F98DAA33554D9C0204D4CDFE458C1878C43C2079B7A3AEC12B2E58199EBD12C30C50AADCC887B805DE274C8E37C92746128763B77C68EBAB39F29A2C8C1C715002C77AD717A33024C8FCA7D5088587279AEA0EB9AA7A83A0077C853202E5601512398BAD08540808663FA66D9DAEB414529E188E547E670F1F70DA81AA0906CAA31E614B3311DA8B9D742FAF20C4B5CFC370C2BE3030BA74622ECEF613DBE7CA80FBE475F1ED 25 | 825AD8C9DB761115C90105B57984301734FBB215AED953E5BFD50300043743059056D9FECA073BCE3FF665B3774D40013FE501C4F1EAA279063687306E0B0575A5CC15CE2843B54C955CD1BC616862CC8460023B57D6125527B24088DB6A38570BEADA48DEB47C5F4CFC7B75F573A481FD905A0E35A37B54E7D944E851778690E8B3263834146DEA25B289A997FED7C2889E7F691C1B6F8C8974A27A5723E814502F8E53C5BA414BF7F2FDF4E29E8154F565F16966421266F53C7E962B07F5F8C7BD76C8D9745E9059F22621DB2DC7FDB75B2E62C634A3F8725D570E5A6EE4D0FA054B0BF94A7762308E294CC462287FA8DD9AA2FF4A035E7AAAE738258CA1B9D57742ABD82B1F44B7550B2834BD6C7D67AD1D131C0FAEF72C329889001702060F1E6C093D2D670000CF507E02DE4063F32CA85E0BFE472955601ECCECB3ADFADC93033EBEBC0C369DF24A504F2DC7980AB10D3EF705BCB1BA39AFD5791D1EA77C56DAC9FDB240438ACDF803C93F1D39BEFC64E272BD5798B3F3CC12BE3999D29263678376DCD38D673F632D8059D4FC6CB8E652542D77EB7F647E94B9A08DDC9B3288B3080AC016D3F89B8BFEE5190179AFCC75072B4EE8A68A4FDB54EC8EEF1F2563C2F93287358DB5DA76EFF9AF89436B033AC949C94DE3A5B774434F0615DD94A7F0BB70E05622A9FF729A22E69EA580BB1147153C8FF40E7311E32D4167 26 | B93C6F13BF9FB0985D3B553BE42DCAD3C20FA9DE80061ED5B6D1C68FE614CC04A11A48EE93B0C55D3E73C2BEE7C2B337F46B0E0F5C6013364BAB2726C36330DA49DC63DFD7E7714AC6FA0943C2259CDFAA46C85B86290482C81676E280116FF16AB2EC72BEAD231B985A5C74B469926C35481D125F811C10106A8FF5ADE19221BD8590F72E90CD3CA44A1C1444355CE8551620A6174EB6B02D9FC9D9B3DB8F4CE7F45D2B49E0149E22CCEF1E8CA820A2E653603C9C21E8986F9BF6F67902D81CC3E77E07F3EBD573BD64B7475CEAF2A188A623B068AAD927360309C22E8518A6A7EA3D781C0773B6C2C8447E1C193FE3BD477969E7A5CE0202D9E1355A7A2096CE88F1BB9FB14A80AB061A259C83183836A2B3C94AD01F9434C53F8EB048B6C268466496456F92521A22761C328380ACA69E54D42C92DDFCA1922D0278F62149CC695A90FFC9F043A37BEB603E7A73D90CDE0B9D1AB8DD43AAA831805FBF15B7B157663736C649D6BA06B6D40C93948F8684A58A0BD07610D9AEC1A9D402486EFDDD34AECD7D2A7EE7CEC2733B9C2B1A7A5872BE04544ED82E87A54A5C6F5DD85766C4C1D49DBA659F4EFF40072FDC8DA3FBEDB5303FA06E91DC7E98964B078B96F0E66A67373D3D658DDF0318FCAA71B51A44FF3A18BE6104802B3CD5D217BAA13478364BEA6F752B4BCBF3DF9777F9B7780D587C23423973965FC49139D177 27 | 9A2BAE2B3D2861A4442D470442B11D83BAD2B06EDF18D54CC7B0C9AC38FE6278B8AB2CEF425EDA3BA791C50E8BD48F9397C07506F6B7BB00096B624AC8A98E529078515F30960B0517263CB1ADDDDED45DCA0B0BBFB384156E0A6AF74FD41538AFF23DE1544E268C3867A40686689E939D209DF530A132C615A291086C8940C8F245CF4D8A3C7CF686CD4CA7772080C5C10A6B2F2760AA3B65F7F6E73A1B33B2E8F9B033937A971A71EB1EBA4B4CE49F66F4BBD68283CA28F6684A8F36CDAD73ABF37DD35F2200AE46EDD3B69AAB68A3C9E46E0CA3FED8F611D46CA865874A56414D66EDE5733E60E3EC65B4ECE6C7B1506E267ABA345B7EF1CFC2B870D7BD9995B8850FDE1495DFD508C18B49DA01B44A42870C4C07D4A5C85C9DD0481E61D70A42B57CE76AEE9B799B163D86B9F8C025CBE5EFC35646B2ED6DFC4D58C622279E69FC603BD5C0DE3AA1250463FE7B680BFA4636D37284C07379635751637950A34A58ABC52F286AA53F7BE9DDF408D62DFD6840AFE85BCB7FCA7DBBB0B90667CB5B99B00BD4386DB80C8364D4456DC04AC4726D3D76FB94D75047A9CE7A54F5D8AE9C70A9E5497079C1BE29002598C532CC23C22A4C708D6D0968E4744914081A3B8C119B8C8A450ACC12630F34023B0A565D71C05F632FF6ABEE64493D83B1AC15DCE24BC4752FB4CDE94295CEBFCB4B7CA02210A861D9400E8908FBBF0CD9 28 | E4E77F538084879BC4246C03F913FC5253F99ED5C9011B26A01BEDD50504A925ACF8DAAD5A7D86D2364465F271D32310347921C3D4511897D79B495C3E321B57D5456AC0728AC70CA8F6C75C044057A36A2BEBC83F28F994786D6E9E06C548ADDFD62A524342B05C3A5CEC6C7BE75AD15BCC1EA48E42C2BE5E7F5DDC36B130388D8AE5CF400BF32A5CD22609140CCD6100D469E3A2A673EC355E7F85BFE4905FEE41079EF772CA223B5BEA16B4F7BE56B74D6C30E7DD6CDA10655A5CBF0E11ACBF6271053D0D5FD5607394C0EB62F46D08941422457E2CC9F926770A1F4C9B454DC4ADB34563B4BB8DBE41C3200B0C161C75E9693FBA295C4F7ADF86CFCCB10FF1B7AEEDE5A71C3C0FED55AD5BC67DBC3BA3AEA36F7AF52E9A7A2B5EA89283C898EF9493C8E8E9CD032203F787B452AC685ECE52ADACACC41C4203F3FF2915819F1475441422B6644DF27E878D71BBF9133DFDBEA24BE3F7DA27D9E8CF6CEB257987038A92F7F65022994C73091E6AA7F8C2A334AC20416F957B038F94C5DD78FDA0507224BE87A5FB919D55B879803EE9C28176A9C184BDE88B346A4A5912BD9383711A54915A53F308A306C654C76E358632FD77B5FBE189BE1E27E3EA471F1DDBA87789E5956D0BC40A0FA44FF0D4B470D47E2805FEA7B11CF0C2C241EEDB4836FB30A0AE31D1F181B8D66B44A51A946DF30EDA05AC67197484AD499C1141 29 | 9177A556E7D410F25C027EF74E5972FC41389C9B0FDF7426BEBE5C4C9559D4D2A9EF5C4352BD6DD8A734D5335D007F8BE098FBCEDD6CEFA56073B816A3588DAA70933D65506FCB6CB930199CC6E7E0D55BBB78A1EDC74B9671454FA541E593FDAB37441C853061671EB7FB17B5882252016DDBEA61B6F610E4E1B7EC1FA97C66F2BD9B62FDA84AF17A4522F62AC52F59FDAECACB0B2DE452F741FCFC7391A1D73EE236404954461AD42775114A03EE5D00F655B5A6413D4B92B1CFE269438DF949617BC4559AA9982D7F5F692DB30F87E5A47C8D04E1DB10D23B117486C83EE6C6CDEAC2A480C975AE9D8B5EA33C9C7CD726B8BBC52B7EA44E90F334BDCEF410F462F6D7CD865CB2F8F58C90CE987EFDDBB5989622A08E6E29143D8AC44B7692F6976EBFB4C841BD079DF2927B82DF69D198D1FFC087843D74298112A27ADA1D4A8339B0C601627C824384A71604122F37E38F5192455278F7A9FC3B3A5E7D0F74BA5867A1DDB335EF8B7C03D6FB73E5915DB01D7A316739E2D70DD428140774F6EE7B44E9F214383CA0FCC09E9ECC0A9B848B3E65CDDDAA048536C1A90E178B77B6E7664DDB17F3026A6B9CD1156BE2C348A9FB2437E431EC4527F29FEF95D16D9A5BD994BFF5C6A134E28DF07E480D3818EC96B2036DACDBFA46A89FF9655FC6193A76BC16737E8A45143FF6469FA68B60BD53A7B1BA0D5BB019D9D06068D2 30 | EE8D4D10CA0B95214800203A2920A29FF67AA10DC620074B5B6BD89117BF48E05F97CCFECD2387365BDD40CE62B8E23F69FB841A23CC0E788DC015BAD6BE2DF93B81AD4697CEAF66FF620C70D24C2E93A2EEB9ECDC8BB8C6DDEC4887B692212A2E6056179355799F0975451DF0C6533A832F69740496145BEAB73FA93F4A4BBCB1E3A9594111EE4FB18353D9E2FD524BE6EE9C8BF34B9D7CC01234ED2423C03629039E520891C7F0676264892DB62B37FBF34EF904F648A0ECE3D75A50FF18EFC74E893D2C0419D1F15FB4F740A32CAEDE4AD3B43287FAAA3DF695152E4C74686098DEBCF8501B461781E18307A010489A4651863C1F2B99E3B35965A03E87B6ADB0D6A5691DEECC8D820FA2B32D5AC2A83826CE2B94857B8BBB22F0E5AEACED528286DFDEEB134BCAD21D46F215E4962BB0CAF16F11086254D0385DAF3C2FAE825D9F5CC9403EC5970036919A9A6DD70CC25B53C171E534C749568ADDA382A7263595CC6E79955A7876EC3815E12602E61B63F6F0D98AD31E95B90E67AFDE6A896EF15CD443A99834B7EF8A30FB42EC1B58CD238AB49F55F18AA9EA9CAD921CE3E531249B9B01843813E052D3A320971BC23B7A31861DB04A1EA9F87371FBBC81CF480A0625867CABA27EC0C30C0125CA026E4DF7458774B3D316056510AC33FE39EEA0BDDEF828DCB272387D14DA2D78CC9A3E61601D0EBE56766779D0803F 31 | A93BC883F867F2E8FCC1F7D623B79A10E3DBE84168E738C97E219C27F28FCF61AAD7055D1C449ECA5549F1BDB9396C1A642DDCBABA8C421F843EBBECEDA4299ADAFA4FA61AB7106062BFC1CF3F9E68342F87BB892C5235518A5D56C8869B1ECD57091F0A045FD010DACC1BD8753F5630D57D907F3DA7D28DD10BAA3212923D358D02EAB666A1B3B1D01EB908692CD7F0089247EAB5E3160974614A7C20514B35D5D72FF12C0DBFE9A4D35EF64D963DB47B7F56D0124A0B78BCAC69F0C16D0625BC5E0359F2F31F71E0EB9E8398A556EB3F21F909B9AC7483A585077CC30949D0E2B57FEED83374811925D0C11EEF75E5928944E26F936DA5DB3DD459604B22CEF93D82C292DFDE9CB5CBC43B43830125AF02AAAC91A70D1A1B516F64E2D6F99EDFA163D95BCF9808E3004BB754E033A4DB981FEB4B185097FE8F66B4A8672498CD1E33695A6A87B493A1B784B756BCB4092993E996271DB47D65BB90263C169A518A35C245A1A48B5CFD5B77D49410B0C9AE4452641881DA8AAEF8851E803270C4DE86FF6F6B92F852CB48BAFB65FF0B6FFA332F1DAC06844EABB4DBBF763CFCC108F44FC1BCCDA8A63E59AC8BB89EB9928838F95EDD90600DB6593C4A325FE038BB846D8E3776474C16CEBAC9F069323AA6123D43CF423051C64181AD3453804CF1E4419AD5D60E197A6D59A2A39386E4C312D39A3946B26606D3B67397A92C 32 | EC31C5809DAE0FFA40DBCB271C91FE9A6BEE2353BF84A65BC4883EFA7F94EE2280AE80A8AA28F00BAD588768CAC709CE416B82E74F89250A4EE19693B3B838C0EB86D2A0976FD3C8A9BAE306D835A06EEA228797514C223EC197A1A571189C9E252500EF99ED8C5D7DADFD73233000AB3D81B1C231C93AACE68E2E14B92CF875D04CCF00FBC7A2A36235C7D1709E24B23ACAF3C623122517E893ED766EBE4E5549A5245CB9C3C935FA8DFDE58C70D44AEEBBCBBF7745F43178B2C63D283D38144477C6D77DD94D72857E355CA7AE45D3F8E0AC2CE1A794AFB8481C45A48AA290BC4C9FF6AE41F235B8D0F7B36AE313CA9F534590BC3000AE43CD47A512F919DBD74FC15B16769DD8EE124BE73A9236EEABA58FED4584B447A5F7DC255C62E2DB2DF8D4A1F7A78C62D0DB1CAA4AD537261BECB7778A61D4679BA29015C33E163A12769B1712082A78493DFE2A8FDADE11A163035E0001209E263300726C4E5D0AD96E8A3E8BEBF35ACB7E7C1DF39B81F847F664F71A4D32DDB1CCF3FCA3949491A9A22DA2B7A1FF3A7B09439E91675073A36C645D9A9FE18488EF7C0833C8FCF4EF86D46576A44E0D23278DD398AFB0D2A93FE26F5D30964AE3A4AFB5F1C8F78F6BAEB663C6F417CA67F68BB38B77FBD81F01CD311087D53F16CE15D4A1F9B0E210A3A30B62CECBB272442A67D2B5621CAAB5E89F6E59CA8A52208BCB626EAA5F 33 | E35AD8A9C1387CDC100CE853ACAFC068ED7ED7801AD82E62B9AE816E389C8035F435C65F51D87260C895083624A48AE77680260C47818B9C74812DC864CF5BC16F2C331136671D7AD6D96B3D5EBC24D5625C93DD1AC6A08D2001BF30E697F3F04F83719A4A3E62F3BFF8B21F0EB8AE4025DAB452A28DF89C128E50C3A3285AA2E79A79B716F598A00937D2E5355CDC053807DB54500253FE6D3B5DABE30337F3C3D90B4FF4E6A963BC7B90BFE1FB412C712DF44F183B37C40E9003582F83CC2D04966C2F464857C18018611F4D352C813E7286DC1D6B52B6134424CFC140D84CC504D95D03C987695D8D234AEBB5B9065EBFD7096C6B1A6654C0D0F409044C7DF9778D356C9275D82138F102477FB79777D04FDD9B31213AA86E58C76A271A7DA8558B0C12F756723CCF1F0442D9ACDA613FF49AA3174CE84BE4250979AB3BCDBB3E9CE9F8611095228493790A25596AAAA8F637BDC91221C36D4C0A6E5E776D802A0D71DB62BB606CC65C7373101851293B15AA8B7BCD0F3C471B374FE7471C93F7E2540270D426D6CD2C278CDD9809AB2A8A9CC5238E0AB98BB14B40E53CCEE35FE0B205C67BBEFFAEB52966ED727C932D28A571768134C4FA5D274ADD0F9DA1E0A40726EDCD6D8E1E66D05DC73460DAAB99370C6884B8D07963751CB6DC004677F82A8FF1A5C935B898D8C96E59F0CAE6DBA25EBF62841831922D842D524E 34 | 82B0D31A56BFC4251DC4EB73B428601585F43FC690B5B655FD9F97AB3FD44BB1AC2947D97D78FE13FA37BD14E17E481B4FEEBE693FC0A448B14544973D8F2CC9517134457B74D9D3F69FC04B7814D8095DEF7D148145E1FB53F59FE7783982761363F079190C6530B8B77D2AD5AE5C5F297B0AA92429E24690024A53A393E8E3A9473A67FECB851D7BC2D252EE98BF67549C7938570A3BAED8211B5023B4B80BB3D0D21BF7BDB327F1DDC3846258B78C9D05475F246C74EAFE56831B494129D4B53FAAB7028F61707FEB0973EFBF75EF009D729C370E25B79C71CEE7B8B196292DDDFE6F7AB125B74B336C1E272D4F35FB36DE7FAE43B4CD879E54F5B196629FE45EC9E77810651A7929DD8164D2EBFC11C25625812E96E23752DBD9459665AA575ABB1D1595A080A825FA86EB5711252B58124270694ABDC8AEF70ED1D05FA6EEC43D2CFB201AB6F88D75269DC722A6358F7887BD55154DB52CEF952D57916B2533883065B4AE3B52693496329D8520D873A170C93C63CCB9C2601A82D84720B00A66E1D009433E9754FEAE0E122D394FE004FCE4B020DC5358A3583704A0797DF1C214A6EF714F7AACD249B38F7F60FA40BD773926EC06C8201092BBD119EFE8E5F5DDDEF159A5D5444E37FA0E73E95E898D9407978085FCA6D7969FF2701DBBE8D19F9334E6C770A5C00026E7CBEB90C38247488434E5FBC0AF2E77DB6BFF 35 | BA03045F61DE3AD028A013E6DB3176CF4987FCB0A398624D520DA8F846D7A37B32144CD32F138424EA7AA61C2D4512387983066A2843115DBED860CE89B375578E919183944BC952D2C20C2C8E21402EDD856F70E1FD4057C64264A69046687AE181BE3FB258E56F062706753CF7B13A9AE214178CAF4848A1B98DD2B31918C4D8DB5C4855442361066FE1A2199498A854AF441D55E1A928F48BB3EF5577ED9B2F22597FDDEE954E0FD0F8097DEFDE3CF636FB144990CA6C8D82A62494C97C04E5DE45A1587DF1A32DCE1F33DC1D5906D4DA0D9583B6739115F07ED2FD68EF235C965512517B704915D7DC2A196330327A9BAE268728709438DE711152C7FE5999489F1B821816BB758FB86BA99986C0C55A257B738F7136ADC5884F5A67D22224C50A8CB6FD886E1C8197D0FFDB4B2331E848D8D4B5FBB5D8756BA7BF34BA6F92BCECF5097D38D495F2F7E8A352AE2A4BBE15F436B93DAF3674061E6ED116440AF4609087277168CD7BCA06E0847B3F63AF3008057C7819B01477464A11FD63BBA24A8475396A228D59B5B818CF647FFE53D75FBBCCF79ADBAB0CC9B4549032806F5C57CC6A0001EA7EF2E9804862E868FF4576EDA6121CF1BB3117755F573646AE3BA990EDE2BF7BA8E0C847A87B626231C596C1C3868AD06AC654EAD6D6D6C547A2172903EA65DF93A9A97A29C99BEDCDE9AAB35A986EFD540BE2EB31C8CB 36 | 90866025E673B87BF0145DDC4F7FED9A49121D21679182581DA6678B527F682E07C8ACF281B13E34E4900F347C0E8FBFC7BD637AFB328A622BEF1194D9A696269B5BD2A48366B4F0A00C0BF77BEC8080D057D6E60C602C65B45EA03D80A8B7080F0CAB379DC6F6395C6CD1C2602366F3E3A513BDBDEDEDBA0F664B465DE862C0B7F2E014C0BB32D46BCAFB40BB6F992C1F24AC77B0747C9F7F4AABCA3C254C609DF241423D220814FC0A394F882B6CC1D9BCF5806F0B955363893D033B235CD32E1C91494140500848A1877A6A97A1760BC6CB58A8C45037A18624107A1FC672623760704D6CC5A5875F55D78F6859F6567726D03EC4C62AEBE46646FDB0A02EB94FB7A44B85ECB8696816CCD5A1CC98D8402E0CB086084EF2A86018E3399C4063111054C1BA3FB97FEA7EA3617C80ACC87C04A077C90261735940A632FF52A8DCFE42ED024C7C233F5CC13F590FB5752144C77C56BDA74CB0D6CD6EC4F89869875A3CEB4F376ABB7B07FDCB90AE2FA22DF29FDB056688C58FAA94913D5669459BB0D2D2BE438C28492E8765F9FDB8631761677A55D5A7FA4BF06316240FCC2F05F1B53F411015F1E2C48E3907D181CD4D29E05AF10F6A27739BA093734E02EC27AC8C9C18EC3B3ED3B3CE292503F2B32FDE65ECF1F4ABBC2BEA02DC84AEB5DFDAFBFD3DD81631B2CB2285C4EF286115BCCF86B6E4E08BECEC4F72F342700C22 37 | A132750B4329A3AD7376779FE4552286FA14D199F66FF8AC903A105DCD75604996BC80FB963BCA6D8000D99B2FFBE248A03B2F438FAEAA971B8FC6073C0CFFCDA3FC778C624CC32B0364420813F2F1476C4C443FF37FFFB6D5DC5583EE5B52F20D1E9214403167375BA9CF73DAD914ECE2C33A669B500E31395D0A85CDC3CE4EF909BE3D82827F6FCD0FFBF911C63DAF2F6ECF82E2E40DCEB8AB80ECCC7406602424CC8EC94FDAC62BB920A67DEB3DE92929B19B9734B140480D63500BB5E57B41F3087E5B1421CA3B896B50A747E553FA531836D25A40D62BFB1D2EF340BBF0BBDED8E592557456A0C438C0F8D1D33A8D5DB1A61E366CD74FAE355046EDF62E92215C60BCC7290C94CB863D19D6863ED2DE6AD63D62B4948C516785ADE445F872AC8070F7C4091E847F5F124C6A7BE82B5E931C580DC9E2A6BAFF96997AF64D0723FC72587F60C14581BFE9C27134708D5AB5DA4B2C225DC05A0EA8459C956DE09E9E76BF05E8ECB4D557A5CECE2EAC510D9525A93E16BA369D7AA50055EDB2C83D18A42604CE1B5DF1C734248C691CE7B15777EA9B6931987B1811D77DDDDBD4C14FB352E2B90BC58EB2567EE2F59D0C2F027275B2CFB736EAFE5903711271AFE278E6E43167D2F9A4DFA356C1EA03F4628A847A07606EA22EABCFAA67383705544FD067CBD03D116FAAD2BCA34A1C88CA0FB3B6DE12999205FB3B4B779ADF 38 | C4DB0F54EBFA6E794BA2C0630D2F62F168633D85373B82041BC6693DF1758A0DD0978D07CE9108EE52E4E5BD861745949366D8C927EEE6517E20BBD4171963BBE6A7DB92771B53A89186CDA632793717AA101710141A05CC76EE23A27BCE86912E54A417147D1BC28C1541CAEAB9DDF92B12A07DE553B919080F7D03D6A0A21689F634225406B60558F7EFACBA77C12AB3A91B2158918F1E5D8E5CBFB5702113F7D19E94ED7953467A9CD5E5ADCA9C66B66719C4C5E54517895C38987AB4AEBD0687CEB104E6B22FF7B09D56C7CC2C748E8F83FAD4E150380936C390F916A6EFFA6EE33DF92772B17E5031A90E1A99907A32065BAE175C381DB55968DE521FF3C2757E29EE454A6202D86595E7B30C5C12DF0A9B3057AA49E720FBBA7CC33DC33D975544D10BB32AD98FFAAEA1B40AC031A844D49BEF55A565EE6748E1DADD5C59499E190659646E5FA9F7B9EA8AA943A06FAA597C7648CE86E9E74DF8025961412C1B108D85DC1CD3DAD8FA1B146AB668BFAE17C3B73068ADA8C0081879C36785A39FA0E05D739C90121E1BE7ADDE2324BB358758F0D9E8817A65B9B6A0CC96E58703E4DDD56162B868E952F87E5DF0607C6A011F595A515B85343E7347ECFD34FD3FBD04B1D6D97C774B09BA72BEF36558947476D1672C8F313F62C3ED73C874965A1724B3A9724D5B7A93F68B7411DF177AE77977B2EDF1D343302D11C0F7 39 | D35C2F53EF43E801EFCE724F6343E8E54400AC27B1A948711C279FAB9BCDD3B70BE0AF08136D57BC30FB6818ADE81388A4AC562A3770CE9AADCC93880F434705FB567F1052ACE15BB9BF39A0BD459AED2842C582F604E284AA14A6F289FF53D6306A54BE26864274DD1DDDA49043B27ECB6166E869C3517E1E0DF7A9F1B5E554E37ED063F2B4FBA52A5643D3D03B68F991083BC67D76D43FA5BAC00FA69016533BF22AE2B43BB551F34115F65D38791AE63D2FB77AE3E20FEA2F28088636EE22AA4CDE2C1F00299636863CD1E197D0DF24DE66A0ADAD1CC9C244B9B2A55FA26E2EBB11766852244AA81033F563F5ECA76B96F99B986F185D0D606B4C3A253FEEC7FBFEB899B4E8F12BC9DC55F426AB9A8F4E86590A8870F33B7E278F51F6413ABCE8822EFEDA162D72123D2E7000E0DFBCAFD65EA3E76854326280D40AE8A6C0473EAA676C7CA9AC90737C952CEC34F99799F4ACB17A92164409D0676DAFDEC3098C568269F21AE1CC9E722F8C31B9FA79EEE0D32D83C264FEE22AC48A142D4FFE1748AD870AB2E7491F02218ED0EDF3902277A3B35EB63ECCBBCD71E81311A27613FC746C361D038EFD4BB58C6F4758A7A38DB8E1C208AEC8B47B06EC7A03E59064CCED10896DC93A8965A203780DBA2416BBA72FEAC5BD9680AF692AEA43B3558D8DE764F1FBF11509BD6FF824F39D04B947FDD0D29FAE8FD2887BB585486C 40 | E95E4439785466AB31A8420CD7428A6D6B0BF71D65F9D53E7EEB22AD2710F177CE44C9FAC127F5FA32FCA8043BB1CE7C65336CEC4347664F46F46EECE3C73F77721E4A2710378657F55C78FD35131E3B3EF6A91C027BABE0451AC0E7035BDA6C19243CD7568B225F250FDBA359C624EA9F20705B902CC1FB17E15C633E174BF1DC1977452795F7F9D978BF18D51895873115370C751C3D006F856557490C25A096A486C5F256B385DD358933303016561D0190F6E282031F4DB4C4C122E40765FCE05E1D985E6298AE69A5F05B3CE8A82CB5E0A3129D07821797E44C069358C6A096BBD3E326618C892589158F3A57FEDC3E917219A71317226201469CA9371BFBE9D7374E55CB03E8EC5916B242433B4E3E122B9549CDE9ADECB764C30E3916A3971BEFDA6D22EEF806E8C0B35C47C275C4B92E4CE989835B932F89719394F271E528C87A05E7EC3C410DA495B092848976187A7F333CE2C87A59CC0A12869B1741E29CDD6D665A44FB2D814757DF4E43ECBFF257936DD8F9265FF099673E3AB9188CAC0B216E1CB213172A4324AA30426C4FFB61903D80B7A819B8926DA169A3A6C2645605AEC7FBA1AF22D1688A6A33C524A9484A5AF516ED448CEC5599AD52BAA12DFD36D1859032FB349A1B8944A90D52ED430270472BB7D3A2CD7CEA809ED99C6C209CAC838A49C0F1D1CE5327DFE88081D726E2AF72904C2A6ACADDA6 41 | EF126C112631FAE4F31CA276A743A3BC898E72138ED99F5705121461A9112701386C873D5191F7993CD95E5767D51A0B2EDC68553BE99A75935B014163C612587967A90F8BF16A71847811F376A605E60FBCA52152891E1AAED475A28A85226F3C8BD19481E612D52EDC128575F0E62BB84AF157D549878442A4E7CA2E8CBF01B68B8237FFCDD70D45A2EE42F7A5EA17A6C85E752CD4507D96AD1DB53D0D22679667EC7513E3DC90B06CDE5AC2F1CACE13041AAE4F13D6663A439FA26CBE5C53B7A9A427DF1BDCA94FB80495A5B8099967B442A009B9453F0750FF83E9D16B83A17FE41EDBD34B40E9F32B45415C61C0A5811D1F947B4A87DF6AD7771060DDBFCA595111757FE2F6D91CFB89ABE5D3A4B750E912FB8E64C232FB586D65F1DA09EDA78B189D481B29DE286C7E73395CB0C612FF55C2CF77DAB901E7E1E5BA84A335F333725A981DE71965A45D059D6A8F6791CC48602AECE99FACC7DD806353849A964D48E48E6FE456FABBDB0805C5AA5631A93765AB1B3D4C7AF07CC946C72FE0BFF0E9B378DA1675517F668227AA7A8F9E0A422834BBC472CEC37DC3844DC36306718655C2CA0268BDFECC360635E3CFF3E41E993CEE61B3BAE82AAC3074C8BC8A94EA21FBD0B123804041DB5D5EFB139BF96471A5F1A1DC13A3554D47A3EC5DB0272BAD2040199BEB26E3A9AD88033BCF162B6DC3617FE88BAE1DA4243663 42 | B208FD49CCD4AA96458A64D2B675B9F83ED8B9262B3A883E0645A7E24DD66D90724ACF0C4B72109466796EADFFDE9B8CB49B25B82EEA4329060DF5110402059358D2908A6B3EA79C878F62A301904CCF1CB8D132B70B1F23AD06F65B234CF7E106412A57E43B9C16E12AA9CBAFC2AF87F2538622FBBEED873019BECFE5B471FEA7CE4A726C2C1877095F923DDA259C15AC7138B7B371BD85A998C5BBD872975A0124793FF873E328B81B2D3DF241E9E8349D4A1F33BB3D4A892054B934EFF4E7828AF814430B1B1F705E68EE0682DBFAACA5E3B4F786D8855F9857C0E34814A665DD3DF83048B49C958782367248AEE5C04F10529B5B0A662241F35EA5431BB6B85A038EF2E6619EC8176287595EEAB8FEF0AFCB4C9E9942390914E4EA0886A2B32BB5C2E100E4BFC9ED4DE0958059CC42918F4FD8AD0B319FB7A045A56F649AB5370E159B535F71CEA203EF1A3506A8FB7F6F932F76238645BAB99B37CA55D358FF147EB1D21D13E2A717D20837F019BCA767EFCFA8CAB1ABB89637DE8A1B8CB639305869F0135B9B6D0D2006873F22F2E6A5D26DA2DF8EAEA489DA5C8CB9F67866C020B5960314DB116DF6FECE7A196DA171C9468B7043BF9D27A043563E228F25246ECA5CCF5A55459EA28A702DA4B4A56E55389201424793E276C7720B4FBCAF0C38F7D2C1B33322721D36CFC7B3A9DDADEBDA7A07BAE5F9BD4EC426DE8E 43 | D431C05E61B19C7EFE619510C3FB88A47C4A46EABD59BC7EEBC0DC4800F467250A0DB7409967ED1500607EC0E266B255C715C7B0F8D5BBBA9C952080B3857BE9D0055C28AB855106866A32DA1D5BC386E134DE9D0794B4C03B37A759F1AB88BB764AEA8D907FCB95F8BA4958E7845890A02EECFD2AE544F75486EE55E642216DF39DDFCDFEA1E27733D1868468BFDCFBC93D2573F395C376E96821EEE6B8B8386F3B3F72C595FB11FE080ED9179D139E08475222369CDD51A23F366768C5AB0EC31A739AB863D448AC0EACA5EA9380BEA3ECF46F2C95B6AEFE1F94A5FB30CAC942947A86CCB1EF125E53811405CBA7DE4CCF78DFA2DF287D0F3E6D64AA68EF07EF89BF9E5CFD494E151CD80CF5E47FEC8BB46126D7EC9942A6B7A1B88F579D95C88D67685EC33BB9688CF89CFF35E5D9B37EC3FEBFD597FA262E52F3CEEFE148B1CEF0DE9830A460DFD3C56E1FF2A8F69570DB5F87EA885C4B4F0350F50CCB79E132EC6CE32BAF7BFCD97FF93307932943216E7C607722EC2CB12F5EA203EBF2F9257B6843D8FEB3A77F43B8AAA4E026DDBE1453E3CD96F9A7B8900B339A7F99FBBB048028318583124260E02A95F90EA89CE69A2D95EDCD50F21609137B797BC1B3541B9BC20DF17B79541791E9453C2D40F086B551B1904A43C2F0CC247BB1A58500764E7AC8E37BB2D1A738244F4AA298555ED7E53468DB316C7A79736A5C 44 | DAA10DC771FCE74B6DAB0640AB1B445731242618BBEEACE2A3F994EE3E9FFE19AE23D4180EB77FEDB89E71917842296851E3A2F51D5158ADC84AE9B4283A5D00947ECBF6DF8448C5B856BD6C0B7AB06F173ACDB43FD5074D09D20923E3488DF49EF3A54087859D7952B6B3A434646C148707C652FC25F97F180C33EDA2942658FD7288F57C742D9766D9E121FCFBF5F6E4395E45AA9332D3E25E6D51E07FC97A73D1212AE065C780824027981AC04355FBC0469F168AB185B27F1275575B4008B33B974FA8CEBF8D6FC5CF19DFEA68F064B9C11C1EAF8EDB557314B9FD8BA24CFFBE69E61C32643649178819A325479E8B63FD867A520C531D34C0653FA7ADA79C3E0B415F42D8F0FEC65ADCF3BCDD5BC0B3D772E9331B8C0662C8921B44E88243A01D1CD4E13394ECA9BE91AA79F4A19A80B496DC5636F3EDBA5418B3EEC8B933314E2F54F732F866BD64A3112AA31CA10157206D72C11E06B911FC8CE7E0CB9B456C6D132426099F0EF8EC417A42C6FAA599AEAE5E9972138BB9F88709B3A6BF8CCC10633EC03A1C25302F2100702DD58E74FADA8E65A23137E744E5CE1C8E379B2E0D3D6C0035F0DBCA7436A7A44CCB2B709BD985FBCE750B8753F3441E85B9AB0CD9EBEE1B549C4EF5E316DED3C7286A66D17BFC7C12AAD5AEE7A3CB5C2FC5D82CCAA38B5FA3362BE2B1F0CFD5353831CAC2F92B9D4694B053DDC941ABBE 45 | BEBD97713E7713BB0C0E4DA161C39D9E800A37A103A35B70D067D8E3C5593FBE0CE71B13CC83053FD2F116FA3A6733B9CB462D6C482603E4C026ECA5FCA14363326B978687FFED3D884EBD434017E907F5AC63B1BD1E11F4FA1FFDF195D353DD67C9ACEBF4088D038FB84544970D7989442FFCFDF39070086F06EFF5C5BFA78DC71599A3B496C8A1964DD49FF04DF4DB03DB91E1927B97FD9023B98E9B0C58F5332F3E8D54E50EEB2FC7F12BFE7CA58BB41C10FF84212E489B9AE671C02205BC266E5EC5865BED9C1FC3C5A8F600A382D6A8EFA039BCBCD096E94DCBAE1AB98F89A09C656C5EE45D5C339385C34B560139DC7EE8CBDA8138E98F17B1FBEAC8C0E881626D8A7EBEE782FABAD69A9DF6E68A52D9769D8099E53DD963947B1141B35148A2522E05ED7A81256999AF96BDC3862EAB62B0042393FD4F35256F913A9752B022E0228ABFC543842AD0F57A5E411200FB5912B81475D7DBE3EC6B6DC644F6C0CBD8401837D8B08CBC7E99FFA03572D2469ECEA3CB5E51409AF137595F56B51B8B12CE77E4339B7931A0ADD8330F1D0F86025EA46B9AEF982901354CC754A56F6D21A27F8080EEA19DDD0EC6838BB1A38F36A932D366744CE683635B0AC5F02E94D66AC3611AD5CA3A74C1AFE64DDBC641C4017E8D15EF589D6EAFD6148E30F5F7196002309C651CDD33D4D8368AB87370CDCFD654236A72240FEE47405F 46 | 98C972FAF45C20DF4F4DE2186FCE6C5E20BE349493A756912D0EA0B23F1BDFE7ACBF8E2E17533FF78F3ECC3FDF376BAC61CDB12674801C2828AD0ED96F8C05AE977B716CF7447EB51A9E47099E29BFA091BC53AA8A8EA20BB2DA704948EBD81D70FC97BD299022188349D9BDCE57AA1DD9BF9C27457F7F37AC78761E39D44A56B8487623E6D26A23A33E9A09847CB747F1C14EE1F6B03FFA43FBA87869D31C02477865FC49422FD74223D8E2F2FD8135AF0F9AAA5F08E54673A894CD0DB73D97CB652E7938324B482B738531359AD686BF2CCDD4D0E4EC6E5022EB419EBD0AB72AF6F7186A400E65A9BFE056A08A94CCDD9F94083772BBF82AB632DBE9124E93D8A62A80017447802FDDDB96A187F5DF1E282034BEEDF07DE098CCB1FEABFD8927623427640D308E70B14A41E379654674ED1B9CDBCC3D6CD5EEF1DF705BB7B1FBFEF44219CFC24456238CF7A34516B435CF310CD58B90B95708B08084A9B9E09F41DF08D5EA338ED87FCC2508479E253A4AB26E0444FA9CBC78965FC25AF0E0F8E96A4C40178DEAA498BF61347CE3C21721D0884B0F3E30A06B512B75AA1396ACA5653C866D55A42269181A81EAAF157D8FE66CB1498D96AC685A518B72E757D9781904BAAFB1F85926C04C44818C5A80C321D4F41BBE834863D56ADA584FD57429FCB940494B5FE7AF8B40E5B102839B0BD21831D5C677D18F137571EC1AF7 47 | 84093A7B4375614AF309E394722D595A47F25840344152689281886D2E34168DF0392C3F8D7F8B4C659BE29302E41E7AB8AED9CA0090BEDAB820B5905D720EDE72F4E4504761A8572E4C009F9C4105D7B7CA9EF3C6351A026E5DB6B16BBEE8AA3D958E1BEFC5E87B39EA226241ABEC0092DD48A0ED36ECE169074D80209D680599D4D1662706F8034FFB6208F6E152DA97AB8FFEEEE8B82B098AE7CB7564C582EA85F91234AD300DC156E20C624EF87C275A472882FB42BC0F9208AECA3A7A7FFA47BE659F25158C00B1CA66C17DCE136E923C41C08D6CA389235E8E2C130C38F18FD6AE1364A3E82333BD42B53E3A0A8BEE8C2BB77ECB28FE02D4A91DD0BCA2F6D585594FB608589DCF3400BABB45770CA16B556C7AADA08A49AA4C6F2F0E82837D4A3CD84BA55F640F3813B1633CE3D5BDBAB49C758185442FAF466AA14B72E86C0EE93A94B6E8518B3AC763131FFF74E4A833E7DABDCEBB43966F2D9D63FED057EA42E2E3BC90DC1D7C668FF01D860CCBC9403F4DDBB204429792A669C2DEF5B1EFC104C03D415160E89CC41FAF44E6230BDA67B8F603AB0E39C2F56791A03A25924C0CCD8E20E311DAD24DC569E2C968F1127DB0CB050689BFADB2949226AC0F87B856851EE06DC7A85E8731D8BABA5BA10CCCAC4A706C989A22370B7023B722243D04FDF8A9655B56FCAA9EDB3A046C9B1E8FE0DA1B70DE1BC317744298 48 | FDA3501AB0E2F77DA0981B5C37B49FD2808295187643BDF3C79531BDB057413A4A66E08D2E0919B5B02FB2F4DB751AA575AFBE7972121057ED8C35659A54C3C9AF02CA68ADE57E4590711FB2A4131C863CBBED0B03E272628BC304294D27C9A88DB521D080C0C235B9B210AC01799D1AA0F94341932F0A7972C19BC495121BE5D96FE2490889FA6D7288D6019DCFB4118CB744868E5C8FE402297ACDB065656F188FBAAFC462BC9CEC493983DFE7F02054DBFFF21D184F39886F2B09BB6B78BF405B79D7A52D1E01FC542FD8AB7BEB9603A186CF56DF833714C2C127993A2411A785BEF63BC51F72CA35415A05AC5B0460754AA859CD4E0938045483F99EC0F0D504610064FD3BDC275D75F07EE02D2F12197F44D87B71CF5F7F2EC3095502124943A73E90EE8E5BDE2C3CA080954CA15F9C03B4B6D9A5389A04F7B629380B020F92DF362FFF2513020BB18ECA4D0BEE4867BA58D72E9ED67A4D898186488ECBF77E27E3770ED193F037CABBC9BCEF465C1880416B835E3A2DCA47D79D40E214F8AC60B2BEE19984ED153815DE100F2EBCC9BDCF2447081AED2A7821988FE0B31461C2898820ABDF944D6DEA2F93069C10ADCEBFA6AF37EC136B0593D649EB078FB1E49688C94D0927872CA942B77874CAC3513B8FAB91E78F6288EEFF9D2A6697EFBBF3812B9EC241014957512A2CE1BA24218604E055B64126FEB2A53B2D37 49 | BC6F9369A4122BFED1EDA4F06A6171FC74BF326932274CB6B58288CA20C0D779B7187AF2543E6B1D0B0C2FDD42EDE878E781D26F70A941DF4A16C8DD443560D24E573B01C1CF1F7E8B3208B5D4320B9C0D1F43A4AD3063C48CDA3F5169695DD578166E1F2939DE46ED6D255EC5131903183DFD4465C233606C9A7200DBA08C49A83EDFC084BD06A0E7702DF448BA0886EC2702ED2DA8F12A3B4E2E4AAAB9485007270CD71E702F273B1026703C481B436AFB92AA72EE2185491397FAAA7C0D91AFA5AFDBE7E53CF50925EC0ECF325C4FEBAF52B79CCFAFC157616AC7472E781D5F199425F1F25B1972DA8DAA786CCDFF8A8EADFE80064F5F6B688CC987A04D39E695158D0038D435F22927E47F09CA78FE97DC31EC1A5669601D0B2E11E5F1FC155007E43CAE5BC64CB4BF4C9AA9EA351F64CFA3BC75406E36CD162E5220359CA3750C16B7DB7811463FE198A4263B1921E8D4B9D7A27189BC292575004E9430B85F6B08478BFA3B5672D7029DE38947BEC67CDDC72556B34427891FBD604621CAC6AC7A21BE3CB347690ED4525BADD9DC030433E4223DAF789232611A4917D4CAAB11D89DA1CA07330C352B7906614C5A4046899A078918EBA969B2B47BFE19D51876B291099311B1823D05E4603EF186308CBFDF13AE5EA8C9C2303F2A8D29804F3A84949158BEBFC9C26001A9E340A1D0505258B10F5ACFDB495769697506 50 | C8D963D40CED50691E26F4106A26A75AA625BDC1B065FA9E417E4F1807130D5A251F312DB7807CEA45A2BE2CB53EDD263BA7C7F93B3BB4A480EE6DFC93B592B91954DC4A77C0C196C34FD8EC478624392F4B2CC7E9955F86C4E27F77DCD04DA1AB303D4C50EEA01F253FB3DDE8F8EB691BCB0C3E2922BD9651383D15925DA77FF55BB0591D6F7A7E8D0D0A502112F46010A9D4DF4EE25B56BD9593BDF298D6BD47C8668E0CBC4894FFF62DBD1A6108A936DDA82D9DED8F6509EC0027C59A1D47954C1ECC3DC8501F3E204334029A655D71E5DA4C143DE07026569EDF60A5F15A93E4AB20D6796CAB6385B6855E353B0D1B57BCFD49FE9C33C4EA24D1A3216B729E72CA5A6A342B98326B0BC99D599A3735A02681DDD3363108E1BEFB95BACC7673B289C853E69BA378BF6E39EFA42ADD70CA6AF9EF77E5F86BB26E22CB1CFAC9D6D5E3C0F0EF99AA0F7C1C576CE34E8873D71172E68F14F086E915D2524AAEB8D6CE055500333935A825AB796DFD6ACEBDD5CC08C1356289149477CA59BDD0B683C0707164C9ABA9F0229069C20BBEE13C146CB4F4066E52B776B7E5E909AF3E531F2DDD17E3FD912E745F62011786D21C16EA1C2B8BEDA6B6B9232BCDFA5FD5008138AB5ED9C7B67D4D9ED290BFC33EC25C51312133AF069DC5C06ACB3136CF359D00C9F67A096686DF3AD59481E661489406B1A2E26292FB434E8DE3BB5FD2 51 | E72EA2B28AFC6551DBD255C4916446B9A7F1C7BCBAAD2D26D977E68A4242350CB8F7ABFA498FDCFE3C961034A90096653BAE41A8DCBB14775DB4AF68BD7F8BAEE008BF2899C05C3833ED3FAEE09509B99F3481AF10F3DFD4B88585640525AF1B347A0BC9254EEC6B39DA9093A6EDC17A36E97E52F353BDB9554944D9C84A2D52C3D604107735C2F9CD0D3E14FFA822AFA7D7CE113AA1DAEFDC2FF383FB1DD10EEF79ABD4FE9456B84EF7EB2F9E62342533D985A0C5CE02AA17A79B058067B851C46018E606D1A844EA0BB713B08AB9947A45F0A8AD7F00151648A82BD40BDF33479423825FEB953D648EAF0A5055C1C7EEC6C1AA1A90C25099D93328C5B052BAD827A6EC352559272786198E6286B3982251233FEFADA57AFD90FC424C5304E33417F1507A41E69E429CF145920F4043791B27B9F92E50F5C34ED0C0391A730026B7B20EC6588B3E00556388544282A6FDC3CFA6F603A24852F643816412F9B5AF11D43F8673D30AD3EE4DEFC37565BB0D76F6EB52056C432C9216B84CC3348FE4D262DB4397CFC79F5B68E2BAFA148CBE4E2BD6742E559FB51878521E81E05F8E1D6A8614397149B344F8711EECFB14231787E44584B84B43959AF98B3AEFB6A3598EBD92BF2725961EE826745C5EBC06BFD8E486ECCB60F491D2A3FB686C089DACC7EFE55D44047F819CD10806D89ECFD723285082A970B6171D833D2119A3 52 | 8AD1C819DABB5CC9B4DFCCD0601ED891F7A21D3537D5CAF1815A78E71938128641206BF984E12FA82F65E5412228AC64CF0C1A8F21D8BE7267499FA3806FC30A4A33A0C37F0E8087DB6CC757D40F857EC59D2C461D589482451ED616C893923CA0F6F016475A243EC72D5C1325082B8DC339CAC6BC66F5B2910C0F8239223F9DBDBC054EC5F57F06B2099C24ABC53E72A8569DC8CD045D6D64ECB0840FF0BE84D66E6A39808DE8AE8CF4C0FFE268E0AA3FCBDBB5203A8279544EEFAFB9E076F581E2FDBE8A79C59C6C5F2EEFA71F76AEF08AFC14C98F3EA256BF7702C40E1FB44BDC0C7AD0D0A8CE0DCD1E993A3DDBA0B52BEFD4373D36FBF94054F6D6311E40E64D59699DB5F4238B199E5F9BD6D43212339048283853A82BDB82267157DD4E5056C75DFBCFE2E20ED87F58797DDE3F6551955551C5BBF5B1E59120A348342BE61DC95D5A2DCE45AB27532F1F29E12B34507A7760215976363D4F410F82E526FB691F153060BE6B57A64C23AD2DA885E518C7222E96FF207BD731F7929D83F58B7C83196CB50A60ECFC61EBAB9D8980424927BF1349488393824D6E271D6252BBE4F6E529A2B77C447721F59B0A5904DD0595490E96F3E620E7F57E9A76BBD615F1B19241911AC36B716645F0465FEEE9F43E61FE4B335C8223EBAC565286314686886DF2A098F22463687ECC4811E7EEE7761D5BE0D6B4BB89E79560B70032 53 | D6F113F353CF130D25C3D91247F0B25F2ED71BDA6DC20B2317B51E4F810ECBE26787EC1CB7D73682DE785D99B44DFF187D75241D104715242850B03F2A839C6239DE444747C5B4093351F62A620E4ED2BE090C7505AD144ECD8D0015255E6FE7232D2557C8ABED0993B8DB592E016A0E50FB10BD0A07367634C272B904E0B3A4B9D92B71D92AC4CD1D1D1C0421BFE298101E04A0946C6F0B88E348C4A591DF76BB9F17435D4AE50B72DC2A807B461BC20EFECCB3762F06D3D25E6C826F3EFEAFCF599939E26726FF8016F7BE7DE36F1DA1F048D4A477D0DE5224110C48E8BA94CABCC0FDD1EF0FF890F6A779E2711793A3353AF70A93249784D1F91BE3F04E7BCF6D96BD3314387B45F7E21EC4204AA073B446947B871130BE7D8E681AD3DBA8806DF4505ADF69502142F1E92E06AEA1C58D88388A8899A30A1DB862C904C8B2B83EFDE161995123F2B755EEFC5A0D9DAF25DEF128B3A2F5E8EE61E471F0ACA421CA3A5D54013A34B6719B190030A27566838F53177951B1821B421CC3F84907C9D227C56266EC7ED2886F417D15710912A05B1C6014F4FF1F7B5C8C8CB3473134086E5099F3C0BFFFF5B00C4B3A6091FB51DE00B55EBF07581E11B5B585276D080A77FBC52169B4E2AC444297A43EEE2BCC5BD83D8949E7DA23B325053F89FA0FB6EF73D0D840985FB11B8C4A50D3AB6EED2E8F7984F208B3A683061D1F3F06 54 | C0F5866588C3FE9B8DB3E1BC935A8BB44FE1D4C260E4D064F3D90F5C8BA920A215B0A91431DCB3BFC0AFE40B3576F2CE5C2571B19ACB9FF8F16FCD9B14DB99FD09B927291AA9B618EF8F3516D2E27CB2BC9B14F0E79794247129B605C1AD3BA4AD53C929F69614B1C34C6B130E3B4258C7A7AB111EB964A9B3C1538D3C6EA41C85F1A888482A2F9955197B1342ADBE474FF372CBF4269A04A18F5242C4D70FC50E17FDD31C6D4BFCFBFBEAEC211CBA04761D1030C92039B25972527FF1A067CB358107E68A4892DBFE893B0F7D636680FD21EE1163171B9FBFB7BA1A401D4CCC27ACBECE8ECE7BF70458CE3EC69E7A012849B61C32C66DD922C63629EA0DCCB480CE313BAB2DF600CEE93879BAC5DC8B68D439AD90E8204FDDE815510D265A7CCEAB7D032E54E2DF8A8F39CD1E83720CDC1B8DCBA6EA410782EFA0D84F10F339952F27F68C2A0560DA8F39018EBC5B0973306396FDA4BFD32F8C34B38B855BAC146E46BE672BDA3EC40A5C15EAE87F7FB41D85A190D6F28D7CBFF80BB1361C13842859D7F1E485A5DDF467D2FBCE1E334AA177891F427DDFAAC3F8AC32620B764D467C876A892B90AC3E034A0542A92FA6E7A03E62D80598AE869F7B6B6DFBC8BD728CCBFDA8116DA91EE8DD70C41FE6BF6A8E8F08E42F7772A1C9996DE901F2878774EEC1D862B4ED4F96997E63B4F260AA76FB2CF4027E1F35FB634C89E22B 55 | EE0561CF00CA340AC98559961440F2AF5CD2A575B155EC5033D85F68E88BE09684CAF845E957289E6B6878F4D89CDDD2E3ABDAAF220E43F7E78416652ECAA8D050FA5AF8EB3B27474F026E3F10E43417736DEC0878F584AC785C151E00DF7D7953112F306610FAD0C73916C008A08111A2BDC4D2D3BA7F4FAE4319F1B3F5DFC4C34DF40B81820100A9FDAF36FD4501DA0D54971AD95E3AEC97DC93BD348EAEE252A1E6E340BE4F6ECB0D891D08FFB35875CBD5DC281AC811B48210F84264D2CFEE1932DA958CED2E513BEB62F25984A527ED5E0006B850333FB9ECFBC20C00471A409E05CF6241976914D5D0E676DD43F47728B32D04BD54C8E68467BF7BFCD29C26C68580C0EEEE3E9E9D0E1D73C435D9F47058F29AA078BD6CA5673D217D3D646490F159D9A58F85A42759B33367718FE57EF4DAFE1E73C96BBCD25230A6B4FF7F0645A93C13709AE5BD3B921730D9A0B53B723132EFD6F25662A1F1C40F37078E978B2CFDAB6E22535DE42585AEB21C51FFCB37560F9B0D7B0853B84A0CB2F958E968B496FCC50E65DE896878628526A7C238C8350EB60E81AAEFDC15D2A8570115928CA4D330BF94661FB2B0511E01920342525FD6F61F73A4E7B59A059E84EF7A29B271E41A74B7869A798DBAF5C1757AE4A32EB2FD83D5A603D1532319EAEFEED69F791962FC96401D108553D3D3B3BCF51923D020BE842F6C9E4B2C28 56 | B044B1AD0A6042623DCCFF49AF5B148265AD98ABAC2F8EF5747B18DD5615D3E22A57FDC0290A87C843ADC70C9E29E8E7E17DD7BF8104C06ABD2A3CCAE339FBC1F1A3FA0F960860B8B0F18ADF8CC572E2A4949E9545EB29E0FC138E314D7C109378AF3615DA804BC7EF15AB9EE51C3287D1A5F1A21539CF97B33D8C459B2FD3DCF6B70F031E88278679BDD53625A23EA271EEB2265442ED5B8ECFF0F4723CA87E98D97B425676DA573697ACD4E3261EE331CC32BCF97D60A2F68BE17E8AC9CC6FD4BB49BA535998F2497A7D4FD3E3FB0C00EE18273A9473DECFE183543413D3B1C292C65C3575317290A786C286ABB5BC9ED2884BFE9BB2A7B6F18933E2B5D96BA62A07720EF158B2FE9C704B3BEF3964D02EA4FE9CD48B8D282117E14C720B5697D8B3CAB61223E5184E6AAC4C4CDFADB936079D0893082903CA3482C7B56DC12286812D1AC20E20B9D83320750123C6777F964F6DF9F1D20EF1B8FC8686F0CFD3C78116BC1EF6016FADCC34BA5C3003D9995B0997EE1BD864B2EBB5B93C14D8A3AA94C483199E0F9AC8F589C1BD32F7D1C84EE0BBFAF0A181B6A7EBE70C3B541BCD05E883207C18F4E7860724AE18587A9B7F45409996EF5E5DF49F8797B8A80310DB78C83654E2D33DF0635C724033414AC32D67076B2C13CE0514D29D6D202BF20CFCB1D5F2E2555365C98FE374EA8DC09F3392C9EE9B2F5196F5A8FB683F 57 | D02DEFC3AA87AC72590F8AA5AFF619C58B90C50668C7EE5CACCEA04695E7A7C6524CB5FE25FEDA498F476CC4A718321651A624500BCEC75EE0AA953BAB877584F1CDE90072E058C2D060D02482B9968686D9D067148928E95889AFAAF66B2479ACE0C42D14E323931AA03D96EB7EA51A5B884D19B8E742BFAE4A2035ABCB709FC4B4ED43A51208E051CF0CB752A183F657597EE0B56F510413D36FBCC28FC147361180960592BF558444DD3B1C3C32847B3009347B1D87048CC13F3208FEFFA29E30A404408565060F54AD605F15079B3DF88AA9391EDDD1802730EE9053ED7AE2CF4312630C08C9B8828EF8ECC5B12652F4AB27D62A59665BC67E51F84A74CE92646F60199FA23A1818EF8D81501F37109443F720CF54EF603245607C1B91601D31BA0E8E056E5FBAC33E95E0DB6975CA3A6E66714F8E1251D1EB424F87536EEF3FBD61B5D9A2171697C25E08771E98ED4B12BD848A39CFBEDFE6613D3510E1C1932EA112D761D4B0DA798A0B4A88463F544AF9E9EDB8DE529242F98C7C382494AAABD8117F52C48FE1A7023ADA0E9800041A26C5BE277473F146F7894B5976F5381AFE96E836A10E296703DEE01AB7EBDA97BBA7136FA855C763F5171B0B2420D3F6D401A098ED67AF06350375EB3AE5B78AA35898425145804FEEA3F894DE86B3FE60692852B18C77AB6FB36AF7B21C6F08DFB4AC7D1ECB48DAEA54F799FF 58 | 8965E9418ECE5DF928E7753BF308A1D6D88337FBC7DBE4DA312D017BD9A07F43C12E4404221A28588870E5426AE7214AD440C1732D978F1F68C02347A6DA6338FC07B743C136AFACA09DE88E832256B947EE035CED60558E0BCC47139FB9ECB1C371BBCC1E5772176AECBF9D05390F886686637725AC68B5B63173D464AC8D2CD2E73B3313B7A4DD55BCF1AC4A1196B16751AAAB1EAACF9D47379054EDEF4AFA3A4AC7966472214C3B3456ABE4F0E864A07B927F4BB62C9B5E2FD17B6D015FD4A3E8163BD54E658F98702A8A467301F7E351348FADD012A40551B3AD66B3C0F18A08370F81ECC0754297161F2C494B557B91A44F121AAEF084F3ABA8CEE38AEFBB5277075A1BCE19ACEEFAE19B8C9D08D30B79623FB3EB078BCB00516D3D228F7CB8A7199B92BE53828FD7EB43C4A8E3A4E269A64176F8E6DE4FFFFE967A9688C97B2A0B2B9B8DE65EABF0AAF5AAF2824CB07D2C8E6C2B24226DD1DCC2446F638A9ACF24CDA4DE85860CE9D54D23302398DB7A5CE74B081BF5DAC330983F6053C9DDB9B8C0D56CD1007583F3425646424B213CC7C0BC995DF637612B5004F71DFB19E1DDB7C23663FA2EF45A5524F9384BE99DE742EA240CB796B3C86628A438A9BD8BB940E071614D3D553A3859A0B338B829CA22BF629597BF5A6DA20D1ED0F4F8329102146A8DA6F1F4E2214E622EE68CE349290899B562B49B95466BB8D3 59 | EF11D0F2A49B583926928DFDF6B06C054B19389662F386DE3DCBD2EE994BD6822A4E54D83018B49AB47194956753FDB24DA20E0EAF9D8F4C93138D13A2DF0E229314749E20CB9C799469D1E887CA70B7512BED28AFADD5E25614D5A40C074BC698C90E76D99EBB2236C4F7610E32A4646AEB8F954ADF4E6F0717EC047E470638E2C42A3F7316D130E3B8D2A0A7964A62CF9F6788B738D1DA37CDFB575AAE77F8D4C10F3043103A2067D225DEA9B6FBE0DE726758D5E9B3A5DBAB4C3A8861335F8E695B083E2633F3048431013EA4441B596FF898341DB20E3A419E8DE4114D5DE060D15A7F82549F6B5D018697ED8C496C66E6760F2A54EF4974E04A0D0FE4249DA6C3E31964933411C3AFE20A8E5BDBA1006CDF61FF11C269D577DF10E954D4879B412216B26AE58660D6CE7BF80CE622B6FDFF378B6FF152A53CE5CA4B68FCC00B8CD95DF7F4DBC86954C776FA793ADB460730B721CABE060D92DB89611B6FE7AE6BE7ECD5D22F5E95AFBA58D8B730FB401736C6497B294E93E18BFC35BE0FACD8F06A4AB073BB569CA231637D586C53ADD2870DC57D4C8000A8DF9FCEF965CC320202A328B0F1BADD8E5F0267456AF22A94F673751220FFE5E61F1B850405A39B6DDA609DB3A9FFE29896B720B39BC64C77E3CF69F0930A13C8E4FF4B87A4D3CB259BD072D80FEF310C21A6A6A66D0F233B0D3BD0F7D2CE182D006D20236C 60 | A9100102FCD12A9A17F1E42D2F3FE86F95E246F601268C0E1A70157F7E438AE3D8EF19AC1CB14496C98562C13F9E7AC4B2C88AAA7FDAE174EBF3F0CFF4AE734EA7DDD3FD920D00BDB352136AF02A0807A4F770B2711C99CA54B6EAB898A1AFE1769471671F213EB388344EE0B2841A4ECA437B5FFEFF9A0461876A234B30454B9F2308013B8A7B5A287EF5C7E7CAA5BD505D8A49656878C90EF58D131DC4DEB8FBF426C7A85CD929088CE06F9E42B1AA908D3338C2BB20816B4716C24A8E9B38ADCB23391521CD54949AA8BA37894219560DC5775E1B32149C5F748C20AC84D8460CF2499B62230ECBF52C773F245E997E5948166A72AA377B3E361FFE33D180B681A68EF7BDD0CE4AAC8E7760C70DBA1AEC46923D8DBDA9A02C7D3F5AFFDF881DA85A4D82BD74B97B49A1C2E98802AFD18470B58AE212B10D140835B9D39F970095A59D1E9CF9CCA8A2855C5417AD1D732D4DCEF0C59A1B3841E94E1218F952283B04AB1C8ED94652B10297A9F6FBC1DC51D27F4E5F63BE3426830C4E86D1D790189C531D806BEA3834A6D3A512BA40AD9AFFB35A0BA64E5FBC1FA65DE15E01398F1AC9B539985930B2597550F97E8EF862AD5FA4327125D91D2827AD9ACFB15022F71635D58BA1519E8523E9A643FFFD59229E6E18272C9340CC5618B964FB8B54A348FA4CED2E2D6059541275EE748150A7E15D63AC5653FBF934BB2292C9 61 | 8339152F41AECCDB26353C194CD331ADA56C1141127F6EEE5BDAA3E1DC68F5DEE68F652E20424B8729C3893FA531C05958FFD60C8FF0320319507ABDA42731B6380FA98D30D97123B563604D1812A76108C64F4A51A4CC65A10F99940D6272D89940359AD690BAA6321335A9930E41A96E2D3B5EC923359C768FD71063FD3146871D2103160A299472D6E879BC1F7180EEA6AF80C8BDD5A72431A7D0B42AF458D341A9F76EF259BE2B625FCC2C26C6498AB2280426BE397DD68B7175F4E40F8D28C83DBEE249CA04081839A6F60A5AEA7410844A515144A7D8693BADF143C202931C885C6C4EC25EDBC6D66AD42651AABC28FE82BD422252A55A876BE167EC28BC345582CDE0CB4C71C89DB7BC7D769026DE34E39AE4AF09A5B5FC988B32AC085CB60DDD51804C6E455FBFE9842973F43A99BE9CF9BE46229636AABBE3DA261557F69030CBCDAF8D68D212B93A1FAA2516F038171CF5F28244189FC5964FE4FC9F8B3DDB0E7765B50AAB20E9A2E4AD70440382F381B8DF0A803FEB506B6E5627A39B4302380331C163803534690B25BD0C6FADDE7FCB024751568541C490C038B29D7E558098108588C87A313FFC0F54497AC20D53C645EE197ADB0D166F0D7A100B1E960C8EC83E75C35FBF67CABF028AB055D512A674AD96D908CDDD286815CEA45A6A4E56ED501825810095C2307C279DBDF1BF44C3A7520820B13D03279D 62 | BF33A5ACFEFC6ADFF0F179029CC24676DED790387F2A248F1A39CE3E46FD6789F9054298B0825D201C2231E3775000A60F6E4B1263E500ABEBEBA73767862F628D37D725093C5894C218D8A0A15A49D096F78D95965FDBAD29CFD45CE97CB8A04AB232A43ACDCDC322F2812725FBE4BC75419E22C270BFFEF55FC950784C89A7B50FAF0C9B9C0B73A03F28C19C0614424FB92847BC5BF9ECF0FD103B50D824B9FD17A7367691731CA307BA343B7F14F946F240CB14DAE08E891AC25F2C5DE597EF39FF286DC60E6ABC1A6C2B72ACE9030447ADCE67AC61F8DAC22CE7BC2EC4BC74F69BF16EBBD6CD7FACA0F4BE4C41CEDFE886AFA9B1A1D4F8B5121AA6F6F2C0CAF8347A7E50E6B0A61D75355D0CBA556E0D06FC3D824FBE2B2D6BDA9B06470B3D53B90855BBC7F1F3416387C508670DCDFB2B5097883D357EA3E28A47D1064EAC1D67BD96AA264E7E607F9C36DE8E1AD0EA529ADEBFBEB3A440663EAEC1603EF9F8FEE21E3AE03240C0D74DA5601F74D71E1CB9673EF84FD614113C655325B7D25D165945288DF5D1A1B27D15A31427C6307E7564FD0ABE4BE743CA1DE26F426CDF862AFB5E38C99E2D1B40BA49E690125CE1A950AA449A81F0ABD8E125B062A05026E027E3D21CF93ECF94CC8E18F7F5B44683DE0731EE07245B9C3A2D357AA6396CEA6C854338E8D252336C5D398CFD2CFA757D04B4B3AB2390F5E2296FCA 63 | B1F74BAE683D8B53A78BA5E64B7EBECF01B5BFB185081AA203D61D196878B2F4ECC15DBE2BB312BBD9648E1BD7F360A6BA82042F85AE3FE89B4CF89D411447B064A54B85B555BF79B136F7B8772143E266C47D11583CD12F5247709D8858426F04B90022E96277CE2F304DD19BF54CB7897607948B2D3B36B8469566A466DC9BDAEF786F5120FC29D63AD3622D3B81B52427BB7852C1F5551180896C14E0B8EE5B30C42A5F6490821DA600D82D7E623DA22856F54FF0CC425D75340DF2C02DB6554FB50BFF758A2355E0B4611780EC15DFACE5BCF910E1DEB273E8BF94B4B677390ACDFB473D5E1E6D00F64321FD53FA61777722420EE7F0948F589BBD037C5CD599740E38B3D6A3F13F9B62F707218CEF18F0BD88540CC5EC7FA244EE5C2F8369C5F9080BF70982C36ED77E7B4EAA16D861BD1B7B47800B4655F2130C0EB0F02A4B65B65119441E23031817AD44B3F39A9062A1EB709A0F4A00A5CF9EC399D00A08905A92BEA789866FF6A05069C72EB79F4B3074D324951B045D1A8835A0C3967D44B4617F41077DEA202008C71147AC7AA0673052F6DDA30C794E0DA0062E80F6ACB974BA602CFC6B7E4429ADD77E92B972D12B9746C330DA7BC9273067DE36394DDFE2ADADC7E635958134C25423A40683EBE2EAE0C6CE68529AB93C257608D3F6BED1BF2C5EC9FD208F52C8397B6217E6CA652F80F1D59D115062F6D0C2 64 | B2861845EB8385CDFD7A988B75EC13F63E56B35EF53F35C31CB77AFAABFC71C3F68F79B7CC1D9BF8899C5F3C2169BD5A128F0997E84DE3C0A63CCD9822ADEFA5CAE5D70E734D3D10EB09A5EE0AE8A9BC9CB2FAA9BDB6EAE887C2E4FCC61094C3D49B764ED078A8DDEB3BD9D86BAAE3CB48EFCFF4B14B71FCDABEA95572813C7F956DA9AF140F477205880C07BC98FE2F86B805A478659C9D94232A9364049B8CA9B53C2E6FF1D6B99A04F0307BF216DE1F27D100B78882AFBB75CC9E0987F17B8F2BE7AF6415CB78E206CF43E6510366A60E90DBADF23A8412F25A85CA26471436D9058C9B53AB026FD35279EE456736421072E69AB7CCAC0D019AB82D40F93FC9D865E290FF076596A763E1442AADDD84193BAD4263C5DF7984406B6CDDAD2B95BA067B7BB3AFB58AA57E525E8AD6C34DAE7CD2E81C99D093D23D8BD4D9511F8C0E039101E3D2317AE6F069ED8F6CB8CAAD5F7DAE2CFD36B60576A4FBE5C864D9BB619CA19607CB40816060EC5724536E3E4E102AE3329FB2727F7C16A6CD79D5A08423F30586F8D32B1F2C826F4DE9B6F5AD51DFC135F9662884010600E9883B312AE8C355824624E7AF2CF30A047D98007BBE9819653368AF428DAB353D1111FCD7E4B4EB7942002AE3941EE3C5CA85081C4C30B014EBA6F6BF3EFA4CAE8A6000835029E74064A1F96F18CC514709CF3366960905C5F8394904D573A3FED3 65 | A4D7CFB5E8B48874E5EBC12C68365E5F19F3DBEF081EB2DC5F89C4089DC7C1830BE0FDF4CA14437072350DF7FE4473F1330F4A814D400F6127EF135DD01251FCADA94F872896A6BCD82F151C11395D96C1BAA83B34C77BD16A30F4C343154D433A6C69051F8233224B61EC5FC3BEE63328949D454FFDD13D97FF12FB34471B78E3559A23311320EE01779F4A222C6B5FEE5BB56D7D50F50BE91E6905C98DB2FC04ACF70F925D8250131190C1E90360E3084FF4BAA6E308D952878F4A0CF5141AA31E4CC6C7C129F352EE983E749045AD7F00E2BA49A5C8A5FC4FE25185C7D22C244EEFFEA31DBFF398054D48BFEC4AC5E0664F61D9F327FF612CE837B254A9E29BC27FB18BB03164A7F4C204F7263E6A15EF0C73D33A0B302D8F9B5C02C5519F647B7880D5611B026C59D0155FD5E4C1AB2861F9BBF1C56F7F207E580BAF2BE3594FD944C11B7DAFF08A89D6DAA9E9A5DC5750502DD193EE7C2A1C3952CEA38932C04726D2593E6B3545A704D5C1AEC58F7A65B2BF540BD5CD4953EAF96BF323B228206A8BCEC5337A4B28F658284AF289A3AB6F830D19099C6DD1C3DEA1972B33B55CD3C873178E6F472BFC256C48848668F49CBCDA154C5C65DA7B05325F680C1B421DB52ABD308144524464B4D57A062C6D8EA4919CD34F57D9712BD539C55DB26D7FB71DE0AABBED771419528D309C88DBD8733B24A1681FC089A57500C9 66 | A428148F51385FB165A770948BFE4C139212D1BFEC163C691FBD631FD4DFFAEF81DA5868A39F628B9DC1478B919C70424B7B7FE402EB5EE348A4E13AF739BE69884301D03EE2962BBEB2A0F70282C2CCFE33B994FC9CC8187C799C1619136014CC3DA684F164D29639330AD677CF15834F86851C093978FCE8FC7A12D578FB2A9776AB8C6673298A6A5A8FDDDBB5D54E9658E550490F60388E2DD56CD9B5F8DD9992F8D3E1B098E2924D75E9D68995012C889DBFF0AD2D968531FD00587E9BC21F1389ECD60968A634B756B643E595B47B5123CC9C156ADAE77FC9E35B0D7E18F888CDE8C356F13B3EFA4BFB52637E0C3150E0FAEA5FA223445CB6BBC7770939973B8354A2E4722A0483DD577A59F83A6CF0174775D310F32AA45565AFB20F536E9F59641E5CD36530BEA7E6CC0EDE0D56B67D07EF08EBEE02B4B4E1BB3442DAEBFAF81BA45BA7095F2652ACC3D85F3CB36042D757B494C97C19FE65DCACE9F6FE1C33A8445070ADC7C9D71A2D7CE8D57CDED7FFF298B3544FB02EE541BFCCA0AA1D6EB68D63B88C09815952ED3F1147A15F5D1B82FDCAA08D927C8946C57A9541A4AD81085D0461704A29C8C9B80E68A60758DCE6DD35C35B76FD2E37C5D1182515348334583B7162DC3110F56CD282000D27B3DE6189933143A57434D91C2735C3AAC5DC4ABC97AC565329C937849434D21D28AAD5AC3A63785AB231393FB9 67 | D859AF4E18F7053BC1C4C9B78F98264CD853AC4E0E91A32628D0B18539CFC62CA03183FED8F4205556871EAED22304700A23241EF626795725E6DA52CFA838A44D653B77B840AD04B4C190260B2213BC964D034B21E823594B1942DE1C6F8F5195E1E10AD90AAE76B4AA5219F3E3AFDA60F31CEA1F8FDCB4835F9C1BC32AD67AD92DABFEFCF358C930C8680CF15C75B6E655D276F6BB791460CA9FDD94E72084BABD4EBBC3BD875F871718E4CAF63D24EF2D70261AC49191F73482BAB2583F2D420EA2D5B02F3457D6D3195FE652194F9142F8AE1F690A79DBFEBE85BBE6011E28CDCEF000D004B2F8D35F7BF4644FFC5DA4F5335B86A0A1395F0036034C6413AE71DBA1737F0FDF97DFCC591CBFAF37A8F30C753F848B4EAFABC3B6080C3FFA62502DA1C7BC1399D7835209FCBEC8667CB327F9939EE969BA6AF3CC26230A00E795BBDFE40277D42430BB31F5CA46BC16BE77ADD6DE19A75F52134CC9CC4B558505C91271958207B37EB7AE8ED768EDDAD3C6D096A1CCADC96E1B047ED461DD9178E4FEBFB5871BB597A93BE0F100B51351B1E6D93AACF19ACA25823B406C5E11A87513DE7FB457F216666D44604B62730B3595B65D116D36D28CE1F7A8DF8D7C30E17230C7A92D5B0442EED4C3A4BAB66C12AE1BFF14F5E147F062107C5E3292DBE6BE918A705CAD33E7C71C0C019A590CF4D3F2A13F61354829A7922A4AAB 68 | 8C901A21D8AF977385079D72316E3F9E4C6A98F616492261D96E32A0B4EAC90B956B33AEA1B4C59D3EFD5959320482846921CC0F05D381A316033CD55552B24050B4AC5651CC19A221C46D46C8F4C7B1CB2C4775F7A14365F3517892E975424723A28DD485DA464A2ED27B410E0ECE9390B559772537AB931E61DD206025EC8BA9D13249A3738221330DF58C999789EA4A8225116D1C2F967C5E0C0446D97ABC8023E2CC11F221D722D6052DFDE2C3D60DAF2A18B0827265A75F4359C03F1A7A92022BB116D4F56338B03AB6A243496B02D7752E08A0A45991DA69ABD58FFD730895183F334876A66256A01BAC4A5251ED7EFF7DA01C6155954FFC93BF0702A8FCC59848E6B72D47139DC42BA8025A5EFA15BD9A66646BBEB9DE6F3D5AEC3E2AFF09B374391C9F8B8CC2F660B3233D422C199155E5B3D0D0BD1BF680B46D3E91BDFA7EED294145294EE04DF06E987ECDF665AC0BCF74E046C113E0D028FF6442045BF56A4A8AEFF269AFEA308C3AE6B3A992CD3E8E732729D8815465DB77029A889243E22B74B777796AC07EC426055B0EDCEDC272DC4C6DDC825D3BA3CEC5C2CEA9C86DF6AEF97E61FFE9BAB5B05AF4F2B699BCDFF40681F0A5AAE471AA49AA36E851725AA9F1741FD3332FD1F8D80EB31C612899FC895037BB02991DBF4E37559FC0190FE978038B86951B9F77B3254760DCB538B321DA09C098602E4E599A 69 | C53DA244AFF6E560A64F166E8DC037495DB80416EAC3C562BB74BAAB0BA4DE9ECC7943748B119CC96AED8D62C83C4F7BD4541AA49881F56FB2C7F6106D73C19CD5CEBE570BE4E5B61F108CDE9DA36A1C50B92C0ADDA3E12F24925654538BB378B7719773B64778E418505542BFCEDE52572153FACE5E3E3899FB07FC1A81FE19D1E28A5AE3D44B341C689C167B7F27EC3BDE4C7AAD8B24572A36991A2422737C3D94AF658BC98779534C410B8877FD7B5ED1795A4B4717DAE2E94B995D7DC524E6AC69D5E5F5443FA88E5E4CC103F66859834E3C66298015C7E5FF12E111611560F67A1469ED68E9D763D73B55CE118E2DBA8072A8E1AB03AEF13BF8801C550F923ACC46BBF8C07AD3666CE543033C0AB8ECA390514A5841EFB7BE0F18B1AD039059D8AFA9271CB638E0E0001B64AF171319DA8A9438DAE94B736F2FB05199D66401E1931B3D2E80F31A35128E19301B058DB5C4738081D22F6535F67833DBC4F46B25073DDF919E8CAB227FFFBC7695361B13CFC5D9913DD79617A615829580E82A88D4FE0562948ADB46F260E78DED6DEF6B49F5FA1E8E25A13AD1B9DD840EF9C656B1940D5A7A98FAD15DEFDF0E5B085E38C0395133E249D31FB91E834D36A443E1CE46DC0291BAD6405F4FE30156A1FC63E995E5399E38834D59FBBD6F07DA05E8DD5FDA390C5DD729A65BC6DEDA653E33A53C599672546FE4BEADC4A7F7 70 | C0734E4A2EF8D1EDD3D5CB2D114F9BA37F39BA741F8EC517676F748EF5F63AF05D31ACF7A727AC11AE34FD75B87C1D11CC36B4375557686EBAE168570CF7A5974337E76B2450F9F56671BD7BEB12E4C30DF48E008836B6A79F051E55027CC3BC109F42EE3387625232B3D48B12672A98F8997B9D85708E8D5B1339C61DBC9E6AFECD316386049AF81F48DAF5673D774D1D6F21BC12E7085373CD5FDF2ED28CBEC4B8D48315F5720FBB14F0DEBE2115FAC1E634721F3EA03327F55BC6238C4A1C45CCB70439613A0C43666AE256E4A3F230A3FDD1AC537E8D637F68AF6B14D771B51F3CD9B965E242D8E5A94D111DCE4851730E43665A06E41D1EE3B0635A7A06D57D0B47DEEECF5F728D34CC699AB9B4C5462CB7FF8AF2D9F920312E4AC8705FD7128EB58B1983DDF30BF002E017465F8D84B270E55AC2362C8884C7A4E8E42C8C97ABFBC4543BF924293863888A571AABAAE11E54259C5D3E961DFA1415C1FEA4008A9C4200F9478A97A54812B1B735252FF23508A87402E4399352A6C181DED26C4C782DEF54AF468CD996E1CF5F5CAA39DAB8C0DB7C53B3270F581781DA1828A5AFDCE7079DC9598772B7355CBE41A372F1BA18B28941A20F94D75F6ECE1AC34F82A0E852F033A1F092084B4183FB57AA1A0902D6183D289A4637406E4CD69EA34B06EF15A46BF32D3B0696D44CDD36084F568EC8492B167E9510BA757BD7 71 | D150BF957443BD20A8F1F78BA4DB18BD1590D444CD23D571850342B35B61BCA0A605688EA410CA20A25CD2078969A62230919699B0CB05A7B08E8088FA81490BEB2E6D6B69E3646BD48E9936CBC13DB48C2BCF472D7B5DB60DBD56FBE1B2371D51AFE4115ADE45A0D4A315917E900712B9FFCF1A97DEC94024FBBA86CA82560BE3EB9BE3CCF69C779ABDD6F6682891FE63E40DF819AE8DCAE09419E313B999869D8A3874B0E6213FC8C6112C89C84BA74DE7681171129C5650EB166A6409302C79D75301E18E794AEA9C22749A7F057F0606B4F4C351CC7BFDD1B2CEE9C32A3DFAFA638803FE00FEF70EAB9BF27A2C4AA48E9EF6B26DBDFE477673D5E518B966FC12A908C882D57AF3CAD6B856D363C10DB0E0AA4B6EB0FE754EFDC42327350AF11348CAC562AB3CBF83428BCBB775264C770A9C90DBE1AED01DE92E8074D57B53FB3E7AD99E87DFC06F9B3AA46948630BB03C5614B5FDC8D4E06A49B1B07C5CA51B7F0FEBD1A5E188013E0E8FE51D570882E029EDDA859548DF61F82713490EE818621A7DC791F65B8C30DB2A0C8B5EED39F882DC8DA2C5043CB3770D75C6D1EA85FC2F4FFEA28DC88EBC33310F140B986E61563947F8D1541897F41D28C99947FD832643BEE2EB404AFFB8BD2F041A666DB19062688041F0AFD4F56CD86747CB31FADDF70891FA1B77C24E86CF0F7C93F4FA755713DD58482A7A1AD755B360 72 | C03A542F7C1DBAB5E826248F21AC7658C0964DFE471C198B59AFA81FCE446E61B7A073D5393615AE4EC6A079EADE4D6822F3204DA706769BAE8B941E087164CF1C498759B0C802F171D63F9F424B73C6DA261C43F5AB562C548C21C939997B063E63B0490084415B8F4759437DD890BB0101ECE621BADBC8C48D9B1C62A91B5DBF590D716986421370B9C1615BE1FF4CEAC4A7A7A143FFBB9737E2FFAAF5DB151BE39A05A2E50646E64C77B717D57FFB7FDDAB36E52EE3C2F9048921D07C4DEF48A711DABA7A5E4C776A9F2F77046FAE9D00486E38942684D7E9CA5338B3C01780CBEB8ABA86F6839158BF39CBA7CAA62B0E6880AF0A5770C8523E34F90D8C17BF35C36A4B3F21F5B08582F9348684B497E919B87124FFF64F827608D71F7CAB1D356C2F808044E169CA23C22E192DC0B18DC8D6513EEEC226E027C91A9BF3F7AC94A817F799606102A793BAFD40F42D9EBE6FE92CA5A8992F8BFF12306D03A692446DE61C801752F7363597E9B1089D7324A4E3D90C13E08A0E9663BA8261BEE50E122CF6E78145C6F57DEE3EC00A739F11636C9CAA66E6870591E0299C5FB2EC85B69C5E9C96AC305A89D98AA4137D503FC76B00AF60BE3228BBB8B68EAA99DC57648B523FFAC8F16C45939F3C50E8AF1F74C1297850B80B9F5117585181A970D2728F28787B294FB79C6CB622D2B6C973B0196D2C1D4FAA11E4B59677FDB6 73 | E5A255494515B93C27BAADDC52181DCA5F1BF6D657DEB7BA7568E28978FC6CDBC383F334B8550EC2D0682D95E222F00300FB9F68CE55A52019D8774E58DC02743B227F2BBFFA8CAEB53B6F4964567C66F0F24F7A08CEEDBEBA8011A366C76A3B5E8782CA78480A93A867B0879694F2F4D1FD5F5F32287A8E675EA822BB7D155F9641D20E14FEE455731BCAC2BFD55B3595854065AF19C115E4D42F65E49C6D904F5884BCCD29BD39E8A3347728CC7D9ACA1DA57614459D4336D837714FB283FC5DDAE38492F9B0E3D53674C9CBB52CC83B4F59B6640C6EE090AEFD095CE087CBD7AEBFA4F84AB6E004345BE294A444694B0EEDB3AF304D28189CB24AF0C32A1DE105DCC0841A7FC6AF9B3157D40AAB4F5B271B982FED9DE9DF446778A9561D16F8997E581DF8CA33349BD13B57E825DF3883436309436C8EE1856CEF987AC6E56405D5062FE0FA09C533FE82D44A5E70FF4B3653B338D5401ADCC6756A81DD2A66D6BFA8ABD0FF0CA8BD9E5300BC15AEDC1BA579429396D72FEB8DDF0F7F462CBA644FA92D1D988EE9F678D5FAA01A59FE14A05670398B04A171A915BDB44F3569D661CC75EC42F302AF8B2C66CA1D67A9A27B40AD3DDA8D3D006A15010003FDC0BB64E172EB20343609C912719E988EC1A3B9A5F636324A4A2203FEE91ED052D3DD60F15728E09F582088E46C467C9A2CBFFC13EDBC0845067F02DF764CD62D 74 | AB60A8ED915761642842F7BA57D7CADDE5B18B21A4AEA002AADC90A3FD9742AA9ECE15C21E437EEADA87D50515E6C8E86685F8C1567B21A3E314B85EA5889F8CF4325BF021D41301F16F5AA262022ED6B2D12AC070F12E2E6658700B216457C1E0752BBAAD50B9A03DD6FD7EA8E926FC1AA5D5333BE8277AB48B94F51849A10EC67F40DAC37FA4BB93CB6E7F8C7A3AE3022B60FC63877F6888479E6F1895F3292EC0F27D2615FC6853BC804FBA193B81BA5E1842364997A8534FE4B2FB8A3673C874942B638FDC33E9C75637B59262A0D2BEA5891F760BEDAA4B3B2811380469A16B3CE8E9F1B681847501224F8EC50E6AC9D68E28D57BFE4BD6B7E02AE86343E793F7966C5DB728B8162C46E21A5C27A3EB05F93A048503109D6ACB9B397C6AD7AD58E6626F80D1B33855C6B16FE4982E573ACE03D65BF8DE30C7D6034D42E0B8CDB4D4C866860DDEC7D1D5006961BE64D2A19BA877B539E18D466A5A84F284409C140A745E9F034B81584EB4CA3B7F0ECE0BAC6F9D125D52BE4E6768A2FABCEB01E43C1D215CDF6D43D74CDEF2179D0A96263F83D44BFE92925C9B54B5FBF026542406CD664FDB395114A7CED6F5FCB64A9AFC8D3E82D9A07A57C53E8A35293918E03F8C4DFD0659F8C3AC9EC7F150A1F1D11F9B0BDD00AB50432CD255A1DFAB4557808DABAEDB97F761866FA37CF8D415ED2F50EC13259AA4968FFC773BEE 75 | ED45E104504F96E8247417BF78235F84605B8A09BFFB3A6F29BE9961BEB38F4B7441F5EAC69781472321D4C33528F472D658BC4D394CDC7E24B04058C9AFF1E771FD562B9059EA47844B567D0F4565A1F8313776B2BCCEF0E4EF686DF003129A3201FC570FE248A0DE51B451CAFA9D862A97ACC36F7B332801ADCF38718E03FBBCF1FD2CB5E5967C2DDE6BA127D9B74D368D988109AA78577CBC3F09179F8D1B79F8D87BE3CCE6C22B5D1E9091F5F09CA35366FC98E000724F75E83791F029D889F20908FE2EA951C9F7CA5323997A2B991A62B29A1C999DA258C87AA285899DA271A59FEF624D80A46618DFD179F518449BE5E1EDE5A295EF0776E77D04C549D74C938EC6AB542E5402884A4D47194E75870A0E16DAC40E0363DBAD134899A10FFB6562EFD1C6A0360F7E52CB14FF6034E971538FBFED62B03B55030465B794E8E9AE1FC4E9382E48EC6D8AE303245B093B5399BD6651F3358A55164E0DE2DB6DD6988CFAC5DC945284E674D28E2C90D86C094F74BE2F29031C854BB20D1694DF488E3AFEDA5BF923F3E62A459061100C653927B1C71A35E1AF7BFD4ED9452983BD6BAE697F2B7AFCBAA8E52A294A49E1CFAA4833DA0244EA38D3E539D91FD1EDD174B2765FE52E23491C3CF0296256F41509536A22D907096263EEEED285AF1135EAAFB32640FD9F1933818700DF66FD06AC1A0664BD0B50922BC30904CBB2 76 | C0AC850AEB12235E41A50F182E909F9AD28E46A82EBFA84F1F34DE5E5E5987C9DFC86B6CF1BA6F16B27E16C1D33C1D49D03317043FE7D87A259BB8C357256D95F2B54CA4C47153B4E21EAEDB11E63E4065F28D4067E7B6A6F4789E351B7BE19FE8DA7789F27386F72EE2ABF3AF5560D66291BAEC9573793DA8DF684B15D4A8A4E9E374DFFF1528430E268EF5ABC40C89973D1BFAE57F99E854E8773FB6E5145E38E72A9FAC2F11B4F185EB42AA922F78F78D72EEE6BD468EC59F939BC0FC3CC2089C2B055C9785E8975494AC61ADE9BBC8EC386A089E2D0B3EA718C1591CBD4EF20E8D73A194D2857334EE574B72FF4041768DC162C812E58084E2BBEB579C6BB1C7526733F84FE64F4AEEF3B4A2D800FA1C963820A301561A0D8A673A9A24DFEB0BB4C445DEA031F62C6FE7450E0F88F99C547C67A62D0C9DA5ADF8F10AA7C86A43A791229366BE545C51BE3E9E2BC8D8C0C9DFC628A60E6F812BB1731C7112080E3DC125B664B88D6FCD3EE61BB9FF3DAB9D89F288A556917DE317CF1A57809158DFE2DDF4CA7CD77B740923B9030290E42503EB048A2BE2CD4382C39B791093549499315594CA838CEF384F627F0FA9CA8F7C4CE2805A427FE1C14592A4255C7E730B1F9D215DF149012DE0756AA982DEB641B5F37D3F25536DDB92625C56245F7ECD15202F39F52341E5514E45C32192FD0D403703101FCC8A88DA35D97F 77 | 9991CC28DA1169803C207D452E46C8B69F296BF9B0D59C8D8BCDE6690C594690A18F980260705090662A2CC2EF23B37D6806502C9F7C6E0411F91DD17015E07D100C2696A4F56FBAEC51DA29A08CC1C56529B3871A878E06CF5D5020A3378F28133594E06963E40E806F0ECEC5F0B8D6158D63505A20DF0B9E89EA1791783EB9B3D9EE13F239826397D412EB0B781059B393AE89B61583FED6DD1368E7A3941F493D9A224AD788E5609F7A027E3C26E1021FF78A8BD69B63B537E5A88F1E22E8B18302F77CE617C1DF52438468ADA5BC08EC17D71B1A2A19B2E6025E2FBEDEDC2C7F0C108E9AFBF786B75E69719AA4433C0F38A07CAD3776B30991F5192F8F4DDC691CE67E5AD958EA617AED10BE19B5BD94C79FFEAE02493C31B6C86AABD4CED684ADC6C9AABDB76D3CF13BD99BB42DC5856C71E6229126DAD5A84925608AF6C3A341AA29C730FEA290734E9EE2E5AE6D3B852B90B03A0029F2C0ADD05173707AE23A7C0E88EBB2D85F84B0A8A726A152DEC572486B652C0293A76C0FBEE7ECCF3F0CD56ABD6AD0F2CA1F6E60433DAAD6BFA89AD7E486ED79505DB3AA451339AD2DDFE1835AC161F09A00F58A3FC9CB79C56E21F582304390371EF270488609D030F917C9CDE6F28245A750D439AF40FC04BD1ACFDF9FD8AD39E43BF52CA4863A805B94EC80CF69E13B3F54486037E4A7097EA2EEAE27D846ECAED9071FED00 78 | A3395BAD0200BDA4BB1B62E3674D971737584D6BC07E1B0E0FF0E08FC56F60480A37F1A206660DA840A556B70EB2B985C3605642DB516B8365EBF853D8F232EEBA9CAD2C156936DA591CB0F9157095847A31EB65BD92CBAE5D4D8F0D852486403914F433A93D39082863708AC15AF63739A16E70A4B609DC215F891E6739B452AA81C3CCEF9D7721C6327938EE2203F5C42EBBAE4659E2B4B9861632B665BF0B059C8FD6E6B06D8649AC778F69214DA53AD4FE2EB8637B7AA1256EDAE6681EC5C4C934FC60F7460055085983C8063C8EFF5441F9E58932ED21865E719DDD2F02E057B9352B63316421B2087F3E1DB84447934C8594D18C36FD7506D0C022C61C9805B2C4E70615CBCB25C16550084F974B2DFC87CCF9511E0F33D41E23BF819446699DD830D8462E298364657A0739741CC5358A2B0CEB1C5B31E2A74412CE7CAADAB07AD7220D2227C57596B65CCB14BE1CD8A0DE0E583BC128F0589F6664757972729969C3E7DB4ED265C18AC2BD523D3D35593ADC9C6C61EEEA167458660DF83CA64F75F64752A3D2414741C111AD37BD05C49EBC07C5AB9C56460E51A1B57BADED8E26B7E8B30039BF06E475EEEE8D02DA9BC9063BD46EFCAE3E04DCF85A6DE3E4A57F0087FFDD00FFBC43D07D6408965080542E6BEBFED35A0D52264FD4900A74A2DA7370347038523BB1F0B63E262A29A36322C48F1A062146C0118274 79 | E6056F300A0092B6436F62B14DA25FADB05CE35EF5AAA66F79B7679FFAC21543410BA991ADD81CCA958B18AAE9D2FB742F01D7A13E5FC47B17B102FED681A43EEDCACDA2948A43565BBF571D3E8F10A3CF158B3B8E503EEA9F3E2BF8BE10D501E22DE980B766FD933EE8B71C268CC657DE46B69A8BA517B1BE6B9767C4AD7F78B5FCA1D1D7E04B2509562735B474A675733259B73B90AE47CA204176D13CB395A089214B4258E4293CF69492959C1D410B41D4AFF00B9E0AAE7260AD5C9F2124CB9407D0BCED503818FBF758093E58FA9FE5A775486B9F7AA70CE9E07D3A7614FBDEB8D794A9733FA85A795078E2F6112414FFF6F2879976A5520B6E15E98F8AC9E8D671F017A489658BCF0661441F3AAD43F35A71A9003DA51F1EB2932DA843C8A4433A09F0414F8CF16110806AEEE843D3C99294D30CE336702447930EF27D9F6DA2DB6B7E975648D16F3DDAC5096F55C55E10FCE51CF4B7244EBF7B489A72A9685895F917E9B8C34C63F78ACB513553B3F8A8895CE70F836DA312C8FF36A7EBDD8D27C4F2E93DC29E203B6E6E2A50FE7C311B82AE900795797812D598CA0595C89282645FD14D9C3D67B4AA33AD7AC59C5F5EE4893C147A04E29005A463E54391F6859EFC8D89E17404B677E76986C2E9192756FC7C41EB4C239BA51305C32E89C4AD8ACD436002B733211AFEF97F2A3C3DDF3757168F7EFF1F9A766D07C4 80 | 8154C107AD4A9B798A8FF51262CBA2444A2015F37B9666DA349474C506A81561F355179977EAEB62FEF218AAB2CDD56CFDB58F297B4974958F4C1DF68F89DDD3B66454D11F5446E05054D16F43BF9091B6028DCA081F3B8958A395232FA8310ACA3FF61FD172681959EF6364BEA7E246D10E20040654D94C5BC2DAF7B65B2B8AD170FD69EA18B0BB7FFA147530A5E7F67AC36A34B10BFFBD48EBB37FDF96E3312AED78E8AF570DCF38412D18BF03C16A5047B328742216F82BA0D42CC3F615583F6C4B5B22BA0193DE931A16E36DB70C7AE383A985A2390BB35105C1C0345940F645A5C24D67AFB66CF4E20125450B95AC1836572FF9FA2E56FAF3B5627340ABA911156AFC311083C0C51F4AE9CD5382A5D6AFBF0AC8834898A8B9B01ECF6AFE22792CF8F299FFED4646305E3DE6DB16AE8E872CE8E426DEB4A88D0E52D3F84E7322B579A16EAD98B21B0C7DE12DBCCCEF3E7332B98F2E146190D36803D1AC212570349340CA33B2A28AA3C58A812B8C02642545BCCBE13A4CC17D6A8D01EE408E3BF3FC7ABA3404B24097EAA0A674421CDAB3A42AAC459709540ACBCF06AFC3D5E984C013340679EE3D7B4248367815FEA5D0021EF1831462D360F58C648E8FED1684B19C031C7EE483C8EC73C291ACD69CC1456BA3AA1F80BA3FB934B2C54F984EC7ABF1FD18B5E02EE50D5F1080894931B6A35DC6539FFA43B3B89428AB69 81 | DAFAD101EEDA9DA820C832EE89BA05439B7420ADDB3C512696D1FEC12D8EB53C8297C0F96B40DC5BDE35FC950C6E71E82000B79805BAC728CF5F255A34B55A1537179557B7965408535E353B7E08AA594A7F2EB41CC0A5D3104546C0B14A7FD929318FD70C58CC99DA05F66C5D844807FE84F9B9CB0CF2D3E2E94E46E7098B8AFF996FADAF720DF9F9A8A07F16290BFB29F87F6D46385D374A227267ABFAB9B7D04D1280DBD92B9D37CF0650B69DED59D5AE1FBF29BAC12AD491D509C9C0E96DE94946C22D6E25DBC6D0615E80BA9F3724154A0FF9460DD9ACF2B566C10E9652EB1C81F00E5BD26D1A85410D5E4E4DF2B087694D04D3C681812D6F29C8121B3B9F8E44BC532192E67C60A1122FFD3A876E5DEF998812B253836EE2314A497340B2A9E6177655DD734B2CE6F8853048F05412F0DADBFDB319E51D895BB8D4864881748A251540D3C79FA98E2156EBCFC951BE520262AEEEE9C2EF4526F1C2B587CB13F5FD559CF8AEE4690838B6698E48E08008EF5452A5BEF75C23A46B4A34B8BB2018E4835DB813230291F64111CC5BBDFD227A469F017A5E9AC841D5EF3C523E406E0D0F7BAB27C630116218142D865280197DFF1BF7D0D2BAE191482C8DC50B5E0B99404FA7F401E3D97B974819E47F07DF0CA3DE55366623EE376EEADA486C74C773FC12C6C35AD1931596F076E7E5597C3AF06FAA62D3C9F925D8FEDA3C 82 | F0170A47AE659CA13734A370EC6A711D92E6ECBEA74A5E41069233B86FAAA0C7249882F0DEBAD8C43F76D9FB70DD4A4234A9BB8C7B6482B97ED98E6726F6B1052139D1246E86F6EC3C1F40CD41D8210474538BF4933FD9A89CB930AEF97577152A6ECDD98BC4DFC4B753BE9E3E2C901FB3DC8CD51C50EE011CB4208C1E17AD99DEE9885F2965C894979131B4906EB6DBA3E74DBD239559BED840376DD57F75A9886C27BC49B9EF6312D698DC7419837248E62C27B281BA35717353AD14DFAE44681B0E73EFC0F1752CF7C8F1F8C4E3DC31F0711469F379AE64AABCD9E0401990686003E369C8A22747C0C3A808D4F15D82925D64293427FE4566928998FB0CE4E7C09CD1CBD6807A43DA1B44D24C69949843E3126C56BF27B6F5CC1BE7B053165A9F0663EC2A8C3FC412AD3E0CD5F3B93E0A37F00DF58A8569BD529EDD4C0CC21FB78CD67E82189C88345C6F27EEAA04F593F2F6016545C01E66D97E53D5CA4A6FBFA7110830F620B87EFAAAA0659B135788D37C741C01C9AE606246FD81039BDB665830B1051D50FAC517F1F2AB758630F79935E9D30289D963963E2D58EABB4D731CF2CD576DBBF6101100DFEAB3AF304A4F5CFB0457D07C041FD1A673B39E3C46DB4E2F8A0C55167DF41813D685DD07DC34C5740AE83CD02E43D0F4599D7FEAF7024DB2A12C7C2CF14296060D7A46CE382C7D7D3E63235AA12381C5FAD291 83 | 80D42A0C9B1B9C6DA55618A64AF7B2A0B09C122C253A19FAAE0CB21858666500F351998694F74D1763F3E97D32F083FEB475FFA41B30EEC2710D4049D622409A1A23A04C420D079BD1DA56AF2317D9E6F97EB5FC2580DE9990A25FA4270AB344E0DDA4AC4A104BA892746463C5AC5162F8C31054791574C519B23C1ED48BEC16E28B216943CEC56C5A44F08BB5B7A520554EB9249DF2902AEA491187EF5C8A9FFC90E945ECAA137C119B573413004F67FD8362893C3143916B1208FB57352ECC4C26B5602EB1ADF58DCAD844934DF3B125175FF2011615695571BD6EFF107E1B0473A16C401A48D2215E149E813651937EC35AFDCFF4E53BE2548BE6F035FD9DA1880C8077E4A03158302B37299E1D3389A554BA34750C62CFC8539EA5E58553617DE858649EEC8BC4FD805D933F1937D2CECDD097068AB2CE46F8A3658FC83E5F5F96FE7F81214F5AE65E349A561EE9F1A9AE0932315D9CCE1E55653222A1AF3926E284E213027DD777442D1A3F297CA5F710FE3A84B1DDB687F78598CC905CCBA9E0EDAC757F8B4A18793918EC6659F7693A6B6DA8553A23798B8FEF40C03E47549E89F7401A1A2F3ADF4A495F68CBE42FCE439B0D232BA8F7E7257AB300FF3D6DA2E75A2142240286E61FD10EC68D66574C7C42DF56A10BC086C026A4BDF4A1E04E3B4B43D9EE54B10BAE8C0341C4B81399B8F6D1110470C0637C0BA667A6 84 | FA89E299DDD1DDA8F7BA27BAAFCEBFEEBA61C5506AFDB85C77881FD5C7169564623BDE9FDB53A6470EE060D50DA14E0B9043CF5C9F87CABA0C3060D38CDE28DF3D6354A382B2C0F5B3D086B3560BA4DA2BF4788BDB69BF9C61E093F8EE4E2F0C1A574462A3207D4F7CE55319810507CA0D9B4D24D764493D89AEF06A987800E3DEDFABE595B333C02D2A43854DAFB43FFCB7A3535C72331975233BDF96FBFDAE079AB33B5C01A4281CA8B0A4827743482B317D7B3B83B8F2A48D94DB58ABC328C79C748351D3DE2EEB259F5E06AF8F2C670E5900898F3BE6BA5FB125A37613EB18D9EBAD3F2178D6B46E27678A6DC853A6CB1738666596CF4C53F3FAD79526F782387AA7AA3286F58D574D9F56A32EB1A7347E45E958089CEFE58A306D2D4EC66473B303794883D2368685580531B9EBDDAB6E4B63F3FE4C7B62B957A17E5C12AB1569085CA6274D11A30207715C360AB4394ED688626E4102B1F4EA1C7A53A56EAD31706FB9526B653F056BABC8368B2A7AFA14A233D7415E86A6A2D5039FECCB9082AE54CE25D8045A2E41E640CC9E78498644103FD44620CE68FD534E15C0008E5C493F3333F91F57129A33CCA96E181E456D530562CAADF77C2B23C2D7A5D6BE06F662F10BC94CF92CD3F35A0DFEAAFC46411739AE53266D442C673AD1CF25690856D895798E7E0C3086F954D999DBBE4355B5931B5521905C2873F1CF4B 85 | AC099AD0409EDE654F448BF54DC902A0F097BFBAE2E49D6520556D5EC2A7630D5190F828BCD45877E39F1AEF72A529D2695828D58882E407B0CE48C7AE6FADAB6946CD448E4E44D26F8E9824E944EF9E24B14445BEE28A546AE194F635505633733287C00D4E7B58DD36ECC97BB10A44C353CB7BDB89B6D746449BD70A31A0E489BE18D4DC415BA1095B9F64393F87103FE377D0DCA69340C0464D6D9CF5A3AF821ED64D8CDB47E89CD58B1FEF663CE532FC6510AAC1AB2F7316F451195516AC3425E9643B0688797D24AB204C12A3B53E87A4E8C63569F373895AA55D4287695EABABF0B8E43DF2010AA86E01CC953747F77C8EC63EE3179F6BDC0457CB5D158EFBC262954BB86DA5370FD88D80159A446AB0D5EDB185F07FF8F584C203788173ED970DB90CBDEED11E9FB51F2998B0210ED29A49F10585FCFCA6534AC77823005515DF72E5D45E2F62BF4D1C72C00105F1ED15B0D9BE08A00187C18758A68B28557573BCC28A8ED1168B35080CF00102FA0D0008F7A44118FD0D56313DB30EB1F69144E11913D560AF788A056F845E405D74F37C2D91D413A8CB30794D0B7268B1A1BDF42508279BAA491D9D3FEC2E84F85A4399C2D56C0A84BDFEB8107B3D815B3A9B1C6FF6868C5208B4863BF90809D6B19CA43C5E1A26083F2F72C794DB84867204AA6D18AA44780100CB4E848B16972DCE69917241F326C6A9AB483B09 86 | B90BB1B749044575D2F3C7ED106D8193CF78E1212EFCD2C2CE47DDEDA7EA7E447B893EDBCCF68DD68887A00A34EF69FF697A49F8320537DBF2E3EA790ED675B400E27F462F4531C58F79CF31696DDC533BC81E8EEA189F5AE8095607AF60498A3644C841D87A741A6FF90DE389F900C3A1F3DAB60D7883158810F8E1466EB789B7264E5C0A7AA33A26C7517B60F15390FFECF7CCBAB3F8B8BE528E69FA5937489F51123D7E394C81C8CE082BD720C6EA2DA849EFFF6E035DC3EA5330462DCF6F1CBC2E101592374C3DC800A386871458EEEEF33547BA6B69016DADCAB29ADE011F77DD845DEE0CFD85F2165CE823B0244E3A120CDFBCC7FC2CB0C413AB1D058C8723D5212FB21394D38460D3191DA5E04957946759B78927237632AC459E3D6EC046B195D8B7966CD0A25D92ADA9CFB4D07CDA9FBAE431C2A40DCD02B4DCE56DBFA5311BC4FCACA400F504E72D646A652D8AAF1AEBD59BB62A7F2F9462FE5661A6641CE7ACF417B57540990D4CB0C2E613CAB7B86CA06A8ED13BC500597D16F4B253073BABDB852637CCC30F2B115678FE836A488270EAE0E351777708096A27A73F2E8B673B3B7C24855E51997F599D05E27BCD90F52E6F6A1713F3E39E5CA12D0A2DE38B7A55F35ADD07CEE6555E0B6E4027902D9CB7BF237809A9226DB2F0FCF10477C72C628A569E9D92484B5F35F5CA8A88B22C07DC082B3E25AB176A78 87 | B3C9AAB7707DA1336013B268AF2B56E82B73877C2910BEFE70323A5ED5C8A31C5B4E8EFD7E5313175B84B7F0EAD6136D8509F702C2E527337FE045A8227BF8D2A4D7C4D575FC7B4E2BD30845E2BB0F1D6DAA61EE4126AACE0252E1EBCAD7A93C2C76D937F991BA170EB0422D4962BE97ACB82AD271862459412C0DA0D35E876EDB62248DBFA290761D2C172C08D8DC21CEE134A3FEC77F7638760A36CCC17DFD9034534859BFCB1DB92FAB1DD8BB50285D102B49C7DD2968BD9D929653775360046274D20D79CFB7EEDB1E5F860A68012E2DE7C6714B225C238B0F836236A01ABF9F7235FAA2DB0B10E9F8AD379F21DD42497D6A3757513F08165B276B23DC94F009F5FC6529E321426E68D20F565876707D8D79A641776B9377FF1C2F464870AACB1EC6073D02A40C25E9DCECC6566C18E7F50D36CAFAA48D3BBC1A4382E939FC8C56C2F07ADB4B61B0E43AFCB51E30BD27145D9588F70C9703A7E03B88BED854EC543371E3458C6EDE836CE9AB6DB022A6922B1F2D15C9CE56FFE6F8812EA09C9615158DFBD08F05037CC9D04578787FBBCD9AAE389910194D720AB1A4000C06BEB5A9725A1B7361003249A366B1BB8EC27B031BD88B793E80F94509F56DFB6549F48919B7924B99FE8B2BA29BF5EB37057BCA66C04181D01962D8765BC1A19C604979AC9C0358100D475B8B2956A1C903DCFF57B794E7C865FAE73163A151 88 | EF27BEA51441AD4B8EB8E9B165592E8CFB8C66CFC354C1E2B7B0C3010858F1B33591805A9121D5EA01BC8058D5BD7F9806661E06215C4025C59DB3B04FC3C6F7310DFEE84D9FD01466F841327321E44B0CD0C4CE1A4F5078019EFC26201FD1E43ECE55F1F6EA46CE785841A04CBC84CAD7B8C6CE6CAF0454FB91F608F934454AA3555C2E953D1DBB25B8CD6D39C95780E244FD540AEC119C2505AAABCB3699EE01F2789605E684C71F5DFB7D45FFEB084438D31288E8DDB0124F8A920AAF5A116BA02E3513C7C6D33D887039991A6379F573A1A704F05AAA609C4D589551956796416E05491A86BDAC3DE3699F8BB226E4319D0183495D290476B1051AFF13C7A28885D8280CC3664B0071D0B6E35748C86217AAEA3F9531F6C1027EB41D08064010A8758FABD22E7DE8DA8A3F932796D2B640C1316BA1473C554DA7AD735ADB408CF5D36CB740D51FA2B15C4EA1ED538E12C67FCA2D7617C5678BD8E6A6A45138771DDFB5E69DD0FE5AD6D77C8033869A1545D60DFB870C2BF713C1547C39CFEB1745C430EFC9BD7CE245336889EB38515A35FE0F4862155753FDB77295B19098AD6603DF5B85D54FDD0E8D3614F82451F29A2D13CA2276FDB0B675D0152E98B83D4A1884BD67B7F93E39C6684E6570915CF4E407B6A74FABB4CB4D2EB5739702A3D9A55D54876D795FF117701D72450915ED248E64C3E101AB1FA4E668CCEB 89 | 8C2F8E953EA149C07660B2000665EE688397B934BD0848AB35D35795856EFAC35A80FC32A5BCF9CD0FD2F5E526293EE250126EC0AE32FFB2F0ADE326E16E20F52E811EF8C41CBAB5A48E3DB6FFC279601D7C239E78FBD4B9190352EA954438BD5C5F915666A0B5660852D99C12BE8A69833FEE2BFC807D6A052247152D07D8ED9615FB1D89509FDC6EC895A1625214D3D7BD8EDA9067B9FE15EFE43E61F21F2EF0D4B19B058F52DE6A4AAB649999C06F38FB95C4A2AF31A6C6E59E227F719C607C44BD9E0F28022C477186E643AF2AD7D563CF04386EB8BCC843AA4B851E2A4E5182152AB473962694EF5A585DB1290BB25970D92C437C6CC3207220642DC790D3BC089510666FBE9087A139FBE6838D3C691B99C8BEC9813220F7A4163991379D4B075636EFA00DCD357718FE2A6D56D8F5D123580C4FA1111F3D706A94DA272B718FF7B1042D42346913E4362CA7833A0A2A7B30D99A9CD3277109DD4482E679CD013370503333F88C6E978D5F8914DD476D8533CE85C2FC07776BD83D197CD0B03897A93874D205C0F6178FB5D935F357159F20423B9485EBA9DD286CDCE9CB5EB926A60075108631190555B713CE77475E1AB3EE57D63E7889EF18BB870E69BD7E10D9761F5A56C22D7A7710CE4F0EEC71DA6D52EAE15DD9257FAA527A2E18B0BE77781E57B8F56FD4F5B364B343382BF16F13775C464CBA85355693E324 90 | A4FAABBD231FC3E476AD651456C2C8C3F2AFB650A139B8F55CA1DA9B952E42095789D9A7837265DE92FA3CD55DB4819E18407B171C9FB42CE49D13DC1A8186584705AD8BB639319629A58896888B2B77692E9C2FF219BB5ECC865B8E8167AE7101CD422DE0642BE4BF514617F44416936689DEEA9E044763A5437B05C8E0C68FF1B223158B6F6C1D4F4F274C9BCFBD014BF681803CA3B0E1F729E60E24C65846D2C9513B5FF917F66FB1D1E26CC53CF4FFA77F8BA4E833C5C98D1CCD0FDFB9095F9F8D629C2CE5A8E0EAAE071357601EEC6D4E6BB5F14756463FC24914CB93D2B8661FC03EF3AABFDBEDD93B0DECFCC7D323D3324B2E309CB6B8CEF6218197A0CB120A73CA415148EA2DEB077205BC7EF012A2A0D8E73154DD32414A6124157D18C22C73C76AD54575F229EFFF91D227917C7CB7CBBD11AB3E9DBF227D5D482888502D35BA8E3A844A8A53492864BE7BF47DEEAF12A8FE41A1FB3F2F8F1D5156EDA1E64B0795B6BC96BB006086422F6C1DC524181E5233B1ABFB84F4B8D21B2A8F98A00E425F6703FE9A7E372BB04A30FE8EC080ACF28FE24CAFCD4F6BBCBC431A08BA237EAA959ABC700D5E72330BF1873164E833FE430202A97C48F39D3E9E755F0D4EBC31D6B08973DBA65FCBD403B6E59296D436DCD46D315F7A59745C09A47DE3D73BA8F8A27CF65B3BD94CBA4A63062F8D128F0443512C380898999B78 91 | F82D167AECE076F265441AA029E5A029AB2C6779A6B909911DF10842E524195BFDC37C51BADCA14CCFBDBB01D0AA0D26A396DD9EC9DB96D387042B6368E18F5DE83E5DD9D11E53D920D7F515E3CA02EAA497700FA70E65D261B7088D74C98442295C465AAB3872018D2EA7C175C68B91C084399831BEB93D4C7BAF45377261608A6A35A4109A0D4F64355A94B19474FF00884610643256DB774A8CB60FEB477C82E61FB929840BD4E5D00396D2A5ED98F2404D9589C48239C974D086E0A52B572BBEB506E0E5D6CF791465478B6AD11A2FA8BC6B94AFD35C99A620E05AC1A20A3368E6CD7C8F8955D47C811FC66649DD28F09D4450E3094CB10CE63ED3A7A87D925CE9EB2CDDCA397EE622C805C339C0370AD97F0222F4B002D630C9879018C78FC6669BB748C36C86CCA28AEE64BC736B2AF172D39B35B341E5859CE363F39DC5D432155F73BED3E6C9C9487B35262AF0F3206D6721E14464A9036E5E1DB5CD23D53BFE2121C2A1BC5D28D99AC3CC9988ECC71B0A468F024A56A33782B2B9D9CA718BE787E5C4CB3A327560E7997898FDC1E4904FC9EF0B5ECF7541250B3D716B766E242FEA12A66F93FA32A2E00BFC3A09E1727DC6B723E749EA85882EBF29F54A43A15B014236776E3548672D29426469EC070FAEBEC88231D83D40BE123B5A5E4C5167F2A54304D2199FD2DCF398AE3DF73875D161DE6D3C0AACF9BA250E 92 | FCAFDDCB1FE6B7ACD2FA48EC26D6BC2C510E8586C9B7E02E56A056C0103070AAF8A24955C02DF1B90803F499AB1514803DEEE34E90A34E59339E5B738401FE9847C056640112ABB5C8AD14011662D023F4E59C74093436CBDBDE69D705B90C5A2256324F220B1CEF82A1F3FD0360A54149E4E46AEE3C0C3AEB9403166F0FD561B3FB7D13A7C17F5A001B9AA8682410AC6329039FD143BBCCDF79F04C66F2E4F616A2143824CF9DEE3AD72B56488C4BC85548B5F3A0DE781523499D9A317312008D6DF1F9A696EF2B494BAE24F18E3052579A1F4A7A60CF5691312C7585A8668F62E2E1281FAC657CE02289B59E90417F389B5A848C38B7E016C86592D4E5BE55AE317DE16BC5778646AE91E8035CD3AA6DD0BFB3DE48D6AD54A77DF568CAA4DBB78947BF6F9DAAD9B18DDDDC1668FBD78788F088E01E1E0EE55359074E9855B2C6A85E18ACA0FA31DD3C8C5927040292FC896AE5B735D6280DBB963B0E8E7ABE621264748DE6840600D9ACFF354378CCC83D064D9A1DF002CABFAC35BB91F967C8A398CB8C40D938D8F8135DD614F60255660343EB25C39C50A5A52E8286D44712F8913723B4054D600FB29F5F40F44F69BC829A0FE4B2AEA02DA6AB042A62BAB455F64ED08E4362737FF0E94E94A9379B200E32AC8325A5A58163405F14C46FDCB3DE46672ADA9CF0BC23426AD93D72736BC4BA7C8F35158567E18358B25134 93 | FCDEFE18D19C71DF16B76EE0B8A7C1956EC9D12EACDCC47399E488075FCE25E8A9319ADE8AE9233DB44D19E6A2D6AA8B438F43FD72BEE0EED055CEBFFD1319208F3A3D7C76E4892913E6557762133FA8AD15517F245E4788546E30EFEEAE646D57FED3DBE3DA5990ECC1924C139FB9AB7BBCF158BDF05EC5E97BDEA893863397DE35B6D51200A2986A67AF73E573EB2006465791FB3E82E1ADA6FE3264D607EBB201CEE1E84B8EA26DCEBF25E2BB3A829DE165DC14541DFA91CA48F073693C3C75A1B3DD25B6CEE4B352BE9E216069E4E0A593387A3FB179DA446F299EA08CA71A3CB87028BCAAFC75AE33661266ED37A6E4049A4F4D20011EDEAD1A01F8F243CE2CBAD73961B9A9D178E909A886AFBAE05556E766E23BF0D1C5AF6D3B89C6379DEA28BCFDA65427AD174A3A476303121A8BAFCE3E41C1CF44BA79EC4B369DA8B3D4C7296A42D86DDCB2888597BE9B3725C15CA26103FDE39633C05FA3F03A2AA991D8102CDAE89C5386FC9F7EF3877394E3D0AB6C9B2D43906969DDEDE99941ABCB522EB1BA9CDB61F99C611C46FA611275FBFC0B22E79434D6D418E70711D3415E49DADCFC4040E81B459C272D93B6FC4B01D369CB3BC6C296F761BF4B318D455A3A8516825076EE08F97A80B797E31AB7648651C786FF493376C5693C98A48C218FFE50DE5EF3213F451D5954085C4F8AD09CD704B5419C3EB9AF20415668 94 | D929A5BF76D43593DA159CAD167F650C00463C7EE5AD862F64BBA5B6612BA0B5C8877B358FA84D9A81BB43D2B7B54C07F03A1C674E4B74A9E9CE0F3D9B945866674F4E53E335B5404CAE95CEE46EBE6D651BF49FB833E7E2EFAD9EC88AD1816D6EE82B4F4A26156AD359C8FEA144AD6727C532A615F8F9C84AA2BDB46C6C760AC4227DA3C492FA49E1DE264DD04B56C036B0E5F39E3A9E442CCEE315CBF04F567B58A68055586274F533DD75F9BD76D19A6FB35747A045607F93E92E8A9552AD7866657FFABDACFB27CB19DE63FA53CC47FC0C70F0968E8A111D444DC51F6F4AA7811AE2000A5F3ADF0F9D83B9BD5450212B5859CB339430E4783ED6CBB6AAE5EA37B4DC64F3BA0E94EF0122B5289AF4817E09E13558539FEEDB51DEDDB9ADDECB4281B219392F139ACED2EB84111DE059A9697AC63F533DD49CFDB68B04F2154F057D03D900591FA95D9D3F3587F6B3051AFFFE1D550C29566B01574C608BBAB73B9EE4A663AC4908BB6FA0191F799C3012AF634D86B1B5926BE3104502EF28B45773A772B6F97A98C9C7EA6F690A538C590BD58AA6126AD5631CE8B7639067AF2962FE875E41115122D8C72EBD7C4054EBA9CFAA743258948842FC8F14BDD940723976E25D6296A03D3B81EF08D22B7FBCA98979586887327C71DE75A0CEE33DAA7F986D4477DFAE03B652B385AF42C690C3CB40BD4798194FCB19372AD4A4 95 | 84D87D5C94336095AF189EDC5E8736B16E27B46A6B411E8FBD09AD38F418561C84140D60E254C09C397952EED21E33E5FD160089330677CF22C8C0E89DA35F9D4EA6AA1D8B626E10BF4A687E5B4BDB891EF48DC027E31C93D5DE4C7A39D94B49D4176F7F2B4050910CD77CA5033C24D8D0C3C9920829F2F4FB6AEAB2F6FF0187F3490F3F7E2C2B02D3C6A04077A78F1E64F67A34077E00F5B027847D0067CE228A17297BE1F677F04AFC0C55D10D908AF016F72AC5C57F99189BD6ED167BC940C251560AE912057C67F716ACA15D29FF4699954ECC4DEA93732BC146DFE73DE3F38BD2A2863462FAC204A26A6D2345ACB376DD4569BF18A283267B1FFC70DFE3C7A95AC98F15495A82718FFFEB7A66A356E6BE03468A6B21E69ECDBDBF7C56B96C2C8BE1E52F6C407A5F735D2B54D30D6DF461E26049A7E2B75898B8A211A3E2305DD2329C77A413CDC34294ADC2E47C7A2733BE49DC2ADCB4EAB33319F3A2B8325D642B31DA0CF3A53DDBCCACA192DF54795F7E168EDEBA30DF6E263643C814BEF5E89A49AC103531990D8299ABAE173A3A9728842E7F5DF515D6BBA178369C326EE101616D6AC847D50634262B5C8D9043E1EAA0EB2A0EDDC3C19C1B78D584EC1203EEEF47A4EE6DC11FD6C56AD0BEC5E6E57ED2BFB9FD1E320BB1FA76F617ED694571AD2ACEE584D0DF415A67D3CDFB9248603676300D65D5AF06DD0F326E 96 | FF1AA36F3240EA3660A49FDD12F97EB28A499E137CE8EDCBB93A605CA59447B207BC0C9E5B812FCBABCDDA745727D6062B22417CC64FB20DE0D72181548F334E91340587F5D66E22A4B4AB7D8255E81AA2A420091659AE586FB5733EE94A9DF3BD3248FA18AABA5EDD83E6641144D702C68446BF501366B4292357A1F74A45B9D7542C213EE99AC26E9D5D4EF61850A55643D1575CDAF532A9391C542862C81350105A59A354E56368F808CCFB637CEE52DB352613DE01AA929E080577F3723998B7FEC12E9FFB9858D0473AC2B9AE5CDB282B7BAC43506C915871C2080DA7576DC0D122AC1640D2535883227A3CFA2A63915CE8F6AAF1055601D01D70532329D0D53F2AE27716DE2E41EC83A654DE8A735BC0D25668F899E0E328941CAE001FB385ADDD48913CA4329790214931E03C3C53D2A468A481F1652BE55736847FE189D51C744B3BB96AE81A4EB0E87D6A1FB3AB0CE41B053B70C5BBAE8CF112B7D4C1E22BD88BE8BA24BDC9F0FB4F7A2906D33691269CE8E8895934AC108DDEE192CFA32C4BCADE2B582A2DB4C31AFEB7124C7FF322DC3652119BDFE763E525D48644AE58B1640E7B47626313AE22FE21D1F259F7D587E15913B100B56524822C9BA611EC00CD0D71B73448D85AA53BA0129614AC67BB9443EF2DA417F903C2BE6B8A472A58A62A205C91AFF1E15BC5E7154289D422BA10FEDD04917652D28F1177 97 | A3D1DC2A2328544839C08F62AA8A5F8AA5E2987260E90ECAB1720DC97C7CDE6275898D72C061C8E8C125A96992AF5A6BF04C833F75F0A8A0C136B6E2AF208C304D5230BE13EA4B7351E826EAE2C9968C207AAE593DEFFC9D06DCA8FFD6071369155A8F77093ED93A8413D8BE8212CF9678F4936AC28D03DECD2E2F0C3D0E2DE8ED2DC196740BD5F0DA27F7741694D018858083B703C0BDFC5796EF95D678B8ECDA81819902C83AD09DD8D6CA2F38772141598E6E13DA53C6E5931DBE23D691EFDE562D179F214698A4FD279640CD43DB253B6AA53E61508A3A52CEA0364A4E6211C9216B8EDF4B23A6B22289833694380F1210BE4107BED494FFC5CC88EB5608C211D8A9930A6E3E9740E69D7429C197BC953D96FC7784A459A69F5BBD8DBD91A2AE5BA30545BB848DBCEDA865993925B2591C5B71365C76045622B73C7FF7F5D85A4DCBC40AD06919FE621BB65A70F0BACACFD9882E383B798382764E016ABDE0688665F25784E8497D97A6AF8C703912BEED3DE431C3887D32D0995A8D8032C2072D87821C21147EB248A2963DADAD06AA77963CEE381DA1C808A5C10A279ADE215767FC961363C2BFBC3B7310945A6AD84021A4D3040C933FF276D089D232AA5386E8AF66B42FDB6B3740F1E318301A700936910739E73BAA482463FCC30A4F35DAB3752356E45C43B537B6958ADEA3AE517C3136842A15B08B3EA18DF67A 98 | 8034408F049228BD5110D26D918A447083F5514AA635D7E379998F9567DECABA6A5D11B544242C71536C1248D72A9BA0F13A7115A5097F492FD409FF1E8D7CD9065997B9426556943F72C6F02CF416A66099BEC22AF90B18B0A8C471FFC5D298FDDE2C5B19EA97CF1842CCD494E8086240A46FCBA654AC2269B10834D427F92F99F96BECAD545BC36E1780502E94B7846E9BC0CF299673700E75FD048BAE19111D4976531D0E3CE51166DD3492708C8B35CE3930B759B6B6C3A8F2CD838D51DD05CE62CDA562A657327212788E732A60B30856555DCE3FBF4F521FA95A9BDF751F15C06271C2B753A1F9FFDBAFF5C7589DD7E18051B3B67FB34879792DAA2218EE53C887291682954DEF628EF58F3E230600A966D1EB489AEB379B6C2352EA5F0B9D74987A82C6B6618AE3A53507B25CD7ADBC8B2C6EC54621E3EF5C259CAE4A01CAC8D6FF12884F59CCF9EB8E6ACBC5971D9B17CE80C18202222C97A38EB1E8FFBBFB28B8DDC89C7F9DFA9FF962B1B307162D7B36F3B6AAE7014D61674B2A4DA40A6DBFC0DCB6D34136EF5EA06C959EF029E10E07564F1698047D28ACA32D2F3F31B5BF7DC4CE3C7D24DB4219FCF27148AF9F328EB81ACF8A8D81A20724214B2CD23D40CF251041CC3CAAEEFE785EF964116393FDF1306E724ACB9D32B16967A8096EAA03D219EF43E73E9FC4BA2ACE8690E354D0899F95230864F684A881C4 99 | 84111F4A3D091008A38C963CA9D338CCABD289F7E8AFD2E81F30244BAEEAE87AA7B23E680231D7052663352967A32BA286BC04B305EAF222680B18AF931D85E63E729A90DB543BEADF30E84E42E67E6DD9A2C10ED43C9FE8667B701691E2D29BF26163E68A07F38BE68BB5EBD53741A0AE0328076D1D4F2DCE9C78750DC6791ADAE241E2947175DF77B60ECC3D6AD04261809AF6A6EC5EDC6A2185BE014CD6C6C09BC803BF5C8685DE5EEE0E6EB8161BC8B3C048EA221590AC9BE0CAA87DF657570E5180B25E002F5261E9A4A3FE880E68BF40CFC54FD7FDDA7F655165636A5B8C5D260D7B2BF87DCB547196EAF5BEB9E7AC7C0A3770B5FCF3B4B6AA47413C6CFF954C534682FD7BA1A00D33D23351F0FD5A89E08EA23F1C0E5662E33F0A24E4BF3CEA37E7FE53F04F2EDC62F37FACC11454FD0CF25246C0AF189BD3DBEFE621B024656F41920427E39CE17BEDC907190904238182F4368709335683F7C2FB67E5E1E4640E4239899660958018DB8DEF0955FCCBECA1E990F76AE2BB3EB92983882ED30EC15F11B642C71A88C81F111C51D1A926995BE524FD1DB7EFAAE3CF8EA553A2215DC8F08DC5EF57F29EB8B36828E818C07C8134064A5128DB9ED84A7665BF9BD7ACB6D632C4A15DC0D18F4C5F235C3C9978762A53ED3E340893ED52AC637D62B6D8FA2D9EEB305CE5A25CF529189E12023FAF79EA81309759C443DC68 100 | EE093DA13DCE9CC1B55B4F9FBC4A60474A6CFBB79E6410307566833A075543AA0260A85DCD2CCC2F6A99F7302FC459D6775A5201E390EF22AE78D94F39595D175B4A61C397C8B347A48328CAE2A377DCEC6804A41519F8F69817F70CA3D2B28D14EDEEDC72F381B2D0A536FE9A11BC156BBDAE476CACDFF0B1AEF4359862F5E99CA50D9ADBE1E6291EBE15F76D81768BDA24CA4926D7746C9E3E255B840A7CCC8DD17F0C1D2F1BEEBCBAD034651F583B13FA0B9FFC201E3BB2F798D508B821A18609669E475878A39E2C7E6951281ADB0504EC3021F63F33037AEB0EC6ED77EA7FE5E12119462DBAFAF866AD8127D96896E69717C93D1DFD478A372777B826709A390434F1D7EAA72184368E80A6247DF29AA6E69B7FD7975C95A0A1C85A8B7A04A7CDD7EAA7F34CDC18D68754F1FAB2C75FE0C516336CCF84B1CE9CADBBADF77D56FF3FF75FA43F68E2041AC921FD34921628F67C640EB1E9E1300B8963721D55E5E8C32D7254C20C89CB132C40D3C10CB18DBA9491CB38C8EB25952893C3698686322AA744DBD96425BE2F599230626D512E38AD88CD16F8B6D66BCE3325B03B631413A4C4C9EEADC2A6A78E041EC440DF6476DBAC84698252A815DFDBD4CC2CEA29CE53483A42CE443794F01E73CE3B83EFAFB91106FAFFE3B59746DBFE52FBE3B830A292D489510A23527DE43265D33B190B239A827B6278A3A56392A8CC 101 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -c -Iinclude -finput-charset=utf-8 2 | 3 | all: simplersa 4 | 5 | src/libRSA.a: src/Makefile 6 | cd src/ && make 7 | 8 | main.o: main.cpp src/include/* 9 | $(CXX) $(CFLAGS) $< -o $@ 10 | 11 | simplersa: main.o src/libRSA.a 12 | $(CXX) $^ -o $@ 13 | 14 | lib: src/Makefile 15 | cd src/ && make 16 | 17 | clean: 18 | rm -f simplersa main.o 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SimpleRSA 2 | ========= 3 | 4 | A simple version of RSA algorithm implementation. 5 | 6 | > No voice, but big deal. 7 | 8 | ## Requirement 9 | Write a Java or C program that demostrates RSA encryption and decryption algorithm. 10 | * The program should support 512, 768, 1024 and 2048 bits key size. 11 | * You are free to use any C++ package or Java class to handle big integers. 12 | * We adapt the convention that Bob is the party who will announce the public keys and Alice the one who will send Bob message encrypted with the public keys. 13 | * You can refer to RSA-Tool and the following interface, and you are encouraged to implement RSA-OAEP(RFC 3447 or PKCS #1 V2.1) or other special functions to demonstrate your work. 14 | * Please include comments in your code, the test files and the sample output. 15 | 16 | ## Algorithm Analysis 17 | 18 | ### RSA algorithm 19 | * 数据生成过程 20 | 21 | > (n,e)为公钥,(n,d)为私钥,要求n的二进制长度分别为512,768,1024和2048(bits) 22 | 23 | ``` 24 | step.1. 找出两个大素数p和q 25 | step.2. 计算 n = p * q, t = (p - 1) * (q - 1) 26 | step.3. 任取一个数e,要求满足e < t并且e与t互素 27 | step.4. 计算d (d < t),满足d * e % t == 1 28 | ``` 29 | 30 | * 加密解密过程 31 | 32 | ``` 33 | step.1. 将信息流分段,每段可一一映射到一个数M(M < n) 34 | step.2. 计算 c = (M^d) % n, c作为密文发送 35 | step.3. 计算 m = (c^e) % n, 则 m == M,从而完成对c的解密 36 | step.4. 将m重新整合,还原信息流并显示 37 | ``` 38 | 39 | 详细描述可以参考[这里](http://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95) 40 | 41 | ### OAEP(Optimal Asymmetric Encryption Padding,最优非对称加密填充) 42 | 43 | > 在RSA加密前进行OAEP过程 44 | 45 | > M: 填充信息(m-bit),P:明文(P1 || P2)(m+k bits),C:密文(m+k bits) 46 | 47 | > r: 一次性随机数(k-bit),G(x):公共函数(k-bit to m-bit),H(x):公共函数(m-bit to k-bit) 48 | 49 | * 加密过程 50 | 51 | ``` 52 | step.1. 生成一个k-bit的随机数r 53 | step.2. 运算生成明文 P1 = M ^ G(r) 54 | step.3. 计算明文的第二部分 P2 = H(P1) ^ r 55 | step.4. 合成出明文P,并用RSA加密,得密文C 56 | ``` 57 | 58 | * 解密过程 59 | 60 | ``` 61 | step.1. 利用RSA,解密C,得明文P,并按m+k bits分段成(P1 || P2) 62 | step.2. 作运算 H(P1) ^ P2 = H(P1) ^ (H(P1) ^ r) = r,还原出随机数r 63 | step.3. 作运算 G(r) ^ P1 = G(r) ^ (M ^ G(r)) = M,还原出信息流,并显示 64 | ``` 65 | 66 | 详细信息可以参考[这里](http://book.51cto.com/art/200901/105944.htm) 67 | -------------------------------------------------------------------------------- /data/1024-1024encrypt.txt: -------------------------------------------------------------------------------- 1 | 41.6200 2 | 41.0200 3 | 41.0100 4 | 63.4500 5 | 63.2500 6 | 64.2800 7 | 63.9200 8 | 63.8900 9 | 41.8100 10 | 41.9100 11 | 42.0200 12 | 41.8700 13 | 41.9900 14 | 42.0300 15 | 41.8600 16 | 41.9500 17 | 41.8000 18 | 41.7800 19 | 41.8600 20 | 41.9500 21 | 42.1100 22 | 42.0900 23 | 41.8000 24 | 41.9900 25 | 41.7700 26 | 41.9900 27 | 41.9600 28 | 42.0700 29 | 41.8000 30 | 41.8200 31 | 41.9200 32 | 42.0100 33 | 42.0700 34 | 41.9000 35 | 41.9400 36 | 41.8800 37 | 41.8400 38 | 42.1000 39 | 41.9700 40 | 41.9700 41 | 41.8900 42 | 41.8600 43 | 41.7900 44 | 41.8400 45 | 41.9000 46 | 42.0000 47 | 41.8800 48 | 41.8200 49 | 42.0000 50 | 41.9300 51 | 41.9800 52 | 41.8100 53 | 42.0800 54 | 42.2000 55 | 42.3700 56 | 43.3200 57 | 42.6200 58 | 42.2200 59 | 42.2400 60 | 42.2100 61 | 42.2100 62 | 42.4200 63 | 42.4600 64 | 42.3300 65 | 42.3800 66 | 42.3900 67 | 42.2700 68 | 42.2000 69 | 42.6200 70 | 42.7600 71 | 41.9500 72 | 42.3500 73 | 42.2700 74 | 42.4000 75 | 42.2100 76 | 43.0200 77 | 44.3800 78 | 45.9800 79 | 45.8500 80 | 45.0900 81 | 44.9900 82 | 45.2300 83 | 45.5700 84 | 43.7400 85 | 42.4000 86 | 41.7100 87 | 42.1900 88 | 42.2500 89 | 42.6100 90 | 42.6000 91 | 42.9400 92 | 42.4900 93 | 42.5100 94 | 42.8100 95 | 42.3900 96 | 42.6600 97 | 42.7700 98 | 42.7100 99 | 42.6700 100 | 42.5800 101 | 42.4400 102 | 42.4800 103 | 43.0000 104 | 43.3600 105 | 42.8800 106 | 42.5400 107 | 42.3200 108 | 42.4000 109 | -------------------------------------------------------------------------------- /data/2048-1024encrypt.txt: -------------------------------------------------------------------------------- 1 | 86.2800 2 | 84.7600 3 | 85.7900 4 | 84.2900 5 | 84.4000 6 | 84.3900 7 | 84.0300 8 | 84.6300 9 | 84.6700 10 | 83.8900 11 | 84.1900 12 | 84.3500 13 | 84.3000 14 | 84.2200 15 | 84.2200 16 | 84.6900 17 | 84.1700 18 | 84.6800 19 | 84.6300 20 | 84.8800 21 | 84.5500 22 | 83.8200 23 | 84.2300 24 | 84.9300 25 | 84.3800 26 | 84.1200 27 | 83.7900 28 | 83.7600 29 | 84.5300 30 | 83.8100 31 | 84.8800 32 | 85.4300 33 | 84.5400 34 | 84.2200 35 | 84.8900 36 | 84.6900 37 | 84.3400 38 | 84.3400 39 | 84.6200 40 | 84.2200 41 | 84.2500 42 | 83.8900 43 | 83.9300 44 | 83.9300 45 | 83.9300 46 | 83.9200 47 | 84.0000 48 | 83.9400 49 | 83.8700 50 | 83.9300 51 | 84.0300 52 | 83.9000 53 | 84.0500 54 | 84.0100 55 | 83.9500 56 | 83.9100 57 | 84.0100 58 | 83.9800 59 | 83.9300 60 | 83.9900 61 | 83.9900 62 | 84.0600 63 | 83.8700 64 | 83.9500 65 | 84.0000 66 | 83.9700 67 | 83.9800 68 | 83.9400 69 | 83.7800 70 | 83.7900 71 | 83.8700 72 | 83.8500 73 | 83.8100 74 | 83.8000 75 | 83.9500 76 | 83.8000 77 | 83.7700 78 | 83.9300 79 | 83.9800 80 | 83.7900 81 | 83.9000 82 | 83.8200 83 | 83.8900 84 | 83.8900 85 | 83.8300 86 | 83.8300 87 | 83.9500 88 | 83.8100 89 | 83.8600 90 | 83.8800 91 | 83.9800 92 | 83.8300 93 | 83.9300 94 | 83.7800 95 | 83.8800 96 | 83.8900 97 | 83.8500 98 | 83.8000 99 | 84.4800 100 | 84.4500 101 | -------------------------------------------------------------------------------- /data/512-1024encrypt-oaep.txt: -------------------------------------------------------------------------------- 1 | 21.1000 2 | 21.0200 3 | 21.2400 4 | 36.4100 5 | 34.9700 6 | 29.9800 7 | 27.5800 8 | 36.5000 9 | 36.4900 10 | 34.8700 11 | 22.3400 12 | 21.7200 13 | 22.5700 14 | 22.1900 15 | 21.7100 16 | 21.4900 17 | 21.2400 18 | 21.0400 19 | 32.9400 20 | 35.4800 21 | 35.3300 22 | 35.6600 23 | 36.0700 24 | 35.8800 25 | 35.9600 26 | 36.1800 27 | 36.0300 28 | 36.2700 29 | 26.6000 30 | 21.2000 31 | 21.0500 32 | 20.9900 33 | 21.0900 34 | 20.9000 35 | 20.9000 36 | 20.9200 37 | 20.9000 38 | 20.8900 39 | 20.9700 40 | 21.0800 41 | 21.0700 42 | 21.0700 43 | 21.1000 44 | 21.1200 45 | 20.9700 46 | 21.0300 47 | 21.0000 48 | 20.9200 49 | 20.9200 50 | 20.9700 51 | 20.9700 52 | 21.0700 53 | 21.0100 54 | 21.1100 55 | 21.0800 56 | 21.0300 57 | 21.0100 58 | 20.9900 59 | 21.0100 60 | 20.8900 61 | 20.8900 62 | 20.9200 63 | 20.8900 64 | 20.9000 65 | 20.9300 66 | 20.9800 67 | 21.0900 68 | 21.0500 69 | 20.9700 70 | 20.8900 71 | 20.9000 72 | 20.9500 73 | 20.9600 74 | 20.9000 75 | 20.9200 76 | 20.9500 77 | 20.8900 78 | 21.0200 79 | 21.1000 80 | 21.0000 81 | 21.0300 82 | 21.0600 83 | 20.9900 84 | 20.9800 85 | 20.9900 86 | 21.0500 87 | 20.9800 88 | 20.9900 89 | 21.0000 90 | 21.0300 91 | 20.9800 92 | 20.9900 93 | 21.0400 94 | 21.0500 95 | 21.0400 96 | 21.0200 97 | 21.0000 98 | 20.9700 99 | 21.0800 100 | 20.9900 101 | 21.0200 102 | 21.0200 103 | -------------------------------------------------------------------------------- /data/512-1024encrypt.txt: -------------------------------------------------------------------------------- 1 | 20.7400 2 | 21.1800 3 | 19.5100 4 | 19.2300 5 | 19.5700 6 | 19.3700 7 | 19.4200 8 | 19.3800 9 | 19.3400 10 | 19.3100 11 | 19.3700 12 | 19.4400 13 | 19.5600 14 | 19.6400 15 | 19.4200 16 | 19.4100 17 | 19.4600 18 | 19.2900 19 | 19.2400 20 | 19.3600 21 | 19.3000 22 | 19.4000 23 | 19.4300 24 | 19.5400 25 | 19.4000 26 | 19.5100 27 | 19.3900 28 | 19.3500 29 | 19.3500 30 | 19.1500 31 | 19.2800 32 | 19.3200 33 | 19.1900 34 | 19.3000 35 | 19.3700 36 | 19.3000 37 | 19.2600 38 | 19.3900 39 | 20.1900 40 | 20.0400 41 | 19.8500 42 | 19.7300 43 | 20.2200 44 | 19.2200 45 | 19.2500 46 | 19.2000 47 | 19.1600 48 | 19.2200 49 | 19.2900 50 | 19.2700 51 | 19.3000 52 | 19.2100 53 | 19.2800 54 | 19.3000 55 | 19.2100 56 | 19.2100 57 | 19.1900 58 | 19.1900 59 | 19.2600 60 | 19.2000 61 | 19.1800 62 | 19.2400 63 | 19.2500 64 | 19.2700 65 | 19.2500 66 | 19.3000 67 | 19.3000 68 | 19.2200 69 | 19.4500 70 | 19.4400 71 | 19.2800 72 | 19.2700 73 | 19.3000 74 | 19.2400 75 | 19.3200 76 | 19.3500 77 | 19.3200 78 | 19.3400 79 | 19.3800 80 | 19.3200 81 | 19.3500 82 | 19.2400 83 | 19.3900 84 | 19.3900 85 | 19.3000 86 | 19.2200 87 | 19.3500 88 | 19.2400 89 | 19.3400 90 | 19.4000 91 | 19.4700 92 | 19.3700 93 | 19.4200 94 | 19.5800 95 | 19.3300 96 | 19.3300 97 | 19.3800 98 | 19.3400 99 | 19.3900 100 | 19.4400 101 | 19.3200 102 | 19.3300 103 | -------------------------------------------------------------------------------- /data/768-1024encrypt-oaep.txt: -------------------------------------------------------------------------------- 1 | 51.2800 2 | 49.3700 3 | 51.1200 4 | 51.3100 5 | 51.2500 6 | 50.9900 7 | 50.5600 8 | -------------------------------------------------------------------------------- /data/768-1024encrypt.txt: -------------------------------------------------------------------------------- 1 | 46.1700 2 | 48.7800 3 | 49.3000 4 | 50.2400 5 | 49.9700 6 | 50.8100 7 | 50.3600 8 | 29.9100 9 | 29.8100 10 | 29.8400 11 | 29.9300 12 | 30.0800 13 | 30.0200 14 | 30.0100 15 | 29.9800 16 | 29.9400 17 | 29.8700 18 | 29.8100 19 | 29.8000 20 | 29.8500 21 | 30.0400 22 | 29.9300 23 | 30.0800 24 | 30.0800 25 | 30.0400 26 | 30.0100 27 | 30.2700 28 | 29.9600 29 | 29.9900 30 | 29.9800 31 | 29.9400 32 | 29.9700 33 | 29.8100 34 | 29.7900 35 | 29.8000 36 | 29.8200 37 | 30.0300 38 | 30.0000 39 | 29.9900 40 | 30.0700 41 | 30.0600 42 | 30.0100 43 | 29.9300 44 | 29.9900 45 | 29.8500 46 | 29.8100 47 | 29.8000 48 | 29.8200 49 | 29.9400 50 | 29.8000 51 | 29.9100 52 | 29.9700 53 | 29.8500 54 | 29.9300 55 | 29.9900 56 | 29.9700 57 | 29.9600 58 | 30.3300 59 | 30.2700 60 | 30.0900 61 | 30.4000 62 | 30.1300 63 | 30.1500 64 | 30.1700 65 | 30.3100 66 | 30.0900 67 | 30.1700 68 | 30.0900 69 | 30.5600 70 | 30.4400 71 | 30.3300 72 | 30.6800 73 | 30.4100 74 | 30.2300 75 | 29.8800 76 | 29.8500 77 | 30.0300 78 | 29.9400 79 | 30.0300 80 | 30.0500 81 | 30.1300 82 | 30.0800 83 | 29.9200 84 | 29.9400 85 | 29.8900 86 | 29.8800 87 | 29.8100 88 | 29.8700 89 | 30.1000 90 | 29.9600 91 | 30.0300 92 | 30.0800 93 | 30.0700 94 | 30.0200 95 | 29.9600 96 | 29.9800 97 | 30.0200 98 | 29.9800 99 | 29.8500 100 | 29.8300 101 | 29.8100 102 | 29.8400 103 | 29.9400 104 | 30.0400 105 | 29.9000 106 | 30.4800 107 | 29.8400 108 | -------------------------------------------------------------------------------- /data/rsa1024.txt: -------------------------------------------------------------------------------- 1 | prime = C9DC63DFD7E7714AC6FA0943C2259CDFAA46C85B86290482C81676E280116FF16AB2EC72BEAD231B985A5C74B469926C35481D125F811C10106A8FF5ADE19221 2 | Time used: 156.6900s 3 | prime = BE521BC1EF0B9773EC345020232749D728984720792B210C7EB1ABCEB13E694546194B0232B7383EBC9423AAFC6BC51D53A99A377C36146FC88F730CCAB91959 4 | Time used: 312.1700s 5 | prime = 92AE568AC7E4E04DE25FAF6D914F5FE80ED011BA090F2037509BB12FF090F29B06E7EBAF05D84CA8AAB967C6ADAC958012613B235CBF8A1B839A95DE9F015DE3 6 | Time used: 562.3000s 7 | prime = B70979DA9173B6B7FD9508A3171265C581FA4135432127D9D535389218C4420C373C818F2DC78A12B5112DBCD8B577B20ECF77DB8BC8FEF04D21773EC162558F 8 | Time used: 429.9000s 9 | prime = A0A1B12DEDC5E92EB66D56EDA28CCD0ED1F4B582BAAEA0CB5BBCE314B6AEAC6DB1A887AA00AC7FA6C4D7ED6E81C8F5C5DCDE06AF8292A6C04A1CF58E3DE2CF7B 10 | Time used: 126.0400s 11 | prime = 8B7EF379B8EA5D967F7ABD1893B4E15625D4D16DBF7111E99614A5FB5C362843394239E0A1C962EE040744AD741981C90F981707E8B8AAD406B3BDA356DF560B 12 | Time used: 72.5200s 13 | prime = DEF1E8D9922C66C512F2CF88AAAAACB0397CAB04D6D80795967CF372319C702F999217FB7A58A913F04A72D0ED6451A505B7D2B27040FE1F6F46BBCC8F3B2AF9 14 | Time used: 677.1400s 15 | prime = CDE3D2832A3CD4DCC9BFE4CD785F8C44CA3607FC0BAE385FA1AF8BD8FE6A3196B402628713C3643D8288FC1C6D7E96B8E7435826E708C15D570E2FC40ECBE03D 16 | Time used: 62.2200s 17 | prime = E9AC0D8741C7827384A12629D83821C8538D46F09833062B9E5354912C9CAF0149CCAC8071A5829DD0C4D18179270B3B5298BAC61FC30573B2FA1DB56777476B 18 | Time used: 483.5200s 19 | prime = 86442F1E7CB290588657F5CE1A272D4F4185AB6E4FA05CFB6E215F8C598F2201149ABAFB62A47BA94256A809176F05E8A589BADC761865A56DB40A5ED61FB9ED 20 | Time used: 267.6600s 21 | prime = BCEFAE7CBC3C6CB938905A62031ADF0B4F8A164D7D5AC4CFC993178F8C8C85BEACC3EA4BA8F9D05F6AFA767C0F814B99677B8CACC6E26A997E2773C96B10DF91 22 | Time used: 113.4200s 23 | prime = B1B69DE55ECF06F6FBE2F81717820F8DAAEF8EC6E6DD43922D5AB1CC71582A7EF6981995ADB49BCAAE83609CCFB8A52E4AD9417B6A2F8EEF4CC3A21F6AD682E9 24 | Time used: 510.0400s 25 | prime = E98662F689C34D20E09ED4B6555AC3A8C4CE3AA8108D90A050438113D688F008E6814CA5755729B87F18BC87BC1311BBECABDF04AA46F54110070EE11EA85943 26 | Time used: 194.1200s 27 | prime = E30C32E28857AC2651C6EE859D8C31AC515163E422E244A69CC675B007F22869C9B2C30007167D92BF0D7FF184B06496693DC0D5C7C81ADF4A8527AABFAFC949 28 | Time used: 151.4700s 29 | prime = ED8EFCF77F1E79F63779F18C50D75E16A3893A6878AAF4A121161382184D0B69027A8889DD99480D4D1D6AE6B5536675963EE56944F02268A251B51ED6D5F43D 30 | Time used: 561.2600s 31 | prime = E7A7BFC42300329B73DCFE7DDB8AE11D3CE6277122CE6446CD673C239BCF2AE2B164C9B984623D9D1830CA448955B0D93C1222A3FD9D8AA3FFFC30CB288CF38D 32 | Time used: 266.3900s 33 | prime = A367FB05B125A0A16227B3300FC9B96717BEFA9189F31168C2149D37CC4282BFBD253C2C9E099FA1D78FA6418D6DED023D4333371C0957795CBD59B65C001C87 34 | Time used: 83.8000s 35 | prime = CC8760EB826BC6FCC8210839FA458388CEBB94599EBAC28C95744C6AAEEC89CC5B2FED5407C2FCB54B26886F106A66AFF3D6478009B0968DAC28F6513542C23B 36 | Time used: 28.2400s 37 | prime = 8886C0716FD0D6EDD39EC66A1008253B88E6E65518C6DF66907ED7120686AE8A7F96AC87229092E0100E5D73DAD95C2E018B698C7526EA6A9DFAEEDDD516E1F3 38 | Time used: 321.8200s 39 | prime = CD7F6F7B27F7E914D5E8139182EB4196AEDBB4A023C3B85DE471D568E81551E764716C66653CE224696FBADF3A847229E5B6CF8FB336B2671A25A54E31A1C9A1 40 | Time used: 30.4700s 41 | prime = B81B6C4CE0C331FAAD1041E5180E79544AF3948B2B93A7201D67E19EBEA1A72BF7647E68E5707B71918C5EC532B0AB64A2470900F4B1DDA643DF6EDDBF0D9197 42 | Time used: 83.0000s 43 | -------------------------------------------------------------------------------- /data/rsa2048.txt: -------------------------------------------------------------------------------- 1 | prime = 85081772695A8A8D67C729447BA36CEEB0FA1187FD0C042A52E1459AF97663BC000E163532BFB2CA6803B777976CE1C3A50AC89A9A733A1E7E9B5A9122AE0992FD2586FAC875D6AA2402A05C51CA94BEBC253260ECC18A2330092C53E1CB5C954739DC3ECE978A9E73DF2B81BFD59DA95B09962A90A021ABAD6A906704AC86B3 2 | Time used: 1328.5300s 3 | prime = 84CEC5E00522D5F9AD152BF4AA44165F3D3538ECC44C65B467DB3D5C325F3D83B4742D081646A362EBA96DCFEAA792668EB48BA49B27F04D30C7D770A244969EB2A554F56059BFFC6738195B7901FE7F4B0F81842DE08D59757424ABF84BC98544185BEB3DCC0EA76AC10ED7372FBC2154264BC319F97C2D0F0380DFD25FB179 4 | Time used: 903.2400s 5 | prime = 971BE038F05FA400C9FA8785EBDAFEC24575DEAC66D8F975F0082ADDA770F7490E3FD33147E093D069112A5331F95ECC9783561D03DCE5191F620C2D807FFC51DDC07E00997F09BF32EDA2469B961E94455F6A4D2C256FCF5F77D7FDB1AA31D0E1A63ED39A15EB74D6293EB121BC25B7635F47AA7BB0734BB7B68E8B380F8C09 6 | Time used: 135.5700s 7 | prime = CD80F5807E0188674714CC9A2B3DF7C683DD49E89886976D27F8FA0EC24F3E5BE9CA18CB6370585D1AC23B8647C5FE1658648FC1F202F016591AA92CAE93F85B7E3A487C5FD9F2F180A926386F4CBA0AACE66452E1CB30E36FB461ED0CC980AA8579444069E04B9F925EE0BEF33AE161147C620925B416ECFA7B1BCE7D7ECA5B 8 | Time used: 1315.3000s 9 | prime = 85547192A8E18E4B3FC5266F613A073E5E6CC580EBA7D46BAAF107964A1B85ADB4061150C9F5C1ADB3E84DECE5B3A292B04EF875262CF94A226CEE96C9EEB041CD4CB8570695A626CDD3E6DE8E153EC7C947159ABC1C2837BB98C61ACDD281018C9013C5DB58E284B33D6EF7D8DE053FA8880E8D51646E14AB79CABAE8C332C7 10 | Time used: 468.7600s 11 | prime = C0B6219565B9943C91EF3CB3B0A823DCD9EA296AA46869D346BE443D6C97CD54A5E240E4608B07422085A7576D30B732D48CF4FD34AEEE38B077BA18D8CF44394D1C30F154C991417BC93D75D1D37B5F16DE82C7017E2B076B255EB626D5CA4FB3B6FC1F921C0C60259B65A3944E9AAE3B90A39A6E807DE3ED33F64194AAF713 12 | Time used: 731.8200s 13 | prime = C66E149EBC6082C6806F9FE13E37EE163CDA0838D52F311F76930027B08F15E041588559D65F3E010BB00263AA147D860A8614DE7C82BCB9FF63981470571DEED7C9B91CA7EB66BA6492ADE0857C0F84231C05359AEEF64D417C3E45008FB233C471D688AB9932D955E531180D392C5A28ABF3814C3DEEED289D51FD54657DE1 14 | Time used: 1386.6900s 15 | prime = 80D3A98B2F22A8C2A0CC70DBADB55220533ED162C45A9710BA3E3843F20CEC394C795C4AE5E217C39ED23DF43513EEDC14442C9A431472EA08E24A764B5BE71580996D59E720D14ADDFD398E25154F1A4C3E9092AC6AA8A466BEC903C763438EA3FF9EC4754E4E109ED4C8DE6A8A324E33380EB1579F21F3C4ECB4A9A819AFB5 16 | Time used: 1335.8200s 17 | prime = FAF34DEA921E7963BE145FCD8779F384EE026DF1954687A2CFB09A8E270511F0EE42989B32138601010DEC0FCC4FC526BD25EDF75F0FD7FB5E73A38E13AE42418C82D3B88FE5C6C2DB89F1793B28141A668091A1EAD9CC5DF3DC0083D9132EF4769BCB451E7FBFD7810DF9B5732FC3D68D45E57F190C81819F3C9273F75B0DA9 18 | Time used: 1492.6300s 19 | prime = BC166B6FFE65DE9B68B375EBD4F506E0824B2A20EE46474E7AEA563A7D75B957BC629074176EBFED4CCD3A104B638310D2C10BDC552D19307BFC6ECAFA598CACB80B6D2E87C2EE8EC27989FFBCED7A34123D8D4378ACB93247915531CF355237870990DAAFB687499CD468E3B70A3EE99210207D85AC7987438839C7A60A2A87 20 | Time used: 359.4200s 21 | prime = B0CED683699A340F69A7965211639311CE88AE4E46435CBCAB71B17FB030809127EF58C1B8F922FB858A310E1D8BC524BC6F3CC6B32C963D9CE80BC64B7879870EB53D4B25CF86D2649F87F8B005A7F25E56E13A1092E44A0BAA7643ACB39B4E9FE053EE4DEBF9E32B249252644C28DA3CD681759DCA6EF022A0B1201F936A3D 22 | Time used: 595.0400s 23 | prime = DCF15B971E8A14E750A1D437CFF1CF772AF46EAE7C32F5ED743F4F33230E28A5048E62A54A8823F7D3301F71C9CDAB5ED8B04B12B0AD62A563105523FFFA20D8A7E0B94BB0C3C31E794E1AEBB16A604A2A8E24AE8218CA0F958AF4040A881BDA0C6B247A9A6792B5025E3877C59048FF8FA8F224794E20335ABF24182344CA0D 24 | Time used: 124.7900s 25 | prime = 9AB9925683581A5AFE266F50CD1CCCCD578DD0E13400AA66101656ABCDF7E622F73DF6C336958AAFB4B9A450C09C9C190BB013E80032FCC18E855FCFD7D9645E6B54EE2218D8473F979B3FD3B04D1DEB8880482E66EC07C2C69CCB5CD60013AB4F4DBC27B1C7B73C1A42C51D20A44B02EDFC2913CF6473E52410CF703E03C47B 26 | Time used: 148.4400s 27 | prime = EFC0A328F34B6A33C2B02545539EA6EB8CCBD2DB589365ADA75EA0190C62C299C76DEFD0EB5F0A5E3C5CFF0098437B198EDD484B1FDCC9E338BD8DE60FDCC743B742D48F42437BA4E415DFA9E095373A2AAF2A1EB683E03B39A7DD80133425D6AD71CA2DD5D4B3CE6F551E7DA9761B6E96C508ADCF6B33519054A6BC8A542D7F 28 | Time used: 452.8900s 29 | prime = B340D5CA73D37E4FAE240C68CDAA27C883A9B8442E855F87CDEAAFE543B884B7AD3BC7379A1249F2521BEFAD9F3D55DC50E92713AAB2BEBDEDA50C86129384C4F9419F4B8E74FB7154253A541D072256A539A7B16C7600166C3262F885B11ADBBFFEAA19BAB7D9D0FFE272CB5AADCFC4C42A886B8CD896F3D919550D14865859 30 | Time used: 395.0100s 31 | prime = B459E02F8057FC8BEC8A579E5426017D69F522E1166441F842A52FD347096B2F0AE1F587AEEA75E56484E67D8D2A2DF63602F422BDE6E9F1E1011E0450F688B6FF88145308170C0032C5A5E6FC29D1814001F71CEA7A235FBC692FB6E812550403A55869303D2CB89501097C7239B12B5B533AF66374157502C9079424CCEFF1 32 | Time used: 245.3600s 33 | prime = FF725EC96D7AC5DA40681E307FB154E8B263BCA68AE71EE93FBF7DA5F931DA72EFA25EEDF0DD904A2A832A6F078406460E127CA12C79BD7742D8FDA483B7E4904FBE81FBEE84AD95F586003D1D969ABCE192B280776CC8568484883B50838B582510EFC3BD23AAF53F5FC558FDD70AD08D7930C7F96CC853FABB04E4788B12ED 34 | Time used: 3614.3900s 35 | prime = 80ABA198F4C502E0AA8996D455ED45C91524C6414697AEB7ADA2B643D24B7DA36DF4348D49AEAB6D0E86D3DCA6525313EFC40ACC368EB0FE0CCE9159B9778111F87DE99E4A15F61BA7D106026B272A835ABC9C0464F60ECEB6D42E58AF0DC125CAFBBB83E544AC49501E91ADAFE6094348180F2C95284B1D2FAED1E44C0C17AB 36 | Time used: 258.1600s 37 | prime = EE8C423BEE9A3D6D112CBE6D5E76D730EC12534A65CA53E9714DA230F9A6F6B507E8B23344F022BBF3E6B05A58F5FFA3E5682DD41A33757B9D7883A32283ED45EEE7464CE8B1AF1834E27C3E6770F41547B8AB888F7C21DF46BE9191F2A97F217DD3975994D18E5549EF63E38CAAD6763197B8D759E7BB9203649E76F7CCEE0B 38 | Time used: 139.3100s 39 | prime = C0941C605D712BAB0D29707B19C0588AD308742096E095C268F92F5EFAE792FE13FAB47D689C699093CBB845A6AA4B9156940276DC267CFBF258CD1BB7193AE26502C68177629CB07BB5DEB7A346F2FD786F50EF841F3B1D61226EADB01CC0F14894604259CCBEB7C1474954DF800A05B750B18852973F6799D7506BB5F89241 40 | Time used: 361.6300s 41 | -------------------------------------------------------------------------------- /data/rsa512.txt: -------------------------------------------------------------------------------- 1 | prime = 989B08F3AE9E94136C7872BDC7A3D7E358D88111CA1DD7F4C98A0CA21276A863 2 | Time used: 20.6800s 3 | prime = 9876484EA49EBD5FDFDD81A2670F416284B9C3721FD4AE75F9E8942323B979D9 4 | Time used: 11.6400s 5 | prime = 850CA68364564EB4EDC93E9F0A01D621D50F375D93878357FBFE8F89EECB8987 6 | Time used: 41.0000s 7 | prime = 82DF1DCBC405F5BC012463DE37580D8544A45047ADE64FD919361D12C145F5B1 8 | Time used: 10.4700s 9 | prime = C9F9A787BC51ED48C8EF242E60C7B487DDD472EFD2683C647D833497DE7FC123 10 | Time used: 21.9700s 11 | prime = A7FE1D5C970BE2F23EA0B5F1450F63DBCFD0453D788EEFC70589AD5A2301C1A1 12 | Time used: 37.8500s 13 | prime = C0EBB6CEFF12BD18750394DCC6FAB5C85862DECD3A7186DB0DC2E1947EF29167 14 | Time used: 179.2500s 15 | prime = C998A1494CCBFA8A480A86E7046CD563EF1F173413AFCD0102E07096749A9FEB 16 | Time used: 29.7800s 17 | prime = F0672B9B04B958880AB8A2935021B097D8513DEB0885DB86340513065FC5C009 18 | Time used: 128.1300s 19 | prime = 9E4EF36E28E409D3F6A8B6F60D376FA86A2A449A0EB193B51C2B7E3DA627F407 20 | Time used: 75.0000s 21 | prime = FB4A28E632CD4CFDAC29CEB6EC0CCD809045C129E2018CB77EEBC420C50CB84D 22 | Time used: 43.8800s 23 | prime = E90658B13CDD57CB6ADC972D1039DF0608B098B44EF549FFBC356B2BCF7A5B01 24 | Time used: 10.7600s 25 | prime = B6F6E60000E55B3FBC7B111B0F6A18C19D7AAE27586EB7D068E6DADB3A189DAD 26 | Time used: 4.2600s 27 | prime = D0219CEC6105194618A8351B173616891AE0308148E177BAE29EC4793872DC03 28 | Time used: 9.5200s 29 | prime = A0199559C3EFCAD3C9F0186B344F7BBC222B9158E2B576215832E9AA9DA6E35B 30 | Time used: 43.9400s 31 | prime = BC8E409C5284C027B5BE0FD9B6939771B2643773F86569B9A04C694F41F9EAFF 32 | Time used: 114.1900s 33 | prime = DF378452203224B1747513FD7491FE0313067C1CD44800DE713762450C887807 34 | Time used: 34.1900s 35 | prime = D1E052030E677D5FD301A1231061D4D7EADACE79493B2E3B26ABAD9CF5BC61A5 36 | Time used: 68.6900s 37 | prime = D0AEA5D48AD2755F4AAC85EB4AEC4611765808DF5EEB373E4B72BD0106D9D4E7 38 | Time used: 10.9300s 39 | prime = EA1F657B719F7598685868BB2B4959450AFA78B2AA35FA240130B19F96214B75 40 | Time used: 50.4900s 41 | prime = F6A40AAD79E7E4F5C4EC202573FE676B1D5B054C72D1B9DEF92D937EBEF3D761 42 | Time used: 20.1600s 43 | prime = F09978F0AC0106F2CD61C30F323E593F6D2EEC13E4EC04036FEFDF60DCFB8D81 44 | Time used: 39.5200s 45 | prime = EDA58A318018A1DDFFE050F3A346FE840317BBC07663B74B5A20C57A49907449 46 | Time used: 56.3600s 47 | prime = E091027801376736205D26B0CDAA0172389F4F5F6A6EBFF4C96DD2F4FF516C2B 48 | Time used: 19.0300s 49 | -------------------------------------------------------------------------------- /data/rsa768.txt: -------------------------------------------------------------------------------- 1 | prime = C97A7D4FD3E3FB0C00EE18273A9473DECFE183543413D3B1C292C65C3575317290A786C286ABB5BC9ED2884BFE9BB2A7 2 | Time used: 277.0600s 3 | prime = 86C4A2D087494B33925437303133A88DBCFB0703CF176B7ECB5B584E2421E50E6763776DCDF501C8535762716B1B275D 4 | Time used: 291.3000s 5 | prime = CB1029FC90D61F47512BFF04816DCEFFC46B071DBAA727E334B48D7A02A511E334B932C7EBCA7A7FF52293C474624D9B 6 | Time used: 46.0400s 7 | prime = E98F735A427C4A73E50AEED9F9CBC974C2BAB0FC53ABF0F437BC807558FAB447FD1EF37C21E1B2F0F21D353DA4E5F2BB 8 | Time used: 38.2100s 9 | prime = D7FF8E07D36F9A34204BCA53E4765B8BC4E428ABDAAD1333E8FD8C20C950556C00CA35A6CCA2237C63C528FFC051AA37 10 | Time used: 100.6900s 11 | prime = CD2B8923FCC752419C6F4C9CD140741036AD53AA04CD62688BA0121C4ACE83279F314FF7CF8A3E8C8239F92BBD02F525 12 | Time used: 53.6600s 13 | prime = DE698C70EFC6A2F47B5309476483A60F1B6BB8D38176D74D466858D368D6DF63CF8E98AF3036AA816B8B9373DC704EA7 14 | Time used: 22.3100s 15 | prime = EB5BC562DFAD5E8EB101CA4EC094E63CF63546502F236A7E33642C9A7EB6A3572997A71463CC230490A94FC14BA9AEB1 16 | Time used: 160.8200s 17 | prime = 82EDF7651BF70314433DC67F9E5C427F9AE17D37A9729E579B1F77D31E64F7AA78F5E419E64F9D3F0477A967E6E65647 18 | Time used: 950.4800s 19 | prime = E5338946DDC27CFF101112C63D095540C97D721CFEEFAC3D0D82F60B30FE1D7BEEF4861BA5FBE36B2709A3EC83F8B0E3 20 | Time used: 32.9300s 21 | prime = E2446250CB01D176E2F90FA82A5F824EC514C41FE5E92C404DF8B155899076EECFB039806D29B0E6424C48F41AA77159 22 | Time used: 181.3100s 23 | prime = BD675BF3089CEADFC2B56454E3A77CAD6BEB7ABE822566C3DA9A5591EA8B68D1592DA7ABA1A9444A77FA3AADCB46ACCF 24 | Time used: 159.3600s 25 | prime = D0DA59FCEB9815E4F370A72CD2BAFF196FC878BE3A13DF31E344E34BC40F7B4667405ED27F913325C8BB32003117E10D 26 | Time used: 57.4700s 27 | prime = BB8F4EF60F715287926886D4F12DC40DC6219E997D62379643755AB8B1E6E177226400E7F0CF40D5DCA2A9DC87E8B6CD 28 | Time used: 334.4800s 29 | prime = A6ED75BB362F38ADE003E091888050C600885007A119F4C8E4766D71916A7B32900BECAEAD76777BF1CCF7582B91015F 30 | Time used: 59.7800s 31 | prime = E15ABD15CB2AAC8137FAC6B0428A0541ECB8AA7845A7337D695DE89EC26ABDCB140ADF3F2D0A4E5FEAB09B33CF8F25D3 32 | Time used: 88.4300s 33 | prime = B3D5CB9AC3E3247F7C01C7BE054A977DB0036615E61B077C516DBE52216BE7C5E97D9DD41B234EEEE514A61E7EA90447 34 | Time used: 30.8900s 35 | prime = C9B74E0704BFD029327F36138CC6B41E2B69ED972EB5AB6273DA03D69CB3B1ECABFEAE9748C732480818813B26B92F85 36 | Time used: 384.9700s 37 | prime = DA6649AAE23D16806453B1AF02CDEB7D1D86CA856F9D212F156A5354AE89BE500F83157C8167C356D4893288E68F1A35 38 | Time used: 70.4800s 39 | prime = E52BF12E4B3BF9C3A43DD8D3799A836C9F261ABA3AAEF801F2A55C8512B5BB73D2F2D3CB8EF009C3EBAAF48F8220CF73 40 | Time used: 170.9300s 41 | prime = EB60DCB0380CDDC9F31522528B2DF1775FC39B796F492C5029825C52955B4DC27E6B60739D832E42533602BE9E86A74F 42 | Time used: 16.5900s 43 | prime = C2EF3FED4BAF2DDA2799CE3ECDCF3D80F26AE9ADFF3F81C2D048C79511F1F20A216C33DE13CA08E69E4C8E4CBD502E53 44 | Time used: 50.6200s 45 | prime = F98177A4A942B1CCF0D3179939BE8419BCB94F51C7611011E4469BE4B53F17F0B866E59B2F069E11B2393E52C6817B3D 46 | Time used: 112.3600s 47 | -------------------------------------------------------------------------------- /include: -------------------------------------------------------------------------------- 1 | src/include -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "BigInt.h" 6 | #include "StringTrans.h" 7 | #include "RSA.h" 8 | #include "OAEP.h" 9 | using namespace std; 10 | 11 | int main(int argc, char **argv) { 12 | if (argc != 2) { 13 | printf("Usage: SimpleRSA [KeyLength|fastTest]\n"); 14 | exit(EXIT_FAILURE); 15 | } 16 | 17 | int keyLength; 18 | if (string(argv[1]) != "fast") { 19 | keyLength = atoi(argv[1]); 20 | 21 | if (keyLength < 256) { 22 | fprintf(stderr, "KeyLength must bigger than 256\n"); 23 | exit(EXIT_FAILURE); 24 | } 25 | 26 | switch (keyLength) { 27 | case 512: 28 | case 768: 29 | case 1024: 30 | case 2048: 31 | break; 32 | default: 33 | fprintf(stderr, "KeyLength must be 512, 768, 1024, 2048\n"); 34 | exit(EXIT_FAILURE); 35 | } 36 | } 37 | else if (string(argv[1]) == "fast") { 38 | keyLength = -1; 39 | } 40 | else { 41 | fprintf(stderr, "Invalid Argument %s\n", argv[1]); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | cout << "Please input your message:\n"; 46 | 47 | string msg; 48 | getline(cin, msg); 49 | 50 | RSA *rsa; 51 | if (keyLength != -1) { 52 | rsa = new RSA(keyLength); 53 | } 54 | else { 55 | BigInt strN("838BB8FFAFF51B40E52DF0DB1F0C3466EE14C46A37C973BBD1718A15023F55EA683D0A6B93F3DD0155E9658B6A413D6715E7B8C1E85BC4167CB9914F5E2137C9", 16); 56 | BigInt strE("ACC86137DDC424D1C24331E10BF9239A49001F34B16BE4B80E39F8D00CD6FA99", 16); 57 | BigInt strD("39E75F3757C1A40A87493AA67EDB38B7BD31954FF184BD24698A66309CED1B7A0C423D0799D42B96815D7A8009EC5F4CB66628E9657004995FDFB5865B10C3F9", 16); 58 | rsa = new RSA(strN, strE, strD); 59 | } 60 | BigInt N, E; 61 | rsa->getPublicKey(N, E); 62 | 63 | StringTrans st(msg, N.GetBitLength() - 17); 64 | cout << "Input Message: " << endl; 65 | cout << st.toString() << endl; 66 | 67 | OAEP oaep(16, N.GetBitLength() - 17); 68 | 69 | oaep.encode(st); 70 | cout << "OAEP Encoded Message: " << endl; 71 | cout << st.toHexString() << endl; 72 | 73 | RSA::encrypt(st, N, E); 74 | cout << "Encrypted Message: " << endl; 75 | cout << st.toHexString() << endl; 76 | 77 | rsa->decrypt(st); 78 | cout << "Decryped Message: " << endl; 79 | cout << st.toHexString() << endl; 80 | 81 | oaep.decode(st); 82 | cout << "Decoded Message: " << endl; 83 | cout << st.toString() << endl; 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /sample.txt: -------------------------------------------------------------------------------- 1 | ********密钥生成(RSA-2048)******** 2 | 3 | 公钥e: 4 | E1E08B7AE438538EF05906AF00D3D41FAE414E03DAF3CFE7A87CF886A492C462965F7AF86921D6B9E7E2327311E8503B4FED7EB0C4C95C6115D8FAA0B46030465E599D1CC7BBD45A3DB2FDEAA66DBC1A50E4231C9520AB3F5413E2AC1F458FB106FD6F2832DFCB2AB7DC52EBD008BB133E56DE4DCE76E9FA010762948570D0BF 5 | 6 | 公钥n: 7 | 62CE67BBD3F5800346A4DF1A2FA8BB701FB1B0F43B0B91F8862427A06AB931926AF1F8A61F20ABF4E28732EAEBEAE8D6FB6764B896EA6F0863838BD02481E314E8B1E48A9D44D6E705DAE19767D89351C6D29C6333E4B7419ADEB4DBCD2DE906ED3093E65FC436C78E100111D792E695C121C534C1D50C724EAA4E8C6BBB27E7904E0AEFF83E2A83E4C08E2C4A7A2121521E2A3EE098CB1671B54648AE4EBA475EEEA9C07BCD8F29A2155B7DD187786D69768C1A9E17C7F66BCDA3DDE91B610149D2AC30B524C8B4C5704B920CAE5DE12946B11366608BC83D339C941594B77E1733866BCF325B40A15551DDE5F763E59CA099D5F90FDE871C87C39A2D6F1A95 8 | 9 | 私钥d: 10 | 2A839B59FF98AC84BE604DA076F1EB63DCF529613D6F2F5DAB00B3A4E8761AFB3D982466F3767ED18D61FD8EAF484A043AF19CF5CA9A74C3D6106316E7B323798121BEB4E29FB1EABDF2787F9477C2B63D3DAE740E0ED2EDB54F33284E31637A62CF6DC0E52D6C4F2CE47A92078405401395A52FD60DF2C8AD8F59817C9DD1B760C17FF088D1C771C94B869A7899F921A50C7E73C9152BA32AB781C783DB0C6C879FECFAEAF78286A4ACA7491E84C5D25D7FB9D9DE34FCE97037E7112A423E9A16086888FAA61A194574FE055CCE59C970C16A57FA1CB2924596344C0D4A3CDA1D34CFCE9663DF64D2F478526563B0E3BD914F094FEFC3419D6AB05646B99CFF 11 | 12 | p = 89E9A03256BA0BEF13B1E90FF3FC58550105E101036BB97C60F32FAC10A5C779E9BF2AF026601106F8942D08F91AFEE1019C4AA9C4BBAF82C4EFF8B560FA84C077EA2B18EE6151751931038BAF8FBF092B02B73C476E694DDDF12D2E36BA857136E4E0144849BA20CCA694AC9BF30ECA71C7D39701625804A3FA7BC8CCD2DF3D 13 | q = B768B0EA288526B6F9DA772E5CAB441DCFF011FED077FA9DDF9CBFBBA7D3702EA66D9C8DCA85D7F93D42415261F5C8722BCF80341C360C2D2C49D7B0CDA7A89BB3ADFFA7E138D3A745A7D0E07E729EF832006BB2E6DC6DC7DDC2D39D22729A0493BA97408DADB6E3D110F932749B722EFFCB5EA2727EBBE75A751A0E4EBF5E39 14 | 15 | 16 | ********密钥生成(RSA-2048)******** 17 | 18 | 公钥e: 19 | AFE49CA5FB4783888C6D0138DB2EA960D98F2EB05C9CB054280FB20E8175D762703B897887DD5482116F6DB62F2E71E27B009BB2A5E024324D12614353FE04A66100EE11FDDD5839D5B2CDA8E4D28772A6A56B72D5E6BBCED714A762B831256AC6004584F4881215565D4362A0C46205E6C39DC496E529D290550F4288286C4D 20 | 21 | 公钥n: 22 | 8188452C61805FF764FAB7845C74313EBC0990BBD04AC8AEA9BEBC8795F25ABA76ECF66E35AC4797FC03463690E1905F07B6CC3CEA140E9425073DDADE31B4E5797625942A7C68B51C0B8C28A0B97CD2A391C9B7A42F6A17C8F9CB821169847E1D38F55197D4114945712C932532DC407576D2ACA6B15CC18D5BAA7F5F940D556AD93F401F981979CFE8C2B38995C4CFBC64F02AEE290E886B4BDD3EBD57F370F8D98C8BAEDB60F0678A31A94C5C287FF420E1C4DC09EB86AEF09A88BE187982BB40853E5FAB6B04F30E9E23D48AB3A7CFE49EAB5D302CA37433D42FA6B908A9ED4D8173B163A500B3513366B38BC9FD3956051EC526F9557CE7BC1E2271EDC9 23 | 24 | 私钥d: 25 | DF12B46D4CACED60D2E39234432A72743CD8C3BA8E5DE1AA2F7545B468FA1507D8510ADCC143C8381B4C653CCA9F9F4EB886C3975697AFB344563F47291F3338EEB7DBCBF778423D30733C68B84EDC316D7427B989E76D17BD21CD33715F00B5C45C94E4020330A729231C9126F8C2A1F8BE9CF0CE03B098D494278E4A637D3ED3A5485434577875E05B699963DC21D117782C8ACC940644E90EEC214AABC5E69F006937A481295DC2134C78D6D73F8493D387F5A2C97B93E377FCC13E4890C8028337F1C3780C50E7FBF2A32EA9A03297EF77D2B15BF20B5DE48E0261A9CF7D982A1841225B1B78755E1BFC416C9881BEA9A74970BD08324478939F95FE985 26 | 27 | ********密钥生成(RSA-2048)******** 28 | 29 | 公钥e: 30 | 84CDC278F173E4C139AC9BA1F5B2992C47F79DD85951DB5F9A164C34DEFADCB0500BEBA5AE4DD477599F244DAD308AADFDA45146CE529341971CB1A4112AB07B6C77C8E39022EAAEF3D15459D0E860D734B69EE3E2046DFE5298D9C6FC972660D3FFBCE641319561BA45EC54BEC1B2524927776BDFD46EE229BBE596E7C74DED 31 | 32 | 公钥n: 33 | CAA886066B57007F931C999162224D36546EAEBAF72DE6A6BF07E091ED43885A096492CF0A911D0019F3903CF09503DDC55C03C138205A425D8A52278A1BA56A6123E410A32C2468C7CB8F79022968013F8E4BABFC655D1B216D1192762B1D6591CEA6C47B8DBE65F771DC4460E854A287C8FE36F1121BFBF998B84D928C37C47A0F161C74F428A23F0B01BD15CB6D545EFDB7A7475473221D9B6BA697CA6D16642D3FCF727D68C1B32940600B0FCD87A71A003E436A29EE4DFB673546472E7DF72BF909D0A1A2E8270A8663C045D4DB1247E7A189AB6802E6D91EEF2A5A894EACA0337DB6AA8DAF5A6766D0C259DDF6338D8AB856CB6933E187745BE43C5CCB 34 | 35 | 私钥d: 36 | 1BCF757D631F0DB87401BF6141756A11666D738C62CC033B1E5E41822DB1CB7F5DD666650F77EB61217DEBE5BE7CF0F86CFFFEC8EC3A37C9F4AA1310299515E2B5A27D2D1296533FBB2B08E97502CA3D7D12611ACEF6B57BB2B61BAAF81257C175ED8B2AF8F346C55D9734C48863DDD4D027100B037912B79E9992B4BF13C6DA5DF1C1B55FF7637899B23F6786ED2E560FB117B61910B7DC930A1A3181E523D9DE7659A34B3C978F52638F071E2293C24FE70D9B3C2030E5FBBD604CAD3F8040C672024B63E6D9811EE1433E94C55CCA1DB9AAA9875726E998178B2092DCE24E6728C7244E2EB6FF5ACF0EC6663429ED0FBBF95AA392FA7AA75060CB23367E25 37 | 38 | Generating test message... 39 | test message: BE22855AD206A47D29BD1CE6455870F3AB8C6EB593B6BF462B28D16677F5DE8C408AB25CE4B556E4705D5C85A3FABAFD44EC504AC7383AF89158808C1EF890B073D8B40B3CE14F5F4AEF4B41BAC1063B1A8D98405DF2A98868F4FAD9AC379E712DA0F9BF2132B1D4759EEC2D31D5F03A074067E6C60A0E0E23FB36B17FEF7D9E794A31ECC8A256E9D2AC913CF9ECC68C3995345CA031F5F3F4146FA13F8C08403A9D21FC8BF9E17A9987FA7984509056FC43B76253139B302F231771E341A17871C6E8060C6457D31BF93F3A8F5CEDC0FA159A8ECC005AEE114BDA8BF90FB88C4E9556142FD445274A37ABFCA1246436609AB0EB476AFCBA9B4B5B529D7A1A5D 40 | after encrypt: 40669CFDF5CA082D94751C2A734837AEACA0804938ACB0C39547A4A877A3D7571B1AA5D3712EE2346EA270B47F45D5531C7761A147F71DC97264B66595DF04B6B044CDE1CE7E13B270CAF0705E651C21D8E34EB00C2EB6CEF65F776FBF90B31DD647E085B04ABE11C506C276411A4C955DF06FD6037A44AD86738DE38A360B38F5FDA07E2C8712696D93B162D09ADC5CD5515BCE7E3251A9EC839B04F8DE10281A73558DF007656DEFD6F9D12C8CF20271629B56B4A8F22DE9AFF92CE6CEA0EA49560F20C07A72C03EAF1F461A1FCC992704CAAC13C700C9053EC0068D4099C10B3C41B1E8B3BF57233BF8DC790EEF0C06BF58F586F395264228DDD84E5C559A 41 | after decrypt: BE22855AD206A47D29BD1CE6455870F3AB8C6EB593B6BF462B28D16677F5DE8C408AB25CE4B556E4705D5C85A3FABAFD44EC504AC7383AF89158808C1EF890B073D8B40B3CE14F5F4AEF4B41BAC1063B1A8D98405DF2A98868F4FAD9AC379E712DA0F9BF2132B1D4759EEC2D31D5F03A074067E6C60A0E0E23FB36B17FEF7D9E794A31ECC8A256E9D2AC913CF9ECC68C3995345CA031F5F3F4146FA13F8C08403A9D21FC8BF9E17A9987FA7984509056FC43B76253139B302F231771E341A17871C6E8060C6457D31BF93F3A8F5CEDC0FA159A8ECC005AEE114BDA8BF90FB88C4E9556142FD445274A37ABFCA1246436609AB0EB476AFCBA9B4B5B529D7A1A5D 42 | 43 | 44 | ********密钥生成(RSA-1024)******** 45 | 46 | 公钥e: 47 | 92534F70144A397F8E319CB3A7B0A0B1B147D71624905496563AC09EB34416599472F9B0752513DA8AFB9F616E7A42409E0EBDEF64CFF67FE15945D9C9FEFDFB 48 | 49 | 公钥n: 50 | D9AA0B3879C08D517DA6D06964FB75160D640107B3D840F0A7A9DF63481E22D1078DA38A26E463DCD0D8F1A8C553FEE005EDD3637B34FF9E444B7A3F9011CB7850BB8D368907DCA712F4627C7E61A94BA934AB3191FCA08366D738E2E853C041AE3C03C7C46C9F5B92A4F896629EA6CA1AE0C3BE7978C605155F08DDF7594CD3 51 | 52 | 私钥d: 53 | 348B8B35B82D3A61C1147B3A57432D40EED96ABEF892EB141C638D04EB14CF15C746F906C4F536E350DA233B46BF4232E2E190BFCF5BC7E2E2B3DA8726F992E251493A799549D90CDD6179E4CCF06E933A596FE71AC165D3500D91D6F7C158F152244630497ED73A3FDEF1AED92531C37D39DCB551B1296975D973B41B4CF723 54 | 55 | Generating test message... 56 | test message: A68FD91F645A45B4DB2F78E23ED178FFFD0CF69F0193F83FDE14A1360B1D10C89762EFE69E5869F2C9BEBE52666DD6A81FF53948414992579F318271AB910756E837631A10705F3A630735D9F5D8A90073E038966EC571D9D387D9B80804F51A5D92CC93F225B02C820CA0EBB4C73E5F4670F56858424900835D2288CC17F9A2 57 | after encrypt: 9FF84C3BDB7988A962FD348750E944FD590AB3F8B1E289EA481ABF2BAB7B1D7FCD547D1D8A3D8F9BE03B0628183E33417C7C288131E60FDE24E4F6D9B85301ED2438028E0213FDCEA8DB2803C1680A82D59B70E4C6256D1A402CDDD4E067AB8103359DC968A6D50955AFDF2719552B7D51C03B3048ACE41A9BABFA3D395ACF8D 58 | after decrypt: A68FD91F645A45B4DB2F78E23ED178FFFD0CF69F0193F83FDE14A1360B1D10C89762EFE69E5869F2C9BEBE52666DD6A81FF53948414992579F318271AB910756E837631A10705F3A630735D9F5D8A90073E038966EC571D9D387D9B80804F51A5D92CC93F225B02C820CA0EBB4C73E5F4670F56858424900835D2288CC17F9A2 59 | 60 | 61 | ********密钥生成(RSA-768)******** 62 | 63 | 公钥e: 64 | F8AE063CD67047F44EE5BB23A9FE26534C12A84342809FC5B6FB8FAED7C31BA0D3F2A250E84324E2DF34156466719C2B 65 | 66 | 公钥n: 67 | AB7AFFB2F11A14E76757ECEB2B879DF87E714919480FB9A3EE3734A5C69D7A4E4C60B674A4B5FBB4CF2B9DAE20579158838766E643875A6F08BCB2EFE806BA98A0492252BD9AA48FCDA4247CBFF3B96C62AF981396A3F1B61ED9316C2A1E4553 68 | 69 | 私钥d: 70 | 29A294DC7D66B5F36BBA0294065F5A0E6390F53EC95C89B19054CEBE4322B73DBB3A9F39468B34A1C157138C9101520F08BD795FC3ED87A25FE408754CC8FF60087C819DAFD91BC6D4CDBA0CCA1D1D7E3045EA6D1A0E1FBD1285F4396F123353 71 | 72 | Generating test message... 73 | test message: 8A2D3C7A01B5E00B42FD513DC2FA06CC44176B973E8F85CE02374A49396D024DE19F8EF07D195FD4CE4E938F67810281A543835C6DB850E7F30199E53DDCFF132402E43BD9BCA55917904E4486288861C89D12D7DF9ED36499547D5A5B964235 74 | after encrypt: 720D6FD7DFB0E1B71115B23301FD89546DFF124E33ED9B3F84ED4E0FB3374A89801C5BFB37E9FEAB749C723454B32A6ECE481CF5C26C7169980C6565A2F06EE6680F459029C514C011FA90A6E2B4D0CC9EAB37C41CDAF104C4A6A41DCA9F6FC6 75 | after decrypt: 8A2D3C7A01B5E00B42FD513DC2FA06CC44176B973E8F85CE02374A49396D024DE19F8EF07D195FD4CE4E938F67810281A543835C6DB850E7F30199E53DDCFF132402E43BD9BCA55917904E4486288861C89D12D7DF9ED36499547D5A5B964235 76 | 77 | 78 | ********密钥生成(RSA-512)******** 79 | 80 | 公钥e: 81 | BBE574A3028D32FF6CC64BDBBF22C9A9F818D25DABD52F1205D57884C3124743 82 | 83 | 公钥n: 84 | F08D035BB07A47CCFFE0D0CB65B69E9DBDFBC1D22248610ABB9FFF9608F9B7A8C8374A008605C7F25C920620C811655D1DFB878A1FA746E37041241EB75B22F7 85 | 86 | 私钥d: 87 | 18AA5C3A538525EB44E0B4213A016FDB0ABACA879661B5C6C13AC6684FAB5DEE10D5C5AF720C6BFD6C6B4AF7FCB9C6BF9283BAB84861738C1DA4A92565F6DADB 88 | 89 | Generating test message... 90 | test message: ECC2DF7C2771214EF9AFA865682B8CA5FA4181809CFD3304FDB000E4E32F8954CC51C4681F86EB08FF25ACDCDC7BBCB60DFC651D25B099AB275713AFB920E56B 91 | after encrypt: 2469E877097FC1C21745CA8BEAE30EFF4FF005A98DD294377A07EC73B8159A42B6CC48A6E9F05C2F78FF035C56EFF3A14099372600CEA3781E129F200C67AB2E 92 | after decrypt: ECC2DF7C2771214EF9AFA865682B8CA5FA4181809CFD3304FDB000E4E32F8954CC51C4681F86EB08FF25ACDCDC7BBCB60DFC651D25B099AB275713AFB920E56B 93 | 94 | 95 | ------------OAEP_SAMPLE(m = 512, k = 256)--------------- 96 | the msg is: E9166E8AE41980401511773929693BCD98B191F755E92373F0F46266721CE2668A246673DEDF9A7F9727696B248779931DD1D490F4F6DD37375E195A608FE1B7 97 | the encode random number is A7735FBC984975CF97CF232163F831FB210186324D51E474CD33006C81602C28 98 | encoded msg: 2CB4045DF46826CAF064B5076BC6E560594F6A2B238864D486D6622E8C5CD5A9170AACE7A918B6C51A62778BFA2F693A02D156813039811B73B0E681E05005AF533067D4E6C627AF3B02CA27553B0CA801748557E89F94A89924C3042E2EE77E 99 | the decode random number is A7735FBC984975CF97CF232163F831FB210186324D51E474CD33006C81602C28 100 | decoded msg: E9166E8AE41980401511773929693BCD98B191F755E92373F0F46266721CE2668A246673DEDF9A7F9727696B248779931DD1D490F4F6DD37375E195A608FE1B7 101 | 102 | ------------OAEP_SAMPLE(m = 256, k = 128)--------------- 103 | the msg is: CCEF5DDA2944FAAF02B1EA16D2472618D08A23884AB589358FB98EC16C3050B0 104 | the encode random number is 8F02ED85428DCE2626CB35FEA452F8DE 105 | encoded msg: 3913EB23AA4D8E94C63C334215DB8973558B870B74CECCD792009D94F001F8FA4A3573F282EB508DCD6467E1C9764B36 106 | the decode random number is 8F02ED85428DCE2626CB35FEA452F8DE 107 | decoded msg: CCEF5DDA2944FAAF02B1EA16D2472618D08A23884AB589358FB98EC16C3050B0 108 | 109 | ------------OAEP_SAMPLE(m = 768, k = 256)--------------- 110 | the msg is: 857DF0DFE7DB33FB119B8DE6A55FDBBCB14AB7C01549FF5904E09A09C7F63B7F9F486932DC850B695E89CCDAF3196A01D9280543B201445B7C3C0BB8B2C35AA74F5A6D68092D3EE8AEEBD3A59F479375516E6165B274CE7C807E943A9C653028 111 | the encode random number is A4863C8F772C197D4BF70ECD26BDAC4C8EB1C1F52D75F8474BAAA85453BF69C7 112 | encoded msg: 4279D82A421322529CC186909E76EC3445943699DCEF50DC89D3AA6E5ADC75FA60B796CD237AF496A17633250CE695FE26D7FABC4DFEBBA483C3F4474D3CA558D32786ED2436C9C397B929E17D2CF74ED4FEDE36A9586641B918F3F6AD0FE8953AEDA80ACCEAAB9CB9A7C4939B2E41E06F028EC08BAFDCAE94D8C6BB09227F8D 113 | the decode random number is A4863C8F772C197D4BF70ECD26BDAC4C8EB1C1F52D75F8474BAAA85453BF69C7 114 | decoded msg: 857DF0DFE7DB33FB119B8DE6A55FDBBCB14AB7C01549FF5904E09A09C7F63B7F9F486932DC850B695E89CCDAF3196A01D9280543B201445B7C3C0BB8B2C35AA74F5A6D68092D3EE8AEEBD3A59F479375516E6165B274CE7C807E943A9C653028 115 | 116 | ------------OAEP_SAMPLE(m = 1024, k = 512)--------------- 117 | the msg is: 8BAF79FC26F5036DA7311CE1833EAD3B8F75804C14378DF433E0FD4C701C16566A9333DFA8450CD35B4A918AF35170A257DD379C96861DEA1928ED7C4869A0D87384E6297146FB15338F158D5DB3DB1D9082EDA21C82098CACF4B806B852A01DA66EB1005D5B75E5158A393E12D3BC469D4A468976BCEAB0921849DFA8C3592D 118 | the encode random number is D42099134B7FFC1489D688CE06FB5E5EAF24D6A2D12EF68159C868652B1B913594C3834F9A2035276E976EABB9B84FC6B554677343EC3FCA10135F8C671A8A7B 119 | encoded msg: 1390681E54A0548AA9AA139587933950BAB2E48F75FCD6F5A290B2F5BDF108708DEE31AABB852AE91050DAB8227EFA268E45723EEBCE376606CA878BF27AAC8A3F9B6ED8486C50E6B4C292375FE511280A615FC3AC67A40C644C9FDA5EA42F0ED5D0303AD4BB66F830071CA77A447904F18664584818FFF69DE97CA475CADF04754C122D5836009C959A1F707835F9EDEFE85FF683C9A3EDEDC3F06DE55B9A42D77327AFB6EABCB0CF10CAD11B6D512DC5B6AFB1F9D3FC7EEB6EE37EB0DAC3B3 120 | the decode random number is D42099134B7FFC1489D688CE06FB5E5EAF24D6A2D12EF68159C868652B1B913594C3834F9A2035276E976EABB9B84FC6B554677343EC3FCA10135F8C671A8A7B 121 | decoded msg: 8BAF79FC26F5036DA7311CE1833EAD3B8F75804C14378DF433E0FD4C701C16566A9333DFA8450CD35B4A918AF35170A257DD379C96861DEA1928ED7C4869A0D87384E6297146FB15338F158D5DB3DB1D9082EDA21C82098CACF4B806B852A01DA66EB1005D5B75E5158A393E12D3BC469D4A468976BCEAB0921849DFA8C3592D 122 | 123 | 124 | -------------------example_demo--------------------- 125 | Please input the origin massage: 126 | Hello world!!! 127 | Please choose the RSA model(512, 768, 1024): 128 | 512 129 | string to BigInt = 48656C6C6F20776F726C642100002121 130 | BigInt to string: Hello world!!! 131 | the encode random number is 719 132 | encoded msg: 5EE0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002432B63637903BB7B9363210800011EB2D8 133 | --------------------encode----------------------- 134 | 4E6626C0C9A82946FA78CA055AB41167F286B99C20BABA2B02584EE162584B0DCADC768875FF5DC0196F818A221CC2893526328EDF64A06C65E1803D2952EB65 135 | ------------------------------------------------- 136 | the decode random number is 719 137 | decoded msg: 48656C6C6F20776F726C642100002121 138 | BigInt to string: Hello world!!! 139 | --------------------decode----------------------- 140 | Hello world!!! 141 | ------------------------------------------------- 142 | 143 | 144 | -------------------example_demo--------------------- 145 | Please input the origin massage: 146 | I am the king of the world!!! 147 | Please choose the RSA model(512, 768, 1024): 148 | 768 149 | string to BigInt = 4920616D20746865206B696E67206F662074686520776F726C64212100000021 150 | BigInt to string: I am the king of the world!!! 151 | the encode random number is E3A9714754BA8F19 152 | encoded msg: 5E98D0C2CC698508FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB6FCF496FC5CBCD6FCA4B48CC6FC84CEFC5CBCD6FC44846E681870E19CB3D6B532D07EB4CBD6EC07 153 | --------------------encode----------------------- 154 | 8CEAEB2D9C4AC4867720F20BAAF54C0DD873815111C429547FA248178850EC27730BDD2535AAA2B8C60DD1D7D1925F242CCCD15801EDA37A4B70D6110A1F8A99F38EB52E599CB7C35F7786650E136BB6EFD2812BD3856D49EDF4BB79BF3F4B13 155 | ------------------------------------------------- 156 | the decode random number is E3A9714754BA8F19 157 | decoded msg: 4920616D20746865206B696E67206F662074686520776F726C64212100000021 158 | BigInt to string: I am the king of the world!!! 159 | --------------------decode----------------------- 160 | I am the king of the world!!! 161 | ------------------------------------------------- 162 | 163 | 164 | -------------------example_demo--------------------- 165 | Please input the origin massage: 166 | Harry Potter is a series of seven fantasy novels written by the British author J. K. Rowling. 167 | Please choose the RSA model(512, 768, 1024): 168 | 1024 169 | string to BigInt = 486172727920506F74746572206973206120736572696573206F6620736576656E2066616E74617379206E6F76656C73207772697474656E20627920746865204272697469736820617574686F72204A2E204B2E20526F776C696E670000002E 170 | BigInt to string: Harry Potter is a series of seven fantasy novels written by the British author J. K. Rowling. 171 | the encode random number is B1E963B163A9714754BA8F19 172 | encoded msg: 6F58DE90DE98D0C2CC698508FFFFFFFFFDBCF46C6C36FD7C845C5CD46EFCB466FCF6FC64D46CB4D466FC84CEFC64D44CD48EFCCCF48C5CF46436FC8C844CD49C66FC446CB45C5CD48EFCEC36FC5CBCD6FDEC6CB45CB464BEFCF4545CBC846EFDAE8EFDA68D87AA70C268720AD19CB3D6CF39A3C695E86CA50E1F78E4F30B8922 173 | --------------------encode----------------------- 174 | A5B98DED1B7EB3C1381A3AD4A50F1777C5FA0F119BA40D8BAF792FB07DEED5E319AEC48ABDEEDB3F4F5F1483C7AA13F2D958E562A71D0AD55BEC6108045459B806DE3701B0EACFEC99A02E78570EACE0D61FBDD5A231F444022F94DAB1E87E42FA974DF9D1B6D6103E06916E6509458E2B9E1A12C38EE6B20283E5F553D45182 175 | ------------------------------------------------- 176 | the decode random number is B1E963B163A9714754BA8F19 177 | decoded msg: 486172727920506F74746572206973206120736572696573206F6620736576656E2066616E74617379206E6F76656C73207772697474656E20627920746865204272697469736820617574686F72204A2E204B2E20526F776C696E670000002E 178 | BigInt to string: Harry Potter is a series of seven fantasy novels written by the British author J. K. Rowling. 179 | --------------------decode----------------------- 180 | Harry Potter is a series of seven fantasy novels written by the British author J. K. Rowling. 181 | ------------------------------------------------- 182 | 183 | 184 | -------------------example_demo--------------------- 185 | Please input the origin massage: 186 | Hello RSA-2048!!! 187 | Please choose the RSA model(512, 768, 1024, 2048): 188 | 2048 189 | string to BigInt = 48656C6C6F205253412D32303438212100000021 190 | BigInt to string: Hello RSA-2048!!! 191 | the encode random number is D1B7B9826B28FCB5EB4965CD7ECD1D29FE7D13AB14C97F763157FCD9 192 | encoded msg: 4F6D6881D918546CA6C72344D5BB0B18AA2B0E990C472AD210CD5448FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8494BBF1373D5C988AED86BA2B2535A0A7CE1AB63C07A06779955CB50718D8E1C541A740F8CB6C96CD3AE0F13C0F46E285329DFC663B2BCDE6497 193 | --------------------encode----------------------- 194 | B1A07CB0739EF0F833FD6CE76BDFD4FFF2EE850D9C6ABD56AFED50AEED4630C47F09AB56CF6B8B202029675146A090A4DE65DF2A2865CFF9E9F976A16555E0A98CD3BB21212DB96D0DEAC6FC0357FB9FB1A72A98BB2C8ECF68B517A9FB801D63C266915C2D2CDED1515A0520DE73BB48C284C94528E606DA83DE380D73E57A1E21485B4445F68CF9829204D0B816C33DD5AA3E21B88DDCB6DEF71C5155E385C3903EF4A68C06F56B6E6218DEDEF84E3A6FEC28D21F5AACD57EABFDD0F84F4EBB6F83AB94FA50C0E6FF5C7F496CC9EDF9F6F982B8053C887FB5360DD04349BB67B51BAB370B18B6D8E388D10745A57A1874F8EB9D3BED79964BA84F6C1C5BFA3D 195 | ------------------------------------------------- 196 | the decode random number is D1B7B9826B28FCB5EB4965CD7ECD1D29FE7D13AB14C97F763157FCD9 197 | decoded msg: 48656C6C6F205253412D32303438212100000021 198 | BigInt to string: Hello RSA-2048!!! 199 | --------------------decode----------------------- 200 | Hello RSA-2048!!! 201 | ------------------------------------------------- 202 | Time used: 62.9500s 203 | 204 | 205 | -------------------example_demo--------------------- 206 | Please input the origin massage: 207 | Harry Potter is a series of seven fantasy novels written by the British author J. K. Rowling. The books chronicle the adventures of a wizard, Harry Potter, and his friends Ronald Weasley and Hermione Granger, all of whom are students at Hogwarts School of Witchcraft and Wizardry. The main story arc concerns Harry's quest to overcome the Dark wizard Lord Voldemort, whose aims are to become immortal, conquer the wizarding world, subjugate non-magical people, and destroy all those who stand in his way, especially Harry Potter. 208 | Please choose the RSA model(512, 768, 1024): 209 | 512 210 | string to BigInt = 486172727920506F74746572206973206120736572696573206F6620736576656E2066616E74617379206E6F76656C73207772697474656E20627920 211 | BigInt to string: Harry Potter is a series of seven fantasy novels written by 212 | string to BigInt = 746865204272697469736820617574686F72204A2E204B2E20526F776C696E672E2054686520626F6F6B73206368726F6E69636C6520746865206164 213 | BigInt to string: the British author J. K. Rowling. The books chronicle the ad 214 | string to BigInt = 76656E7475726573206F6620612077697A6172642C20486172727920506F747465722C20616E642068697320667269656E647320526F6E616C642057 215 | BigInt to string: ventures of a wizard, Harry Potter, and his friends Ronald W 216 | string to BigInt = 6561736C657920616E64204865726D696F6E65204772616E6765722C20616C6C206F662077686F6D206172652073747564656E747320617420486F67 217 | BigInt to string: easley and Hermione Granger, all of whom are students at Hog 218 | string to BigInt = 7761727473205363686F6F6C206F66205769746368637261667420616E642057697A61726472792E20546865206D61696E2073746F72792061726320 219 | BigInt to string: warts School of Witchcraft and Wizardry. The main story arc 220 | string to BigInt = 636F6E6365726E73204861727279277320717565737420746F206F766572636F6D6520746865204461726B2077697A617264204C6F726420566F6C64 221 | BigInt to string: concerns Harry's quest to overcome the Dark wizard Lord Vold 222 | string to BigInt = 656D6F72742C2077686F73652061696D732061726520746F206265636F6D6520696D6D6F7274616C2C20636F6E71756572207468652077697A617264 223 | BigInt to string: emort, whose aims are to become immortal, conquer the wizard 224 | string to BigInt = 696E6720776F726C642C207375626A7567617465206E6F6E2D6D61676963616C2070656F706C652C20616E642064657374726F7920616C6C2074686F 225 | BigInt to string: ing world, subjugate non-magical people, and destroy all tho 226 | string to BigInt = 73652077686F207374616E6420696E20686973207761792C20657370656369616C6C7920486172727920506F747465720000002E 227 | BigInt to string: se who stand in his way, especially Harry Potter. 228 | the encode random number is 285 229 | encoded msg: 60C002430B9393C902837BA3A32B91034B990309039B2B934B2B99037B31039B2BB32B7103330B73A30B9BC903737BB32B639903BB934BA3A32B710313C51C43 230 | the encode random number is 446 231 | encoded msg: 784003A343290213934BA34B9B41030BABA3437B9102517102597102937BBB634B73397102A3432903137B7B5B99031B43937B734B1B632903A34329031531FE 232 | the encode random number is 338 233 | encoded msg: 45FFFC4CD48C5C546CD466FC84CEFCF6FC44B42CF46CDE9EFDBCF46C6C36FD7C845C5CD46E9EFCF48CDEFCBCB466FCCC6CB4D48CDC66FD6C848CF49CDEF5FC27 234 | the encode random number is 47C 235 | encoded msg: 7A80032B0B9B632BC9030B732102432B936B4B7B7329023B930B733B2B9161030B6361037B3103BB437B69030B9329039BA3AB232B73A399030BA102436599C6 236 | the encode random number is 379 237 | encoded msg: 4A3FFC44F46C5C66FD64E4BC84849EFC84CEFD44B45CE4BCE46CF4CC5EFCF48CDEFD44B42CF46CDC6C368EFD5CBCD6FC94F4B48EFC645C846C36FCF46CEFBDBD 238 | the encode random number is 196 239 | encoded msg: 46FFFCE4848CE4D46C8C66FDBCF46C6C36C466FC7454D4645EFC5C86FC844CD46CE48494D6FC5CBCD6FDDCF46CA6FC44B42CF46CDEFD9C846CDEFD4C8498B457 240 | the encode random number is 5D2 241 | encoded msg: 69C0032B6B7B93A16103BB437B9B29030B4B6B99030B932903A37903132B1B7B6B29034B6B6B7B93A30B6161031B7B738BAB2B9103A3432903BB4BD30B89526A 242 | the encode random number is 447 243 | encoded msg: 785FFCB48CC6FC44846C9CDE9EFC6454ECAC54C4F45CD6FC8C848E9494F4C4B4E4F49EFC7CD4847C9CD69EFCF48CDEFCDCD4645C6C8436FCF49C9EFC5CA29158 244 | the encode random number is 148 245 | encoded msg: 63FFFFFFFFFFFFFFFFFFFC64D6FC44BC86FC645CF48CDEFCB48EFCBCB466FC44F4369EFCD4647CD4E4B4F49C9C36FDBCF46C6C36FD7C845C5CD46FFFFFF8B546 246 | --------------------encode----------------------- 247 | 7678C9CE72182CF83FC44D01BD7CD149DCD8D13396FE9C0F2F731FCEB38EC36C9609C4379E4455DA2FD33377956E50210D5C6349347D383711CBC96443A5F6C8 248 | 8F6D2D07AC9B64D704D70FFE602C9BB6EAA202180B9B8381C4B0162746A81A3BDF3EE29B4A4D4C7579E7EFFA3DACFC349D3AF1280AA904F2949B4A5D3A7DC2 249 | E231F048E463E066B39E023362D6FBFA24E9BD2EA928BC6E6E09D73858EA6880F42AAC79A995127DC57DC63506F5B0C015FD56774B276AB45B9B955D57B9086B 250 | 88230EBA6143E3262932DEFE612BA434CF1C313EF01479EBCC06B6402C86FE14D86B4ECFAFD92FFC06BEF4199EEA2D8491FB53FE8F565765A9D7529C60CABD3A 251 | 32C724EEF85B0D6CC4A59913FA1ED8F0A801B42714F540794828DAFA7F7EC88A77F3D53C06AEDF3B824D5DD7E18299DB10721734FF2DA65DC7DF56686F0F0B 252 | 7257F94E95A4895A32E237F0B8A21788730265BA7562BA22843AF80BA08AA614805F1B62FF522C2ACC9DC20EAD335E2D22434F24F89BF1481EC9B6DB25CD2BB6 253 | 958DDC601076927C1FC45582F6D2E5FBC49F636108C94621C70D02C462E5C670D69C287E232CEBFD122532AB54B290C3A86E1B7E8F65E34005C97FB731821AE8 254 | 28C6659F6972CD28A3DD8A0D9A16B4AAFE2430C1419B8F7F506045A36CA1B9CAD48D82D0E2220673001572529403188A826111A32F9F4F731E54451CC3859ACE 255 | 27C362093BB6099DB28B90BA89045DF128D84ADC513C51F495D4F433E6FBE398FE28A8D0422FCB5076E36360D96B59CFE3AA208F839505553BB0C633D7B290AA 256 | ------------------------------------------------- 257 | the decode random number is 285 258 | decoded msg: 486172727920506F74746572206973206120736572696573206F6620736576656E2066616E74617379206E6F76656C73207772697474656E20627920 259 | the decode random number is 446 260 | decoded msg: 746865204272697469736820617574686F72204A2E204B2E20526F776C696E672E2054686520626F6F6B73206368726F6E69636C6520746865206164 261 | the decode random number is 338 262 | decoded msg: 76656E7475726573206F6620612077697A6172642C20486172727920506F747465722C20616E642068697320667269656E647320526F6E616C642057 263 | the decode random number is 47C 264 | decoded msg: 6561736C657920616E64204865726D696F6E65204772616E6765722C20616C6C206F662077686F6D206172652073747564656E747320617420486F67 265 | the decode random number is 379 266 | decoded msg: 7761727473205363686F6F6C206F66205769746368637261667420616E642057697A61726472792E20546865206D61696E2073746F72792061726320 267 | the decode random number is 196 268 | decoded msg: 636F6E6365726E73204861727279277320717565737420746F206F766572636F6D6520746865204461726B2077697A617264204C6F726420566F6C64 269 | the decode random number is 5D2 270 | decoded msg: 656D6F72742C2077686F73652061696D732061726520746F206265636F6D6520696D6D6F7274616C2C20636F6E71756572207468652077697A617264 271 | the decode random number is 447 272 | decoded msg: 696E6720776F726C642C207375626A7567617465206E6F6E2D6D61676963616C2070656F706C652C20616E642064657374726F7920616C6C2074686F 273 | the decode random number is 148 274 | decoded msg: 73652077686F207374616E6420696E20686973207761792C20657370656369616C6C7920486172727920506F747465720000002E 275 | BigInt to string: Harry Potter is a series of seven fantasy novels written by 276 | BigInt to string: the British author J. K. Rowling. The books chronicle the ad 277 | BigInt to string: ventures of a wizard, Harry Potter, and his friends Ronald W 278 | BigInt to string: easley and Hermione Granger, all of whom are students at Hog 279 | BigInt to string: warts School of Witchcraft and Wizardry. The main story arc 280 | BigInt to string: concerns Harry's quest to overcome the Dark wizard Lord Vold 281 | BigInt to string: emort, whose aims are to become immortal, conquer the wizard 282 | BigInt to string: ing world, subjugate non-magical people, and destroy all tho 283 | BigInt to string: se who stand in his way, especially Harry Potter. 284 | --------------------decode----------------------- 285 | Harry Potter is a series of seven fantasy novels written by the British author J. K. Rowling. The books chronicle the adventures of a wizard, Harry Potter, and his friends Ronald Weasley and Hermione Granger, all of whom are students at Hogwarts School of Witchcraft and Wizardry. The main story arc concerns Harry's quest to overcome the Dark wizard Lord Voldemort, whose aims are to become immortal, conquer the wizarding world, subjugate non-magical people, and destroy all those who stand in his way, especially Harry Potter. 286 | ------------------------------------------------- 287 | Time used: 39.6800s 288 | 289 | -------------------------------------------------------------------------------- /src/BigInt.cpp: -------------------------------------------------------------------------------- 1 | #include "BigInt.h" 2 | #include "utils.h" 3 | 4 | //默认构造函数,成员数据清0 5 | BigInt::BigInt() 6 | { 7 | for(int i=0 ;i < _capacity;i++) 8 | data[i]=0; 9 | sign=true; 10 | } 11 | 12 | 13 | //用int初始化大数 14 | BigInt::BigInt(const int& input) 15 | { 16 | for(int i=0 ;i<_capacity ;i++) 17 | data[i]=0; 18 | data[0]=input; 19 | if(input>=0) 20 | sign=true; 21 | else 22 | sign=false; 23 | } 24 | 25 | //用大数给大数赋值 26 | BigInt::BigInt(const BigInt& input) 27 | { 28 | for(int i = 0; i < _capacity; i++) 29 | data[i] = input.data[i]; 30 | sign = input.sign; 31 | } 32 | 33 | BigInt::BigInt(string str, int base) { 34 | switch (base) { 35 | case BIN_STRING: 36 | GenFromBinString(str); 37 | break; 38 | case BYTE_STRING: 39 | GenFromByteString(str); 40 | break; 41 | case HEX_STRING: 42 | GenFromHexString(str); 43 | break; 44 | default: 45 | LOGLN("BigInt: Error base"); 46 | exit(1); 47 | break; 48 | } 49 | } 50 | 51 | void BigInt::GenFromHexString(string str) 52 | { 53 | Clear(); 54 | int index = 0; 55 | while (str.length() > 8) 56 | { 57 | string seg = str.substr(str.length() - 8, 8); 58 | str.erase(str.length() - 8, 8); 59 | unsigned int cur = 0; 60 | for(int i = 0; i < 8; i++) 61 | { 62 | cur = cur * 16 + _hexCharToInt(seg[i]); 63 | } 64 | data[index++] = cur; 65 | } 66 | unsigned int cur = 0; 67 | for (int i = 0; i < str.length(); i++) 68 | cur = cur * 16 + _hexCharToInt(str[i]); 69 | data[index] = cur; 70 | } 71 | 72 | void BigInt::GenFromBinString(string str) 73 | { 74 | Clear(); 75 | int index = 0; 76 | while (str.length() > 32) 77 | { 78 | string seg = str.substr(str.length() - 32, 32); 79 | str.erase(str.length() - 32, 32); 80 | unsigned int cur = 0; 81 | for (int i = 0; i < 32; i++) 82 | { 83 | cur = cur * 2 + (seg[i] - '0'); 84 | } 85 | data[index++] = cur; 86 | } 87 | unsigned int cur = 0; 88 | for (int i = 0; i < str.length(); i++) 89 | cur = cur * 2 + (str[i] - '0'); 90 | data[index] = cur; 91 | } 92 | 93 | void BigInt::GenFromByteString(const string& buf) { 94 | int len = buf.length(); 95 | int s1, s2, s3, s4; 96 | Clear(); 97 | int mask[] = {0, 8, 16, 24}; 98 | int validmsk = 0xff; 99 | size_t curmsk = 0, cur = 0; 100 | for (int i = 0; i < buf.size(); ++ i) { 101 | int tmp = (int) buf[i]; 102 | data[cur] |= ((tmp << mask[curmsk]) & (validmsk << mask[curmsk])); 103 | curmsk ++; 104 | if (curmsk == 4) { 105 | curmsk = 0; 106 | cur ++; 107 | } 108 | } 109 | } 110 | string BigInt::ToString() const { 111 | string res; 112 | int len = GetLength(); 113 | char ch; 114 | unsigned int f4 = 0xFF, f3 = 0xFF00, f2 = 0xFF0000, f1 = 0xFF000000; 115 | 116 | for (int i = 0; i < len - 1; i++) { 117 | ch = (char)(data[i] & f4); 118 | res += ch; 119 | ch = (char)((data[i] & f3) >> 8); 120 | res += ch; 121 | ch = (char)((data[i] & f2) >> 16); 122 | res += ch; 123 | ch = (char)((data[i] & f1) >> 24); 124 | res += ch; 125 | } 126 | unsigned int tmp = data[len - 1]; 127 | while(tmp) { 128 | ch = (char)(tmp & f4); 129 | res += ch; 130 | tmp >>= 8; 131 | } 132 | return res; 133 | } 134 | 135 | //用大数给大数赋值 136 | BigInt& BigInt::operator= (const BigInt& input) 137 | { 138 | for (int i = 0; i < _capacity; i++) 139 | data[i] = input.data[i]; 140 | sign = input.sign; 141 | return *this; 142 | } 143 | 144 | //比较两个大数的大小,a 0; i--) 148 | { 149 | if (this->data[i] < b.data[i]) 150 | return true; 151 | if (this->data[i] > b.data[i]) 152 | return false; 153 | } 154 | return this->data[0] < b.data[0]; 155 | } 156 | 157 | //比较两个大数的大小,a>b,返回真,否则返回假 158 | bool BigInt::operator> (const BigInt& b) const 159 | { 160 | for (int i = _capacity - 1; i >= 0; i--) 161 | { 162 | if (this->data[i] > b.data[i]) 163 | return true; 164 | if (this->data[i] < b.data[i]) 165 | return false; 166 | } 167 | return false; 168 | } 169 | 170 | //判断两个大数是否相等,相等返回真,否则返回假 171 | bool BigInt::operator== (const BigInt& b) const 172 | { 173 | for (int i = 0; i < _capacity; i++) 174 | if (this->data[i] != b.data[i]) 175 | return false; 176 | return true; 177 | } 178 | 179 | //判断一个大数和一个int值是否相等,相等返回真,否则返回假 180 | bool BigInt::operator== (const int& b) const 181 | { 182 | for (int i = 1; i < this->GetLength(); i++) { 183 | if (this->data[i] != 0) 184 | return false; 185 | } 186 | return this->data[0] == b; 187 | } 188 | 189 | //计算两个大数的和,采用竖式相加法 190 | BigInt BigInt::operator+ (const BigInt& b) const 191 | { 192 | BigInt result; 193 | //64位数据,存放每两位数相加的临时和 194 | unsigned long long sum; 195 | //carry为进位标志,sub为当两数符号相异时,存放每两位数相减的临时差 196 | unsigned int carry = 0, sub; 197 | //取a,b中长度较长的长度 198 | int length = (this->GetLength() >= b.GetLength()? this->GetLength() : b.GetLength()); 199 | 200 | //当两数符号相同时,进行加法运算 201 | if (this->sign == b.sign) 202 | { 203 | //每一位进行竖式相加 204 | for (int i = 0; i < length; i++) 205 | { 206 | sum = (unsigned long long)this->data[i] + b.data[i] + carry; 207 | result.data[i] = (unsigned int)sum; 208 | //sum的高位为进位 209 | carry = (sum >> 32); 210 | } 211 | 212 | result.sign = this->sign; 213 | return result; 214 | } 215 | 216 | //两数符号不同时,进行减法运算 217 | else 218 | { 219 | BigInt tempa, tempb; 220 | 221 | //取出a,b中绝对值较大的作为被减数 222 | if (*this < b) 223 | { 224 | tempa = b; 225 | tempb = *this; 226 | } 227 | else 228 | { 229 | tempa = *this; 230 | tempb = b; 231 | } 232 | 233 | //每一位进行竖式减 234 | for (int i = 0; i < length; i++) 235 | { 236 | sub = tempb.data[i] + carry; 237 | if (tempa.data[i] >= sub) 238 | { 239 | result.data[i] = tempa.data[i] - sub; 240 | carry = 0; 241 | } 242 | else 243 | { 244 | //借位减 245 | result.data[i] = (unsigned long long)tempa.data[i] + ((unsigned long long)1<<32) - sub; 246 | carry = 1; 247 | } 248 | } 249 | result.sign = tempa.sign; 250 | return result; 251 | } 252 | } 253 | 254 | //计算两个大数的差,采用竖式相减法 255 | BigInt BigInt::operator- (const BigInt& b) const 256 | { 257 | BigInt result; 258 | //64位数据,存放每两位数相加的临时和 259 | unsigned long long sum; 260 | //carry为进位标志,sub为当两数符号相异时,存放每两位数相减的临时差 261 | unsigned int carry = 0, sub; 262 | 263 | //符号相同时,进行减法运算 264 | if (this->sign == b.sign) 265 | { 266 | BigInt tempa, tempb; 267 | 268 | //取出a,b中绝对值较大的作为被减数 269 | if (*this < b) 270 | { 271 | tempa = b; 272 | tempb = *this; 273 | tempa.sign = !tempa.sign; 274 | } 275 | else 276 | { 277 | tempa = *this; 278 | tempb = b; 279 | } 280 | 281 | //每一位进行竖式减 282 | for (int i = 0; i < _capacity; i++) 283 | { 284 | sub = tempb.data[i] + carry; 285 | if (tempa.data[i] >= sub) 286 | { 287 | result.data[i] = tempa.data[i] - sub; 288 | carry = 0; 289 | } 290 | else 291 | { 292 | //借位减 293 | result.data[i] = (unsigned long long)tempa.data[i] + ((unsigned long long)1<<32) - sub; 294 | carry = 1; 295 | } 296 | } 297 | result.sign = tempa.sign; 298 | return result; 299 | } 300 | 301 | //两数符号不同时,进行加法运算 302 | else 303 | { 304 | //每一位进行竖式相加 305 | for (int i = 0; i < _capacity; i++) 306 | { 307 | sum = (unsigned long long)this->data[i] + b.data[i] + carry; 308 | result.data[i] = (unsigned int)sum; 309 | //sum的高位为进位 310 | carry = (sum >> 32); 311 | } 312 | result.sign = this->sign; 313 | return result; 314 | } 315 | } 316 | 317 | //大数减一个int数 318 | BigInt BigInt::operator- (const int& b) const 319 | { 320 | BigInt temp(b); 321 | BigInt result = *this - temp; 322 | return result; 323 | } 324 | 325 | 326 | //大数乘以一个INT数 327 | BigInt BigInt::operator* (const unsigned int& b) const 328 | { 329 | BigInt result; 330 | //存放B乘以A的每一位的临时积 331 | unsigned long long sum; 332 | //存放进位 333 | unsigned int carry = 0; 334 | 335 | for (int i = 0; i < _capacity; i++) 336 | { 337 | sum = ((unsigned long long)this->data[i]) * b + carry; 338 | result.data[i] = (unsigned int)sum; 339 | //进位在SUM的高位中 340 | carry = (sum>>32); 341 | } 342 | result.sign = this->sign; 343 | return result; 344 | } 345 | 346 | //大数相乘,采用竖式乘 347 | BigInt BigInt::operator* (const BigInt& b) const 348 | { 349 | //last存放竖式上一行的积,temp存放当前行的积 350 | BigInt result, last, temp; 351 | //sum存放当前行带进位的积 352 | unsigned long long sum; 353 | //存放进位 354 | unsigned int carry; 355 | 356 | //进行竖式乘 357 | for (int i = 0; i < b.GetLength(); i++) 358 | { 359 | carry = 0; 360 | //B的每一位与A相乘 361 | for (int j = 0; j < this->GetLength() + 1; j++) 362 | { 363 | sum = ((unsigned long long)this->data[j]) * b.data[i] + carry; 364 | if ((i + j) < _capacity) 365 | temp.data[i + j] = (unsigned int)sum; 366 | carry = (sum>>32); 367 | } 368 | result = (temp + last); 369 | last = result; 370 | temp.Clear(); 371 | } 372 | 373 | //判断积的符号 374 | if (this->sign == b.sign) 375 | result.sign = true; 376 | else 377 | result.sign = false; 378 | 379 | return result; 380 | } 381 | 382 | //大数除,采用试商除法,采用二分查找法优化 383 | BigInt BigInt::operator/ (const BigInt& b) const 384 | { 385 | //mul为当前试商,low,high为二分查找试商时所用的标志 386 | unsigned int mul, low, high; 387 | //sub为除数与当前试商的积,subsequent为除数与下一试商的积 388 | //dividend存放临时被除数 389 | BigInt dividend, quotient, sub, subsequent; 390 | int lengtha = this->GetLength(), lengthb = b.GetLength(); 391 | 392 | //如果被除数小于除数,直接返回0 393 | if (*this < b) 394 | { 395 | if (this->sign == b.sign) 396 | quotient.sign = true; 397 | else 398 | quotient.sign = false; 399 | return quotient; 400 | } 401 | 402 | //把被除数按除数的长度从高位截位 403 | for (int i = 0; i < lengthb; i++) 404 | dividend.data[i] = this->data[lengtha - lengthb + i]; 405 | 406 | for (int i = lengtha - lengthb; i >= 0; i--) 407 | { 408 | //如果被除数小于除数,再往后补位 409 | if (dividend < b) 410 | { 411 | for (int j = lengthb; j > 0; j--) 412 | dividend.data[j] = dividend.data[j - 1]; 413 | dividend.data[0] = this->data[i - 1]; 414 | continue; 415 | } 416 | 417 | low = 0; 418 | high = 0xffffffff; 419 | 420 | //二分查找法查找试商 421 | while (low < high) 422 | { 423 | mul = (((unsigned long long)high) + low) / 2; 424 | sub = (b * mul); 425 | subsequent = (b * (mul + 1)); 426 | 427 | if (((sub < dividend) && (subsequent > dividend)) || (sub == dividend)) 428 | break; 429 | if (subsequent == dividend) 430 | { 431 | mul++; 432 | sub = subsequent; 433 | break; 434 | } 435 | if ((sub < dividend) && (subsequent < dividend)) 436 | { 437 | low = mul; 438 | continue; 439 | } 440 | if ((sub > dividend) && (subsequent > dividend)) 441 | { 442 | high = mul; 443 | continue; 444 | } 445 | } 446 | 447 | //试商结果保存到商中去 448 | quotient.data[i] = mul; 449 | //临时被除数变为被除数与试商积的差 450 | dividend = dividend - sub; 451 | 452 | //临时被除数往后补位 453 | if ((i - 1) >= 0) 454 | { 455 | for (int j = lengthb; j > 0; j--) 456 | dividend.data[j] = dividend.data[j - 1]; 457 | dividend.data[0] = this->data[i - 1]; 458 | } 459 | } 460 | 461 | //判断商的符号 462 | if (this->sign == b.sign) 463 | quotient.sign = true; 464 | else 465 | quotient.sign = false; 466 | return quotient; 467 | } 468 | 469 | //大数求模运算,与除法运算类似 470 | BigInt BigInt::operator% (const BigInt& b) const 471 | { 472 | unsigned int mul, low, high; 473 | BigInt dividend, quotient, sub, subsequent; 474 | int lengtha = this->GetLength(), lengthb = b.GetLength(); 475 | 476 | //如果被除数小于除数,返回被除数为模 477 | if (*this < b) 478 | { 479 | dividend = *this; 480 | //余数的商永远与被除数相同 481 | dividend.sign = this->sign; 482 | return dividend; 483 | } 484 | 485 | //进行除法运算 486 | for (int i = 0; i < lengthb; i++) 487 | dividend.data[i] = this->data[lengtha - lengthb + i]; 488 | 489 | for (int i = lengtha - lengthb; i >= 0; i--) 490 | { 491 | if (dividend < b) 492 | { 493 | for (int j = lengthb; j > 0; j--) 494 | dividend.data[j] = dividend.data[j - 1]; 495 | dividend.data[0] = this->data[i - 1]; 496 | continue; 497 | } 498 | 499 | low = 0; 500 | high = 0xffffffff; 501 | 502 | while (low <= high) 503 | { 504 | mul = (((unsigned long long)high) + low) / 2; 505 | sub = (b * mul); 506 | subsequent = (b * (mul + 1)); 507 | 508 | if (((sub < dividend) && (subsequent > dividend)) || (sub == dividend)) 509 | break; 510 | if (subsequent == dividend) 511 | { 512 | mul++; 513 | sub = subsequent; 514 | break; 515 | } 516 | if ((sub < dividend) && (subsequent < dividend)) 517 | { 518 | low = mul; 519 | continue; 520 | } 521 | if ((sub > dividend) && (subsequent > dividend)) 522 | { 523 | high = mul; 524 | continue; 525 | } 526 | } 527 | 528 | quotient.data[i] = mul; 529 | dividend = dividend - sub; 530 | if ((i - 1) >= 0) 531 | { 532 | for (int j = lengthb; j > 0; j--) 533 | dividend.data[j] = dividend.data[j - 1]; 534 | dividend.data[0] = this->data[i - 1]; 535 | } 536 | } 537 | 538 | //临时被除数即为所求模 539 | dividend.sign = this->sign; 540 | return dividend; 541 | } 542 | int BigInt::operator% (const int& b) const { 543 | int len = this->GetLength(); 544 | if (len == 1) 545 | return this->data[0] % b; 546 | 547 | unsigned long long cur = 0; 548 | 549 | for (int i = len - 1; i >= 0; i--) { 550 | cur = (cur << 32) + this->data[i]; 551 | cur = cur % b; 552 | } 553 | return (int)cur; 554 | } 555 | 556 | BigInt BigInt::operator& (const BigInt& b) const { 557 | int len = max(this->GetLength(), b.GetLength()); 558 | BigInt res; 559 | for (int i = 0; i < len; i++) 560 | res.data[i] = (this->data[i] & b.data[i]); 561 | res.sign = (this->sign & b.sign); 562 | return res; 563 | } 564 | 565 | BigInt BigInt::operator^ (const BigInt& b) const{ 566 | int len = max(this->GetLength(), b.GetLength()); 567 | BigInt res; 568 | for (int i = 0; i < len; i++) 569 | res.data[i] = (this->data[i] ^ b.data[i]); 570 | res.sign = (this->sign ^ b.sign); 571 | return res; 572 | } 573 | 574 | BigInt BigInt::operator| (const BigInt& b) const { 575 | int len = max(this->GetLength(), b.GetLength()); 576 | BigInt res; 577 | for (int i = 0; i < len; i++) 578 | res.data[i] = (this->data[i] ^ b.data[i]); 579 | res.sign = (this->sign ^ b.sign); 580 | return res; 581 | } 582 | 583 | 584 | //将大数输出到输入输出流 585 | void BigInt::_output(ostream& out) const 586 | { 587 | unsigned int temp, result; 588 | unsigned int filter = 0xf0000000; 589 | string resStr; 590 | for(int i = GetLength() - 1; i >= 0; i--) 591 | { 592 | temp = data[i]; 593 | //大数的每一位数字转换成16进制输出 594 | for (int j = 0; j < 8; j++) 595 | { 596 | result = temp & filter; 597 | result = (result >> 28); 598 | temp = (temp << 4); 599 | if (result >= 0 && result <= 9) 600 | resStr += (result + '0'); 601 | else 602 | { 603 | switch (result) 604 | { 605 | case 10: 606 | resStr += 'A'; 607 | break; 608 | case 11: 609 | resStr += 'B'; 610 | break; 611 | case 12: 612 | resStr += 'C'; 613 | break; 614 | case 13: 615 | resStr += 'D'; 616 | break; 617 | case 14: 618 | resStr += 'E'; 619 | break; 620 | case 15: 621 | resStr += 'F'; 622 | break; 623 | } 624 | } 625 | } 626 | } 627 | while (resStr[0] == '0') 628 | { 629 | resStr.erase(0,1); 630 | } 631 | out << resStr; 632 | } 633 | 634 | //重载输出操作符 635 | ostream& operator<< (ostream& out, const BigInt& x) 636 | { 637 | x._output(out); 638 | return out; 639 | } 640 | 641 | string BigInt::ToHexString() const 642 | { 643 | unsigned int temp, result; 644 | unsigned int filter = 0xf0000000; 645 | string resStr; 646 | for(int i = GetLength() - 1; i >= 0; i--) 647 | { 648 | temp = data[i]; 649 | //大数的每一位数字转换成16进制输出 650 | for (int j = 0; j < 8; j++) 651 | { 652 | result = temp & filter; 653 | result = (result >> 28); 654 | temp = (temp << 4); 655 | if (result >= 0 && result <= 9) 656 | resStr += (result + '0'); 657 | else 658 | { 659 | switch (result) 660 | { 661 | case 10: 662 | resStr += 'A'; 663 | break; 664 | case 11: 665 | resStr += 'B'; 666 | break; 667 | case 12: 668 | resStr += 'C'; 669 | break; 670 | case 13: 671 | resStr += 'D'; 672 | break; 673 | case 14: 674 | resStr += 'E'; 675 | break; 676 | case 15: 677 | resStr += 'F'; 678 | break; 679 | } 680 | } 681 | } 682 | } 683 | while (resStr[0] == '0') 684 | { 685 | resStr.erase(0,1); 686 | } 687 | return resStr; 688 | } 689 | //大数置0 690 | void BigInt::Clear() 691 | { 692 | for (int i = 0; i < _capacity; i++) 693 | data[i] = 0; 694 | } 695 | 696 | //返回大数长度 697 | int BigInt::GetLength() const 698 | { 699 | int length = _capacity; 700 | for (int i = _capacity - 1; i >= 0; i--) 701 | { 702 | //第一位不为0即为LENGTH 703 | if (data[i] == 0) 704 | length--; 705 | else 706 | break; 707 | } 708 | if (length == 0) 709 | length = 1; 710 | return length; 711 | } 712 | 713 | int BigInt::GetBitLength() const { 714 | int len = GetLength(); 715 | int res = (len - 1) * 32; 716 | unsigned int tmp = data[len - 1]; 717 | while (tmp > 0) { 718 | res ++; 719 | tmp = (tmp >> 1); 720 | } 721 | return res; 722 | } 723 | 724 | //重载移位操作符,向右移a(a < 32)位 725 | BigInt& BigInt::operator>> (const int& a) 726 | { 727 | unsigned int bit, filter; 728 | filter = (1 << a) - 1; 729 | data[0] = (data[0] >> a); 730 | for (int i = 1; i < GetLength(); i++) 731 | { 732 | //先将每一位的低a位移到BIT中 733 | bit = data[i] & filter; 734 | //再把BIT移到上一位的高位中 735 | bit = bit << (32 - a); 736 | data[i - 1] = data[i - 1] | bit; 737 | data[i] = (data[i] >> a); 738 | } 739 | return *this; 740 | } 741 | //重载移位操作符,向左移a位 742 | BigInt& BigInt::operator<< (const int& a) { 743 | unsigned int bit, filter; 744 | filter = (1 << a) - 1; 745 | filter = (filter << (32 - a)); 746 | int len = GetLength(); 747 | for (int i = len - 1; i >= 0; i--) { 748 | bit = data[i] & filter; 749 | bit = bit >> (32 - a); 750 | data[i + 1] = data[i + 1] | bit; 751 | data[i] = (data[i] << a); 752 | } 753 | return *this; 754 | } 755 | 756 | //判断大数和一个INT的大小 757 | bool BigInt::operator<= (const int& b) const 758 | { 759 | for (int i = 1; i < this->GetLength(); i++) 760 | { 761 | if (this->data[i] != 0) 762 | return false; 763 | } 764 | if (this->data[0] <= b) 765 | return true; 766 | else 767 | return false; 768 | } 769 | 770 | 771 | //模幂运算,采用蒙格马利快速模幂算法 772 | BigInt BigInt::PowerMode (const BigInt& n, const BigInt& p, const BigInt& m) 773 | { 774 | BigInt temp = p; 775 | BigInt r = n % m; 776 | BigInt k(1); 777 | while ( !(temp <= 1) ) 778 | { 779 | if (temp.IsOdd()) 780 | { 781 | k = (k * r) % m; 782 | } 783 | r = (r * r) % m; 784 | temp >> 1; 785 | } 786 | return ( r * k ) % m; 787 | } 788 | 789 | char BigInt::_intToHexChar(int n) 790 | { 791 | char c; 792 | if (n >= 0 && n <= 9) 793 | c = '0' + n; 794 | else switch (n) 795 | { 796 | case 10: 797 | c = 'A'; 798 | break; 799 | case 11: 800 | c = 'B'; 801 | break; 802 | case 12: 803 | c = 'C'; 804 | break; 805 | case 13: 806 | c = 'D'; 807 | break; 808 | case 14: 809 | c = 'E'; 810 | break; 811 | case 15: 812 | c = 'F'; 813 | break; 814 | default: 815 | break; 816 | } 817 | return c; 818 | } 819 | 820 | int BigInt::_hexCharToInt(char c) 821 | { 822 | if (c >= '0' && c <= '9') 823 | return c - '0'; 824 | else switch (c) 825 | { 826 | case 'a': 827 | case 'A': 828 | return 10; 829 | case 'b': 830 | case 'B': 831 | return 11; 832 | case 'c': 833 | case 'C': 834 | return 12; 835 | case 'd': 836 | case 'D': 837 | return 13; 838 | case 'e': 839 | case 'E': 840 | return 14; 841 | case 'f': 842 | case 'F': 843 | return 15; 844 | default: 845 | break; 846 | } 847 | LOGLN("BigInt: hexCharToInt error"); 848 | exit(0); 849 | } 850 | 851 | //产生一个随机大数,其二进制长度为digNum 852 | void BigInt::Random(int digNum) 853 | { 854 | if (digNum < 32) { 855 | data[0] = (rand() << 17 ) + ( rand() << 2 )+ rand() % 4; 856 | unsigned int filter = 1; 857 | filter = (1 << digNum) - 1; 858 | data[0] = (data[0] & filter); 859 | return; 860 | } 861 | for (int i = 0; i < digNum / 32; i++) { 862 | //由于RAND()最大只能产生0X7FFF的数,为了能产生32位的随机数,需要 863 | //3次RAND()操作 864 | data[i] = (rand() << 17 ) + ( rand() << 2 )+ rand() % 4; 865 | } 866 | data[digNum/32-1] = data[digNum/32-1] | 0x80000000; 867 | } 868 | 869 | 870 | //产生一个较小的随机大数,其二进制长度为digNum的1/4; 871 | void BigInt::Randomsmall(int digNum) 872 | { 873 | if (digNum < 128) { 874 | data[0] = (rand() << 17 ) + ( rand() << 2 )+ rand() % 4; 875 | unsigned int filter = 1; 876 | int tmp = digNum / 4; 877 | filter = (1 << tmp) - 1; 878 | data[0] = (data[0] & filter); 879 | return; 880 | } 881 | for (int i = 0; i < digNum / 128; i++) { 882 | //由于RAND()最大只能产生0X7FFF的数,为了能产生32位的随机数,需要 883 | //3次RAND()操作 884 | data[i] = (rand() << 17 ) + ( rand() << 2 )+ rand() % 4; 885 | } 886 | data[digNum/128-1] = data[digNum/32-1] | 0x80000000; 887 | } 888 | 889 | //求两个大数的最大公约数,采用辗转相除法 890 | BigInt BigInt::Gcd(const BigInt& m, const BigInt& n) 891 | { 892 | //cout << "m: ";m.displayByHex(); cout << "n: ";n.displayByHex();cout << endl; 893 | //outfile << "m: ";outfile << m; outfile << "n: ";outfile << n;outfile << endl; 894 | if (n == 0) 895 | return m; 896 | else 897 | return Gcd(n, m%n); 898 | } 899 | 900 | //用扩展欧几里德算法求乘法模逆 901 | BigInt BigInt::ExtendedGcd(const BigInt& a, const BigInt& b, BigInt& x, BigInt& y) 902 | { 903 | /* naive version 904 | BigInt t, d; 905 | //如果一个操作数为零则无法进行除法运算 906 | if (b == 0) 907 | { 908 | x = 1, y = 0; 909 | return a; 910 | } 911 | BigInt tb = a % b; 912 | d = ExtendedGcd(b, tb, x, y); 913 | t = x; 914 | x = y; 915 | y = t - ((a / b) * y); 916 | return d; */ 917 | BigInt x0 = 1, y0 = 0, x1 = 0, y1 = 1, c = a, d = b; 918 | BigInt k, r, t; 919 | while (!(d == 0)) { 920 | k = c / d; 921 | r = c % d; 922 | t = c; 923 | c = d; 924 | d = r; 925 | t = x0; 926 | x0 = x1; 927 | x1 = t - k * x1; 928 | t = y0; 929 | y0 = y1; 930 | y1 = t - k * y1; 931 | } 932 | x = x0, y = y0; 933 | return c; 934 | } 935 | 936 | BigInt BigInt::Euc(BigInt& E,BigInt& A) 937 | { 938 | BigInt M, X, Y, I, J; 939 | int x, y; 940 | M = A; 941 | X = 0; 942 | Y = 1; 943 | x = y = 1; 944 | while ((E.GetLength() != 1) || !(E == 0)) 945 | { 946 | I = M / E; 947 | J = M % E; 948 | M = E; 949 | E = J; 950 | J = Y; 951 | Y = Y * I; 952 | if (x == y) 953 | { 954 | if (X > Y) 955 | Y = X - Y; 956 | else 957 | { 958 | Y = Y - X; 959 | y = 0; 960 | } 961 | } 962 | else 963 | { 964 | Y = X + Y; 965 | x = 1 - x; 966 | y = 1 - y; 967 | } 968 | X = J; 969 | } 970 | if (x == 0) 971 | X = A - X; 972 | return X; 973 | } 974 | -------------------------------------------------------------------------------- /src/Key.cpp: -------------------------------------------------------------------------------- 1 | #include "Key.h" 2 | #include "BigInt.h" 3 | #include "PrimeGen.h" 4 | #include "globalData.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "utils.h" 10 | 11 | using namespace std; 12 | 13 | void Key::generate(int digNum) { 14 | this->digNum = digNum; 15 | srand((unsigned)time(NULL)); 16 | 17 | BigInt p(GeneratePrime(digNum)); 18 | BigInt q(GeneratePrime(digNum)); 19 | 20 | LOGLN("Key: 密钥生成"); 21 | BigInt t = (p - 1) * (q - 1); 22 | BigInt x, y, temp; 23 | while (1) 24 | { 25 | e.Random(digNum); 26 | //产生与T互质的E 27 | while (!(BigInt::Gcd(e,t) == 1)) 28 | e.Random(digNum); 29 | temp = BigInt::ExtendedGcd(e, t, x, y); 30 | temp = (e * x) % t; 31 | if (temp == 1) 32 | break; 33 | } 34 | LOGLN(" 公钥e: " << e); 35 | 36 | n = p * q; 37 | LOGLN(" 公钥n: " << n); 38 | 39 | d = x; 40 | LOGLN(" 私钥d: " << d); 41 | 42 | } 43 | 44 | void Key::getPublicKey(BigInt& N, BigInt& E) const 45 | { 46 | N = this->n; 47 | E = this->e; 48 | } 49 | void Key::getPrivateKey(BigInt& N, BigInt& D) const 50 | { 51 | N = this->n; 52 | D = this->d; 53 | } 54 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | OBJS = BigInt.o Key.o OAEP.o PrimeGen.o RSA.o StringTrans.o 2 | CFLAGS = -c -Iinclude 3 | 4 | all: libRSA.a 5 | 6 | libRSA.a: $(OBJS) 7 | ar cr $@ $^ 8 | 9 | %.o: %.cpp 10 | $(CXX) $(CFLAGS) $< -o $@ 11 | 12 | BigInt.o: BigInt.cpp include/BigInt.h include/globalData.h include/utils.h 13 | 14 | Key.o: Key.cpp include/Key.h include/BigInt.h include/PrimeGen.h include/globalData.h include/utils.h 15 | 16 | OAEP.o: OAEP.cpp include/OAEP.h include/BigInt.h include/Key.h include/utils.h 17 | 18 | PrimeGen.o: PrimeGen.cpp include/PrimeGen.h include/BigInt.h include/utils.h 19 | 20 | RSA.o: RSA.cpp include/RSA.h include/Key.h include/utils.h 21 | 22 | StringTrans.o: StringTrans.cpp include/StringTrans.h include/OAEP.h include/RSA.h include/BigInt.h include/utils.h 23 | 24 | clean: 25 | rm -f $(OBJS) libRSA.a 26 | -------------------------------------------------------------------------------- /src/OAEP.cpp: -------------------------------------------------------------------------------- 1 | #include "OAEP.h" 2 | #include 3 | #include 4 | #include "BigInt.h" 5 | #include "Key.h" 6 | #include 7 | #include "utils.h" 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | // map k bits number to m bits number.(k << m) 13 | BigInt OAEP::k_to_m(const BigInt& cnt) { 14 | //cnt have k bits 15 | BigInt res(cnt), tmp(cnt); 16 | while (res.GetBitLength() < M) { 17 | tmp = (tmp << 1); 18 | res = (res ^ tmp); 19 | } 20 | return res; 21 | } 22 | 23 | // map m bits number to k bits number. (m >> k) 24 | BigInt OAEP::m_to_k(const BigInt& cnt) { 25 | //the digits of cnt must more than k 26 | BigInt filter(1), res(0), tmp(cnt); 27 | for (int i = 0; i < K/16; i++) 28 | filter = (filter << 16); 29 | filter = (filter << (K % 16)); 30 | filter = filter - 1; 31 | res = filter; 32 | filter = (filter >> 1); 33 | while (tmp.GetBitLength() >= K) { 34 | res = (filter & tmp) ^ res; 35 | tmp = (tmp >> 1); 36 | } 37 | return res; 38 | } 39 | 40 | OAEP::OAEP(int k, int m) { 41 | this->K = k; 42 | this->M = m; 43 | } 44 | 45 | BigInt OAEP::encode(const BigInt& cnt) { 46 | if (cnt.GetBitLength() > M) { 47 | fprintf(stderr, "OAEP Error: Message out of range. Length is %d\n", cnt.GetBitLength()); 48 | exit(EXIT_FAILURE); 49 | } 50 | BigInt r, tmp, P1, P2; 51 | srand((unsigned) time(NULL)); 52 | r.Random(K); 53 | tmp = k_to_m(r); 54 | P1 = cnt ^ tmp; 55 | 56 | tmp = m_to_k(P1); 57 | P2 = tmp ^ r; 58 | 59 | for (int i = 0; i < K/16; i++) 60 | P1 = (P1 << 16); 61 | P1 = (P1 << (K % 16)); 62 | P1 = P1 | P2; 63 | return P1; 64 | } 65 | 66 | BigInt OAEP::decode(const BigInt& cnt) { 67 | BigInt r, tmp, P1(cnt), P2, res; 68 | BigInt filter(1); 69 | for (int i = 0; i < K/16; i++) 70 | filter = (filter << 16); 71 | filter = (filter << (K % 16)); 72 | filter = filter - 1; 73 | P2 = (cnt & filter); 74 | 75 | for (int i = 0; i < K/16; i++) 76 | P1 = (P1 >> 16); 77 | P1 = (P1 >> (K % 16)); 78 | 79 | tmp = m_to_k(P1); 80 | r = (tmp ^ P2); 81 | 82 | tmp = k_to_m(r); 83 | res = (tmp ^ P1); 84 | return res; 85 | } 86 | 87 | void OAEP::encode(StringTrans& st) { 88 | for (StringTrans::iterator itr = st.begin(); itr != st.end(); ++ itr) { 89 | *itr = encode(*itr); 90 | } 91 | } 92 | 93 | void OAEP::decode(StringTrans& st) { 94 | for (StringTrans::iterator itr = st.begin(); itr != st.end(); ++ itr) { 95 | *itr = decode(*itr); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/PrimeGen.cpp: -------------------------------------------------------------------------------- 1 | #include "PrimeGen.h" 2 | #include "BigInt.h" 3 | #include "utils.h" 4 | 5 | /** 6 | * 产生一个待测素数,保证此数为奇数,且不能被小于5000的素数整除 7 | * 8 | * @param [out] n 9 | * @param [in] digNum 位数 10 | */ 11 | void GenPrime(BigInt& n, int digNum) 12 | { 13 | int i = 0; 14 | BigInt divisor; 15 | const int length = sizeof(prime) / sizeof(int); 16 | while (i != length) 17 | { 18 | n.Random(digNum); 19 | while (!n.IsOdd()) 20 | n.Random(digNum); 21 | i = 0; 22 | for ( ; i < length; i++) 23 | { 24 | divisor = prime[i]; 25 | if ((n % divisor) == 0) 26 | break; 27 | } 28 | } 29 | } 30 | 31 | /** 32 | * Rabin-Miller 素性测试 33 | * 34 | * @param n 35 | * @param digNum 位数 36 | * @return true: 是素数, false: 不是素数 37 | */ 38 | bool RabinMiller(const BigInt& n, int digNum) 39 | { 40 | BigInt r, a, y; 41 | unsigned int s, j; 42 | r = n - 1; 43 | s = 0; 44 | 45 | //找到令N-1=2^S*R的S和R,R为奇数 46 | while (!r.IsOdd()) 47 | { 48 | s++; 49 | r >> 1; 50 | } 51 | 52 | //产生一个小于N-1的检测随机数 53 | a.Randomsmall(digNum); 54 | 55 | y = BigInt::PowerMode(a, r, n); 56 | 57 | //检测J=2至J 6 | 7 | BigInt RSA::encrypt(const BigInt& src, const BigInt& N, const BigInt& E) 8 | { 9 | if (!(src < N)) { 10 | fprintf(stderr, "RSA Error: Encrypt source is bigger than N\n"); 11 | exit(EXIT_FAILURE); 12 | } 13 | return BigInt::PowerMode(src, E, N); 14 | } 15 | BigInt RSA::encrypt(const BigInt& src) const 16 | { 17 | BigInt N, E; 18 | key.getPublicKey(N, E); 19 | return RSA::encrypt(src, N, E); 20 | } 21 | void RSA::encrypt(StringTrans& st, const BigInt& N, const BigInt& E) { 22 | for (StringTrans::iterator itr = st.begin(); itr != st.end(); itr ++) { 23 | *itr = RSA::encrypt(*itr, N, E); 24 | } 25 | } 26 | BigInt RSA::decrypt(const BigInt& src, const BigInt& N, const BigInt& D) 27 | { 28 | if (!(src < N)) { 29 | fprintf(stderr, "RSA Error: Encrypt source is bigger than N\n"); 30 | exit(EXIT_FAILURE); 31 | } 32 | return BigInt::PowerMode(src, D, N); 33 | } 34 | BigInt RSA::decrypt(const BigInt& src) const 35 | { 36 | BigInt N, D; 37 | key.getPrivateKey(N, D); 38 | return RSA::decrypt(src, N, D); 39 | } 40 | void RSA::decrypt(StringTrans& st) { 41 | for (StringTrans::iterator itr = st.begin(); itr != st.end(); itr ++) { 42 | *itr = RSA::decrypt(*itr); 43 | } 44 | } 45 | void RSA::getPublicKey(BigInt& N, BigInt& E) const 46 | { 47 | key.getPublicKey(N, E); 48 | } 49 | void RSA::getPrivateKey(BigInt& N,BigInt& D) const 50 | { 51 | key.getPrivateKey(N, D); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/StringTrans.cpp: -------------------------------------------------------------------------------- 1 | #include "StringTrans.h" 2 | #include 3 | #include 4 | #include "BigInt.h" 5 | #include "OAEP.h" 6 | #include "RSA.h" 7 | #include "utils.h" 8 | using namespace std; 9 | 10 | StringTrans::StringTrans(const string& a, int b) { 11 | this->BitLen = b; 12 | this->split(a); 13 | } 14 | 15 | void StringTrans::split(const string& msg) { 16 | int n = 0,i = 0,j = 0; 17 | int StrLen = BitLen / 8; 18 | (*this).clear(); 19 | const char* msg_c = msg.c_str(); 20 | do 21 | { 22 | char seg_c[255]; 23 | for (i = n * StrLen,j = 0;i < msg.length() && i < (n + 1) * StrLen;i++,j++) 24 | seg_c[j] = msg_c[i]; 25 | seg_c[j] = '\0'; 26 | string segment(seg_c); 27 | vector::push_back(BigInt(segment, 10)); 28 | n++; 29 | } 30 | while (n * StrLen < msg.length()); 31 | } 32 | 33 | string StringTrans::toHexString() { 34 | int len = this->size(); 35 | string res, tmp; 36 | for (int i = 0; i < len; i++) { 37 | tmp = (*this)[i].ToHexString(); 38 | res = res + tmp; 39 | } 40 | return res; 41 | } 42 | 43 | string StringTrans::toString() { 44 | int len = this->size(); 45 | string res, tmp; 46 | for (int i = 0; i < len; i++) { 47 | tmp = (*this)[i].ToString(); 48 | res = res + tmp; 49 | } 50 | return res; 51 | } 52 | 53 | void StringTrans::push_back(const string& str) { 54 | this->push_back(str); 55 | } 56 | 57 | void StringTrans::push_back(const BigInt& bigInt) { 58 | vector::push_back(bigInt); 59 | } 60 | 61 | StringTrans& StringTrans::operator+= (const string& str) { 62 | this->push_back(str); 63 | return *this; 64 | } 65 | 66 | StringTrans& StringTrans::operator+= (const BigInt& bigInt) { 67 | vector::push_back(bigInt); 68 | return *this; 69 | } 70 | 71 | StringTrans& StringTrans::operator+= (const StringTrans& st) { 72 | for (StringTrans::const_iterator itr = st.begin(); itr != st.end(); itr ++) 73 | vector::push_back(*itr); 74 | return *this; 75 | } 76 | -------------------------------------------------------------------------------- /src/include/BigInt.h: -------------------------------------------------------------------------------- 1 | #ifndef BIGINT_H_ 2 | #define BIGINT_H_ 3 | #include 4 | #include 5 | #include 6 | #include "globalData.h" 7 | 8 | using namespace std; 9 | 10 | class BigInt { 11 | public: 12 | /** 13 | * 无参构造函数,默认为0 14 | */ 15 | BigInt(); 16 | 17 | /** 18 | * 用int类型参数初始化大数 19 | * 20 | * @param [in] input 输入的int类型数据 21 | */ 22 | BigInt(const int&); 23 | 24 | /** 25 | * 拷贝构造函数 26 | * 27 | * @param [in] input 另一个大数 28 | */ 29 | BigInt(const BigInt&); 30 | 31 | /** 32 | * 构造函数,从16进制字符串构造 33 | * 34 | * @param [in] str 35 | * @param [in] base 进制(2, 10, 16) 36 | */ 37 | BigInt(string, int); 38 | /** 39 | * 从16进制字符串读入数据 40 | * 41 | * @param str 16进制字符串 42 | */ 43 | void GenFromHexString(string str); 44 | 45 | /** 46 | * 从2进制字符串读入数据 47 | * 48 | * @param buf 2进制字符串 49 | */ 50 | void GenFromBinString(string buf); 51 | 52 | /** 53 | * 从字节串读入数据 54 | * 55 | * @param buf 字节串 56 | */ 57 | void GenFromByteString(const string& buf); 58 | 59 | /** 60 | * 把大数转换成10进制字符串 61 | * 62 | * @return 大数10进制字符串 63 | */ 64 | string ToString() const; 65 | 66 | /** 67 | * 把大数转换成16进制字符串 68 | * 69 | * @return 大数16进制字符串 70 | */ 71 | string ToHexString() const; 72 | 73 | /** 74 | * 赋值运算符(深拷贝) 75 | * 76 | * @param input 另一个大数 77 | */ 78 | BigInt& operator= (const BigInt&); 79 | 80 | /** 81 | * 赋值运算符,用int类型整数赋值 82 | * 83 | * @param a 整数 84 | */ 85 | BigInt& operator= (int& a) { Clear(); data[0]=a; return *this;} 86 | 87 | /** 88 | * 位右移运算符 89 | * 90 | * @param a 右移位数 91 | */ 92 | BigInt& operator>> (const int&); 93 | 94 | /** 95 | * 位左移运算符 96 | * 97 | * @param a 左移位数 98 | */ 99 | BigInt& operator<< (const int&); 100 | 101 | /** 102 | * 返回大数的二进制长度 103 | * 104 | * @return 二进制长度 105 | */ 106 | int GetBitLength() const; 107 | 108 | /** 109 | * 返回大数的长度(已占用的内部储存数组长度) 110 | * 111 | * @return 大数的长度 112 | */ 113 | int GetLength() const; 114 | 115 | /** 116 | * 判断大数的正负 117 | * 118 | * @return true:正,false,负 119 | */ 120 | bool TestSign() const {return sign;} 121 | 122 | /** 123 | * 清零 124 | */ 125 | void Clear(); 126 | 127 | /** 128 | * 产生随机大数 129 | * 130 | * @param digNum 二进制长度 131 | */ 132 | void Random(int digNum); 133 | 134 | /** 135 | * 产生小的随机大数(长度为digNum的1/4) 136 | * 137 | * @param digNum 二进制长度 138 | */ 139 | void Randomsmall(int digNum); 140 | 141 | /** 142 | * 判断大数的奇偶性 143 | * 144 | * return true:奇数,false:偶数 145 | */ 146 | bool IsOdd() const {return (data[0]&1);} 147 | 148 | /* 四则运算符 */ 149 | BigInt operator+ (const BigInt&) const; /* 加法 */ 150 | BigInt operator- (const BigInt&) const; /* 减法 */ 151 | BigInt operator- (const int&) const; 152 | BigInt operator* (const BigInt&) const; /* 乘法 */ 153 | BigInt operator* (const unsigned int&) const; 154 | BigInt operator% (const BigInt&) const; /* 取余 */ 155 | int operator% (const int&) const; 156 | 157 | /* 位运算符 */ 158 | BigInt operator/ (const BigInt&) const; /* 除法 */ 159 | BigInt operator& (const BigInt&) const; /* 位与 */ 160 | BigInt operator^ (const BigInt&) const; /* 异或 */ 161 | BigInt operator| (const BigInt&) const; /* 位或 */ 162 | 163 | /* 逻辑运算符 */ 164 | bool operator< (const BigInt&) const; /* 小于 */ 165 | bool operator> (const BigInt&) const; /* 大于 */ 166 | bool operator<= (const int&) const; /* 小于等于 */ 167 | bool operator== (const BigInt&) const; /* 等于 */ 168 | bool operator== (const int&) const; 169 | 170 | /** 171 | * 把大数输出到流 172 | * 173 | */ 174 | friend ostream& operator<< (ostream&, const BigInt&); 175 | 176 | /** 177 | * 模冪运算 n ^ p mod m 178 | * 179 | * @param [in] n 180 | * @param [in] p 181 | * @param [in] m 182 | * @return n ^ p mod m 结果 183 | */ 184 | static BigInt PowerMode (const BigInt& n, const BigInt& p, const BigInt& m); 185 | 186 | /** 187 | * 求两数的最大公约数 188 | * 189 | * @param [in] m 190 | * @param [in] n 191 | * @return m与n的最大公约数 192 | */ 193 | static BigInt Gcd(const BigInt& m,const BigInt& n); 194 | 195 | /** 196 | * 欧几里得算法 197 | * 198 | * @param [in] E 199 | * @param [in] A 200 | * @return gcd(E, A) 201 | */ 202 | static BigInt Euc(BigInt& E,BigInt& A); 203 | 204 | /** 205 | * 扩展欧几里得算法,求乘法模逆 206 | * 207 | * @param [in] a 208 | * @param [in] b 209 | * @param [out] x a mod b的乘法逆元 210 | * @param [out] y b mod a的乘法逆元 211 | * @return gcd(a, b) 212 | */ 213 | static BigInt ExtendedGcd(const BigInt& a, const BigInt& b, BigInt& x, BigInt& y); 214 | private: 215 | static const size_t _capacity = 128 + 1; 216 | unsigned int data[_capacity]; 217 | bool sign; 218 | /** 219 | * 将大数输出到输出流 220 | * 221 | * @param out 输出流 222 | */ 223 | void _output(ostream& out) const; 224 | 225 | int _hexCharToInt(char c); 226 | char _intToHexChar(int c); 227 | }; 228 | 229 | enum _STRING_TYPE { 230 | BIN_STRING = 2, 231 | HEX_STRING = 16, 232 | BYTE_STRING = 10 233 | }; 234 | 235 | #endif 236 | -------------------------------------------------------------------------------- /src/include/Key.h: -------------------------------------------------------------------------------- 1 | #ifndef KEY_H_ 2 | #define KEY_H_ 3 | 4 | #include "BigInt.h" 5 | #include "utils.h" 6 | 7 | class Key 8 | { 9 | private: 10 | int digNum; 11 | BigInt n, e, d; 12 | public: 13 | Key(): digNum(0) {}; 14 | Key(const BigInt& n, const BigInt& e, const BigInt& d): n(n), e(e), d(d) { 15 | LOGLN("Key: 载入密钥"); 16 | LOGLN(" 公钥e: " << e); 17 | LOGLN(" 公钥n: " << n); 18 | LOGLN(" 私钥d: " << d); 19 | }; 20 | Key(int digNum) { 21 | this->digNum = digNum; 22 | generate(digNum); 23 | } 24 | void getPublicKey(BigInt& N, BigInt& E) const; 25 | void getPrivateKey(BigInt& N, BigInt& D) const; 26 | void generate(int); 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/include/OAEP.h: -------------------------------------------------------------------------------- 1 | #ifndef OAEP_H_ 2 | #define OAEP_H_ 3 | 4 | #include "BigInt.h" 5 | #include "StringTrans.h" 6 | 7 | class OAEP 8 | { 9 | private: 10 | int K, M; 11 | 12 | /** 13 | * K-bits 转换成 M-bits 的单向函数 14 | * 15 | * @param cnt K-bits 16 | * return M-bits 17 | */ 18 | BigInt k_to_m(const BigInt& cnt); 19 | /** 20 | * M-bits 转换成 K-bits 的单向函数 21 | * 22 | * @param cnt M-bits 23 | * return K-bits 24 | */ 25 | BigInt m_to_k(const BigInt& cnt); 26 | public: 27 | /** 28 | * 构造函数 29 | * 30 | * @param k P1长度 31 | * @param m P2长度 32 | */ 33 | OAEP(int k = 16, int m = 32); 34 | 35 | /** 36 | * OEAP加密 37 | * 38 | * @param cnt 明文 39 | * return 密文 40 | */ 41 | BigInt encode(const BigInt& cnt); 42 | void encode(StringTrans& st); 43 | /** 44 | * OEAP解密 45 | * 46 | * @param cnt 密文 47 | * return 明文 48 | */ 49 | BigInt decode(const BigInt& cnt); 50 | void decode(StringTrans& st); 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/include/PrimeGen.h: -------------------------------------------------------------------------------- 1 | #ifndef PRIMEGEN_H_ 2 | #define PRIMEGEN_H_ 3 | 4 | #include "BigInt.h" 5 | 6 | /** 7 | * 生成素数 8 | * 9 | * @param digNum 位数 10 | * @return 素数 11 | */ 12 | BigInt GeneratePrime(int digNum); 13 | 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/include/RSA.h: -------------------------------------------------------------------------------- 1 | #ifndef RSA_H_ 2 | #define RSA_H_ 3 | 4 | #include "BigInt.h" 5 | #include "Key.h" 6 | #include "StringTrans.h" 7 | 8 | //通过getPublicKey把公钥取走,然后调用encrypt加密信息吧。 9 | class RSA 10 | { 11 | private: 12 | Key key; 13 | public: 14 | /** 15 | * 构造函数 16 | * 17 | * @param digNum 密钥长度 18 | * @param fast 是否采取快速生成素数 19 | */ 20 | RSA(int digNum = 512) : key(digNum / 2) {}; 21 | 22 | /** 23 | * 已知n, e, d 24 | * 25 | * @param key 26 | */ 27 | RSA(const Key& key) :key(key) {}; 28 | 29 | /** 30 | * 已知n, e, d 31 | * 32 | * @param N 33 | * @param E 34 | * @param D 35 | */ 36 | RSA(const BigInt& N, const BigInt& E, const BigInt& D): key(N, E, D) {} 37 | 38 | /** 39 | * 对消息进行加密 40 | * 41 | * @param [in] src 明文消息 42 | * @return 加密后的消息 43 | */ 44 | static BigInt encrypt(const BigInt& src, const BigInt& N, const BigInt& E); 45 | BigInt encrypt(const BigInt& src) const; 46 | static void encrypt(StringTrans& st, const BigInt& N, const BigInt& E); 47 | 48 | /** 49 | * 对消息进行解密 50 | * 51 | * @param [in] src 接收的加密消息 52 | * @return 明文 53 | */ 54 | static BigInt decrypt(const BigInt& src, const BigInt& N, const BigInt& D); 55 | BigInt decrypt(const BigInt& src) const; 56 | void decrypt(StringTrans& st); 57 | 58 | /** 59 | * 取公钥 60 | * 61 | * @param [out] N 62 | * @param [out] E 63 | */ 64 | void getPublicKey(BigInt& N, BigInt& E) const ; 65 | 66 | /** 67 | * 取私钥 68 | * 69 | * @param [out] N 70 | * @param [out] D 71 | */ 72 | void getPrivateKey(BigInt& N,BigInt& D) const ; 73 | 74 | }; 75 | #endif 76 | -------------------------------------------------------------------------------- /src/include/StringTrans.h: -------------------------------------------------------------------------------- 1 | #ifndef STRINGTRANS_H_ 2 | #define STRINGTRANS_H_ 3 | 4 | #include "BigInt.h" 5 | #include 6 | using namespace std; 7 | 8 | class StringTrans : public vector { 9 | private: 10 | /** 11 | * 对储存的str进行分段,每段BitLen长 12 | * 13 | */ 14 | void split(const string&); 15 | int BitLen; 16 | 17 | public: 18 | /** 19 | * 构造函数 20 | * 21 | * @param a 消息原文 22 | * @param b 每段的长度 23 | */ 24 | StringTrans(const string& a, int b); 25 | /** 26 | * 把它所有的分片重新组合成一个string 27 | * 28 | * @return 重新组合的string 29 | */ 30 | string toString(); 31 | string toHexString(); 32 | 33 | /** 34 | * 各种合并函数 35 | */ 36 | void push_back(const string&); 37 | void push_back(const BigInt&); 38 | StringTrans& operator+= (const string&); 39 | StringTrans& operator+= (const BigInt&); 40 | StringTrans& operator+= (const StringTrans&); 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/include/globalData.h: -------------------------------------------------------------------------------- 1 | #ifndef PRIMER_H_ 2 | #define PRIMER_H_ 3 | 4 | #include 5 | using namespace std; 6 | 7 | static int prime[669] = { 8 | 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 9 | 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 10 | 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 11 | 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 12 | 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 13 | 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 14 | 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 15 | 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 16 | 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 17 | 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 18 | 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 19 | 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 20 | 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 21 | 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 22 | 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 23 | 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 24 | 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 25 | 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 26 | 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 27 | 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 28 | 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 29 | 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 30 | 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 31 | 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 32 | 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 33 | 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 34 | 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 35 | 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 36 | 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 37 | 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 38 | 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 39 | 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 40 | 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 41 | 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 42 | 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 43 | 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 44 | 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 45 | 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 46 | 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 47 | 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 48 | 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 49 | 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 50 | 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 51 | 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 52 | 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 53 | 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 54 | 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 55 | 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 56 | 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 57 | 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 58 | 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 59 | 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 60 | 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 61 | 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 62 | 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 63 | 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 64 | 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 65 | 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 66 | 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 67 | 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 68 | 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 69 | 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 70 | 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 71 | 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 72 | 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 73 | 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 74 | 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 75 | }; 76 | #endif 77 | -------------------------------------------------------------------------------- /src/include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #define debug 1 5 | 6 | #include 7 | #include 8 | 9 | #if debug 10 | #define LOGLN(msg) std::cout << msg << std::endl 11 | #define LOG(msg) std::cout << msg << flush 12 | #else 13 | #define LOGLN(msg) 14 | #define LOG(msg) 15 | 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /密码学_实验报告.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphkwan/SimpleRSA/8bc122d4cd99cf70adc204f72f2d856fdd369c07/密码学_实验报告.doc --------------------------------------------------------------------------------