diff --git a/.github/workflow_metadata/pr_hash b/.github/workflow_metadata/pr_hash index 105a167..c0482ab 100644 --- a/.github/workflow_metadata/pr_hash +++ b/.github/workflow_metadata/pr_hash @@ -1 +1 @@ -a62d2ed013912136edb279a0e805b752fcee6aa58f2d4bf094bd42badde9f48c51cc0b27c58c00db7a6458e1dbfcdcfa \ No newline at end of file +41b06b124b04e583d0f040b825a4f769f1db7b6d2a1caf2820f12d656c293ba4572c81c43d3e77aa92679b7fe74cd3a1 \ No newline at end of file diff --git a/.github/workflow_metadata/pr_timestamp b/.github/workflow_metadata/pr_timestamp index bd410a5..ef7913a 100644 --- a/.github/workflow_metadata/pr_timestamp +++ b/.github/workflow_metadata/pr_timestamp @@ -1 +1 @@ -1734034065 \ No newline at end of file +1734046579 \ No newline at end of file diff --git a/src/mldsa_top/rtl/mldsa_ctrl.sv b/src/mldsa_top/rtl/mldsa_ctrl.sv index 2c75357..562ee0f 100644 --- a/src/mldsa_top/rtl/mldsa_ctrl.sv +++ b/src/mldsa_top/rtl/mldsa_ctrl.sv @@ -834,11 +834,10 @@ always_comb mldsa_privkey_lock = '0; end end end - - //concatenate OID and MSG to make msg prime - logic [MSG_NUM_DWORDS-1+4 : 0][DATA_WIDTH-1:0] msg_p_reg; - - always_comb msg_p_reg = {24'h0, msg_reg, PREHASH_OID, 8'h00, 8'h01}; + + //pure-MLDSA assuming 512-bit input msg and empty ctx + logic [MSG_NUM_DWORDS-1+1 : 0][DATA_WIDTH-1:0] msg_p_reg; + always_comb msg_p_reg = {16'h0, msg_reg, 8'h00, 8'h00}; always_comb rho_reg = verifying_process ? publickey_reg.enc.rho : privatekey_reg.enc.rho; diff --git a/src/mldsa_top/rtl/mldsa_seq_prim.sv b/src/mldsa_top/rtl/mldsa_seq_prim.sv index ddd3d2d..a9c9829 100644 --- a/src/mldsa_top/rtl/mldsa_seq_prim.sv +++ b/src/mldsa_top/rtl/mldsa_seq_prim.sv @@ -197,7 +197,7 @@ module mldsa_seq_prim MLDSA_SIGN_RND_S+ 2 : data_o_rom <= '{opcode:MLDSA_UOP_LFSR, imm:'h0000, length:'d00, operand1:MLDSA_NOP, operand2:MLDSA_NOP, operand3:MLDSA_NOP}; //μ ←H(tr||M,512) MLDSA_SIGN_S : data_o_rom <= '{opcode:MLDSA_UOP_LD_SHAKE256, imm:'h0000, length:'d64, operand1:MLDSA_TR_ID, operand2:MLDSA_NOP, operand3:MLDSA_NOP}; - MLDSA_SIGN_S+ 1 : data_o_rom <= '{opcode:MLDSA_UOP_SHAKE256, imm:'h0000, length:'d77, operand1:MLDSA_MSG_ID, operand2:MLDSA_NOP, operand3:MLDSA_DEST_MU_REG_ID}; + MLDSA_SIGN_S+ 1 : data_o_rom <= '{opcode:MLDSA_UOP_SHAKE256, imm:'h0000, length:'d66, operand1:MLDSA_MSG_ID, operand2:MLDSA_NOP, operand3:MLDSA_DEST_MU_REG_ID}; //ρ′=Keccak(K||rnd|| μ) MLDSA_SIGN_S+ 2 : data_o_rom <= '{opcode:MLDSA_UOP_LD_SHAKE256, imm:'h0000, length:'d32, operand1:MLDSA_K_ID, operand2:MLDSA_NOP, operand3:MLDSA_NOP}; MLDSA_SIGN_S+ 3 : data_o_rom <= '{opcode:MLDSA_UOP_LD_SHAKE256, imm:'h0000, length:'d32, operand1:MLDSA_SIGN_RND_ID, operand2:MLDSA_NOP, operand3:MLDSA_NOP}; @@ -339,7 +339,7 @@ module mldsa_seq_prim MLDSA_VERIFY_H_TR : data_o_rom <= '{opcode:MLDSA_UOP_SHAKE256, imm:'h0000, length:PUBKEY_NUM_BYTES, operand1:MLDSA_PK_REG_ID, operand2:MLDSA_NOP, operand3:MLDSA_DEST_TR_REG_ID}; //μ ←H(tr||M,512) MLDSA_VERIFY_H_MU : data_o_rom <= '{opcode:MLDSA_UOP_LD_SHAKE256, imm:'h0000, length:'d64, operand1:MLDSA_TR_ID, operand2:MLDSA_NOP, operand3:MLDSA_NOP}; - MLDSA_VERIFY_H_MU+ 1 : data_o_rom <= '{opcode:MLDSA_UOP_SHAKE256, imm:'h0000, length:'d77, operand1:MLDSA_MSG_ID, operand2:MLDSA_NOP, operand3:MLDSA_DEST_MU_REG_ID}; + MLDSA_VERIFY_H_MU+ 1 : data_o_rom <= '{opcode:MLDSA_UOP_SHAKE256, imm:'h0000, length:'d66, operand1:MLDSA_MSG_ID, operand2:MLDSA_NOP, operand3:MLDSA_DEST_MU_REG_ID}; //c ←SampleInBall(c˜1) MLDSA_VERIFY_MAKE_C : data_o_rom <= '{opcode:MLDSA_UOP_SIB, imm:'h0000, length:'d64, operand1:MLDSA_SIG_C_REG_ID, operand2:MLDSA_NOP, operand3:MLDSA_NOP}; //cˆ ←NTT(c) diff --git a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/signing_output.hex b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/signing_output.hex index 5c28e28..4766438 100644 --- a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/signing_output.hex +++ b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/signing_output.hex @@ -1,3 +1,3 @@ 01 -00001260 -AE57D1C40C0BDC22B2E521CA19C616063993A8013D8D2311D74AB6747A8A37F25683B6757900850E38F6B30CA0167FCC2A6431195AA244018D4FD9A86FD54A71765B6F2D4121D0591F99C28F12ADE0CC6682FBE38FD8CE53D735E013EF8F52B540D76FB6E5FA39FD0C202FE5F5E3D893A2C4EC7A4B2256DE91F8856335556AEBEADEAB1274881F799434ACCA3FBCBEB95DF8FC95CEA3DDBD75B5C8BF9CBF7A7CEC74EA242745CFE42FA3BBFA7616477184075A2C57B4D56852FB32CED0F92659966B8398D95131221561DFC2059C78B798DEF17C4C343BEF9AAF30B1A454E28D9E034A1483D0B675D95935B0FC38BB28B9676EC1FF779C68B32C6E51A62573D31EE7B9D5F450BE55165845FA9A5E52D5AD476E4B3FA8108692649171A62918B1B04CCCC2E02721E2821775ADA29AD242233118B795AD9E80208FEB9F1DC81FDB942896E3A2C595A8158479353AC22ABFE94AB0EB8514DCD910007B29A51FCF323CA3B03C5862C8A4E2AB30A2F4B0DC1BA6F7B1E93EF635BBBD5FA0B2C2186FD16D63A09F8F49BC74C4EA59818C4E5A5D8F0B224B29E57BE261EA7ED14DDEB9ED013B02AE0E17F0C2AE25267A22090B4FEA10F791C59E5ABCBD90301E22DEF0A2B33DFCC5D7582379EBC420129A93356CC5AEE6CD01E355317DC3A6CF64D2ECCC7E85AD008C2D0B93E08081910BF5D4B7F0A8568BF684F8C2887783DF690818FE02A7B872FD0F9216C93CBA079650A2F589FE6E1BE5B8D6C0FF9052A0A96FE42F427CD5F70B4D765C9D806E8EA7B5E6F5B53FA5E79E4155225D342CB15D1615936ADDCABD5E44C6A598C90F350F6E6F0A31FFD59309D81B4F4E2C12B214E3AAB5029E7A037BED2C7B3561EE2D298F46D6FE5992CE3A3BEEEE9DF709E0F76090B6C49C01C4C168C16B263B53535AF60969E8778114FCC2949752B337E5907280535354C26C5F22AAED80788087A5FD8C09CAA0C75B2BF7EE78E021E91C76773BC17A6925AE424B8564873DD24F632C00AD9BD96735D7299FAE1A6845476A6DD7CB0B0D9C0E0CC522E9A24BED4C257A5EEC3D8BDAED29BA8C004ADBE2125DDF27CAB871784232F923C8A130273263FA6B2E2E79CD1DD448FCC9602DE126CD6CB0CE591CF313106B93FF866E90947584F6FF4A37EBA85D8BFB3D4DAE1FB77B751FDD0440267082252007F908C69FFBCD4AD3D71693DC2CF16B5FAA7AA127686110585A17279A9542390FDE4F939925F8983862A2B855A2541B7A12A159D2136A90EB7A7567FCB11FA0E09D1B7C4B81A85C9EB9E5ECBE2A6F1AB5A035436807E5BF728D3A373289D4ACC80D124B3A9DE3E875BD894F9138BE5BFB8A3EC7F13ECAB3C11509F60AEF86B13DD91CFC3E68530B261F9A37B1DE877437A6D112005A26643596470BACA2659E4538F392207C62CFDD2B9B54892B861861A82665BB0DF229AAD6AEF63866442F33C2F70103459862D0222EB0A40ACFFDC6FE38B8B48465E1EDDB4F41D1EEFDE3FC2ED8CB6FD0273286CB21C8A159FA7B4677810D2AE12DDF3A77E717A1CA39B3B99DA32D2B4213E49CBF30803FDEF08BC3187D95DCF15B0531E28BBB73C21DD3233F36010F9CF6C9751F798B02C0FF7792099289E6ADA8121E6BDCCEC81FA9C057019A412A66E5D9908524AB11855F7BC963C8D3C3A37E898A7105EE6F866A7EDE1FD0D34A000976326A57D63CB3DF28A2313C3D9BAF713096AEAA5E3D5866F970F029E1932A95EE853A799231089C5EDC1C30168DF2F09D843B4185F5F7AA56E35BA0734C89DD919F788A30F4322ABB33251ACACA8F29C0AA53E702753399A1025626CA0FB6FFBC89B070C5C0E1D65D2AE16928B72A4811B973CDBFD5D97A418C10B16215F59CAB301BC248AE1DBA5ADC91F294CD9E26023AF54DBCE02F259934DF4EBE17D80314767F5643DB45E8F322ABD71DCFC55F4218E156221CC8C5C302B34B893909D87D2CB3C5E8725EC204C7ACCA92C9B4378153BAE4D4E1C1B2A4775ABCD2B3F086D4561302D90E98BB0F4F2B90016E090AA7ADFF084B03409CD465806140572DEEC45C238BB5AD46E5740048FDD616A603536A46CC5CEA0A6F46331835EF143B9A9287DF8A7EC9D501846B412203946B98FD40F603995E9A0FFA5815AFA50918714BEA056D00602E2DA2F3A2D5A1CDAD4725A76708194FBA81E9C6F66DEB7C8AC1381358CE766DAF364706FE6030ECADDE15D689AEFC0D74CBB403E8B93B081D8CA8A7ACE6C92C058BD4E767B6F1CE79DB8649A0000DD4F18BF277A39564FCEC7F28587309A6186232E22CCFF611F56473C9BD7CB8B93BD0185D8FE94C9E43DC7B0C70EC41483EADEEBE2FDE60725ACD9A4DCB65413B36BC1400D91D994C3B365C8AF568CC8C6C56828E9528233ED074AB3D57C396B86F23F62C0B30A09B0A7E1FB772499540B27838F37778249B75AF4E73310023FCAF36905D64D7CB265EA3D1BB58EAD5E4A443B55D43B94FC4A14AC9A30D42A47E37583E96367F3A4280AEF01F30EB70C46431ED729C5464FAAE577EE3BB9492D36345BC9F0D2C5F83D1A9F6CE6FE478E35C637014B9136D07231CD51D56D5C9F2AB3F4F277FCFBF2CCD226F8F0A58ED8D9356FEA490BDBCBC63CB91D7C96B0F456DA4131ACE7638E5CF0F24C374CF8291B75DC43A1F9CC705E90424774391B125EFC529C3AF6497ED4A4B939657D290B1554792580C1C895F554AD26942ED53C7C16C6D826E8C263D1A3F33FB3B7DB728EDCC20483E5C50D90D4CE697671E4092EB38AFF043A45B541510998597E419E1ECB090EBA9AF804A3FC778D73585DF9AE3B46F6421DF373B6AF735F1AFEC1EEB01661DB91C6B79660F29552B199372ECBB864E6EB5F16C71A6791918FEA4EA4A26204E867C26D16E138E6505523AC84D72393051C744C9D1BE927AD18E851273181890F8B32E086D74142C36A847E736C927280AE0C47C2720B8B0ADF557832AFDABCA80AD4DE8B0A79E41684C7C53F88C0A22FE0BCEBFE19BD657BC4251F870712D366C8D0306C1CA915154C6B6B82C1AAF941C489A1B7563702A8F7DBC287BB778F685D2055C9971CB0DDB529B0F4B5C8FC417D8579F26AA0C56B4583C3D11ACC3CD18B48ADE45FA09243907D3FE2B059F7F40F432613644A394F44977267D2EA2DFE56088B276CF5C9F364E30C2C71D78A8358EE3A5D8E99C9778742836D8BA2FB6642F244C68BBE2ED2B4855418BCBE122FEFA31D8575BFC5C98F9A8D3F01A28B1D50B1DD408C15205C57620DD623FC999EE8D1C02A3463EAE84C72B356B05CBF1634AFB247DF9FC3145E5D543B056D4C63E466903773B0AB794ED5E3BAD87611D5737D30426BA1CF76CA96209059FC2C8055C0894FECEF0B7526E1CA233B4D57B0F487447386EE83CF0DB5100BC1C161CF7D7E501681D5FAFA0DFF94535566CA0FAD9911B69DBDB33FB08ABB35D1F7DA09D5986BFE914C104FDBB9B53B41FF1935646F5F80AAE3B617130EEC2DB8A70E3BF1D11EF7D4A38DF4DCA74454BEC6B20A05B0A088B89B3FBF2CF7454D94465281263D4D2E01AF1D405189718155474DBE7EC64F92464F2F2E16686686EA01448DDFCFF053279EE27C0D840F430274D1E5C0FD16E4B6AA880E8971008140C7D3B63EEB4D4DEAF3F56768186C2C37AB0BF1FCCD2512156B6EA224C1F8A70FD6EBC77AFF4885AC5ED05DBD832E7792DB86BFC4546BEC3113B862A826812C06A827E3F034DC61ECF72740C438B55DC62F7E641B34FC5685574FD7A906984862128919D27091F06436DE302A05C22DC4882362F2F7737CCEF0E159EF34B307EAB62566E6165D6FFB1DC7E68702B32258D5EB2DE89F5F324D98079CEAA46C4FFCF61ED5A8881BA7C62F1F7B225C484C7505614A592EF3D32E883F9E71D398B4C63759ED6FC11CF38CD41373E0996875ADE0B48EAB4C750B9CEF7E9BAD217315F48E103DF380C32C950B1799F70B123854B763D97C60034BB34F5AA7699B07E3BCF99441586821447E48D582C3FE5E8206CBC439499ABAFC69BB0C884E2726A1878CE83EAE8BE5F3613155A398D4FCE09AF52A7DC0F09C88DAF3AD0F7236DA2BDB969D31D42B853725A34D6E4A4D67A7C1A1A95C1541F8E467CC35AF312FD1EC518C0D9A6D56EBD54F6453920C2026F9459CA0849EE62278E71F2B5DF57523790DE5DF1253C6C421FB11749FD73E557B77A67C4B9FDF79A441CA359C5C499526C122B33A2C2EB29387B33EF4E125CF7AB2423414933557B6DF4005F4BF60CE22FAFE031FEB450E5CCE7033D16BA9B2C47A63D60972BB7CB00B28E04CBDA578CC3D09556C092070373858E9969C4319952B71DDFAF0B4CC768F9129223F6B493E61292DD3EFC788747F7C6B0D9006B86C3AFC0DBE21DDDBEB385E568354B636E8C20ED17992FF016AC495DCD1BB387E31BAD5A3E9DDAC565D1EFAFE533AB661D20351FE85FE35AC5809A3D493C672D29F890C22C40392C9002B30BB478644F1CD6D3378B53747C6DA11E54237395AE64A7B54F9639DD1AF96E8798F665FC6C6DBBD4B865AA83CECA818BA9139F047C1F9BCD3932A6CF31EA0DEBA1AB1A86E9D5C3D1BC71FBB09476AE630BB8EB47814A83791547E3397F1944D05B754BB352A55CDCD582936DD8565EA42E2A010007519B88A0CA17E4C57EA2820D1833C37684A63B9519DF9465A8A6A15B8E80FC9119A9DE135CFB02770F3B6F7EAE0B69763D3855CA13E87659F2B3911B7A32307A9A232A5C1FB15B905E672E55FDC3C2C61137F37648B31D8612E61461FD474D4448FF3AB1C2E0E782EFAB358949CFA96DCB2C25EC173D75FED30CFE49AB44F01151713D10ACC8374368B0FEBECDF937941DC26724B5007330C77C0944FD48E6C4269AAC25513D22EA7AEAE8E94E3F4E73A5D632C8B89155478295EEDAFA26AE4FD34963B9FC80A347C2B8346012A9C6D95AF2BD0793899A82E40F66BB0EBAFB9967A464144B6E16E591E01C4DCC1FD7A8165ED755118D6823ECE467E28D1A571AC0541C0BF952C88C500954F685C4DFB31EB105DB9B12428E1A5DD42B6658B646A8103D9E137E8493861458117FCB2270B598F6697F4DAD3607523EFF54F980F54E4E791042FF6BC0BF077D3057C6A101E7EC1EAF8A25DBE420F078BA8E44C1CC78E0176FEA402F81FD572CC075E3AA52A911284A301C746520535726729F9928D4402AA37DC5B10B40DBE7C01E4272D9122D19ED7B41441F1402C1B81B16122F2F8048C57EE779DD145D3D20DE060E0929E49DEAA873F1198B99BDD8D50970F0B899E46DBB10D4AAE3F742EC62F0DB5168947307BFF2371CCAAA7036DBDF1AC9BE8F1DF27461FC5649B9E6C3AEAD67A6539B7843E3B22C17B70B96911A9E05894ECCC0A7D6C30016DD49EBA6C0A3F923E3A547C1E024AB2BD0256B7535608B25503641239B029C87016D78BA4E2686E0DCD97592EEBED209FA420D1C1BD42E99066B587F5370166934936AFDAE6F17EA39481F415F49AC65542C4D2FA14E11062133A682A8C66A4B1DAF43326C295BBA45F5CFAD64A1A0C97981E320C528D0F428921275A675B0F6D4413A00982ADD633240FF2B9B3F2811B00C6EC3870EECC933234EA128D73543FA4458EBE03855C09D591F23A666B4B9D79E31838D26321FA1A3E87813A9130492BB143D19B18AD61FED31E7E5754FD5DFACA22BA2F7F9B5986049497EC46527BFA8614D3E29CCEC3DA2A0B586FBBAFDB5442E60398F167DF4F47FE27691AB5BCAF84E8B07DD77A16782B6CFEE2543BC1CFC357FACF89E0AD547FE0EC2CA49D007CFB35B9818BE721D46C8683268422D37BEE9DC8D3B75E906F69B4C6C929318765043C84919347396E490BF839576EFDCE049FCD984350C8CC48418FA5FBEDEE7AD9A28C53FD88D849248FA23E4BD9927B083E3EA7C7DFD08F3BA9CE88D4B17BCCD286F6C82A8136E20B2F0FF8A71F18810CFF873E5EE3CE067FFB1EAC34332D226B1EEF78C081077152A84AC1A5540DC8BBFAD7BED3C7E42C2F55650FA407910AEB29C80F7D0EABEDD3A9BCF3687AA45F567638D6B61B0B6B0482A021177E70075F96A11D058B8154708CE5FBF9CF2F544F8482D0DE70E89FF7FB389ACFAA305F2999D36CB9A534CE22C77601962C6310A9B85521ACA7738BCFEB4E6AC6A1358F6C011F2CDD0DCE07ED3AAC4DF5027867DAA99DF3997CBBC964D27A135847533D3DDFA38BBDBA39EC1B88A1D99315A4FA8DA04F1BBAB6864F35E3DB57CCC7983B148F2C034FD8A6F61C54448EC516A83FB3742BFB6A7D43EF186FC5A1FD44B9282ADF5839DA760AB95947D02D8712E057EAF19A4FD34D7EF3EDDBDFB8F80A3AF4D6AD3EF283F0A2EEF69D1F5C33EF0CA5EC92A29E5B6C90FA6F6AF1A207A2ABF77942565347306988223A454CEE89F14185069A89263C394CE93C042648D2788E813EAEAAF01393E66D22C6A72D7D9E1F803A9AB37495D6A749497BF232836757D879DA6B5EC0E395D728FEAFBFE264774AAEE0F1F2C5A6276000000000000000000000000000000000000000000000000040B0E1620282D33 +00001255 +38796E20B090704AA24C32C0C124A7DEF5F130609930B6E1AED360E513B596E661776CF8976D08F52605680DEF3C4EBDB95740C59650522ACB3CD56303D4D823E0C4BD7493B3B27047885BA8CFD93B4D71C0B9B300F56557C665ED9C953E894B02FE79219D32DBAF5AE4DBBADA3CBF2861EF00C40075142DE7552DFD76C76F18997884A8F00B9B6DCDB234C162000C37AFFD2D346128F84204DD5AF3612D45C0EBDCCF49C5F02ABF5E984AAF164A08E150F75A19C1BF0F64A70903B07254161BEE6742DF447DF312E408B7F00E6CA547280866574F050E0F8CA05E16F1001BDF6C5877D088B919D5754F2B4DC7BACCEA22431065A58F221F616CFB33289129C8891FB590D76E15DD76A94163B20B9D8DF203A1A6FF451E95E7B06936704DEB768F6A4FC95A333665064DB55D0CD5B28FD844C249D1DA5423F3F31665F42676BE1BF123C9A8BB26C76ADDFC6E8B66A940FF88283129BAB039EF285F1CEFA91C11178CCF37599D3857AEFA3D6D8B8F1C806D3154FC1D8995AFCCBC73EA0AE540726411A18CD0297201139A7F182D84FACA6DCE99D48C7A84BF5BFB3352E0B16943D96C5F758FA8AA111D8F3CD25CEA8D0B232BAF70FB8547728BA0E19BCB9A75509F4892B7826B3AEEABC56F3A45EF2B7A4F6BBDFA052EB1A7204BB59C9D4A3777E4D5EBEB1F7AF263E3614794A0E66250884BF9CFB777522398DA1B9C709C33F06E8C5E108D30218C199C5B097C823837A99AC786074052668C8A4B5AF0152AE4D92FE4E98C91F7D318AE67F482CBD19BB70AFC290B90ED5B630387410596BFC754764C81AFFB5931AE0A85E41E1DC950E65CA22D272B58CEEDBC6DE6635ED6C85B05A699DE77B6B921B6DC281A914159E26C77F84F7636D0A3D9B90E8965949CF1A04EA6D36838CD54530D1E9953442BEF130B25CBB733B43A324ED5898B0C8F8EF5C71FF164D5F37B2219E2CC3618DF2CEA8449C95BB3261C350E6BA81E7B72E6D46740DFC331CDB78D3074F79DCEED70BEF2B0467A73137058795AA933ED60E00AB9105ECE16193839EC4534012A2DB5910970E0BCECF04085D622EB92BBAAFE2A888E1B2F4E381E58518F7AD10445E21E40829ED18D61DE3856812D5AAF963F058C1203BD6D73B933518BB4A44DB2154E10C0B07830FA07E20001857D46D3CB541061EC6CBBDABA1731574B3A140E1CC1F3EF88AE1D78FE7E80A6565FAC737FA1E0A70BE706250C93DC1BAFD46BA50CFE07A3DDB8CAC3943BEC70044D9D374EA8D8C3634FA270A6701DD69C251A7229A0F37F49649195252E9B74D03B6256565E26BF484FAF02181D6457BE6F615FF54E21356B36E119DFAB1673984A31A47365F766C9C4229EEA10B483B219AEE164162A54F3A9D7A474D8C8AD1A2D82B95F42E88E6EE7B67C2D103A1E939D4377A59FA56673DC1F0EF642B3B7541ACA2D21AAE4044E53B29C04C16D510575C2D5F104BDBA6D3102DD46589E690C34DB73245D0A299DF65974BF462FC35B58A6465518988F5E2D3C2B5C60C728C0F21E311228A7AE2F7481C9EC12183FFBD2314BC065BE9E5A7ABCA9627E9360EC13AA078953FFE49C981E29D9FC0117929BC51056CE6F9E3CD6D65877C95A6C7B6E4BD0B2BAD131DF0477645FCEDA0E5328638D094F618FF61932B7B2ECC280D26C9BB72AAEF2B34E55A2527A34E76406AD6917C95085A228CD7EF3DC63FEF65CE8A33B1B4BF784D008686B6471D0E9E699CA6E589DBB666D6C11B608B3F4030FCDD476F381CE03FE12DCBA93E2AF7BEF259BB86BC39AE969BEACCED93FACFD3707C5DCBE449245F6E2E0D0E689CF5B534C9EAAC4F083A38B5F869E025290C07DA6AB972158A1A07F2A1BE774848D05A1B7DB112CFEFD66CC91911DB54906557DC52036685F76B2BE5557D14E1B58C7A962F7A8706787F726076FFAB03997E438DBAFDC5FC38E1BBACA4533694069371FBEFA4E271AE66B876020C3C7543FB2BAFA40FBB08125EFB057FF3E14E253F3949745AD6AC708B87B598B9A28020FFD44A243661D0DF1B2F26E047B55BF1E502B5DDC5EFBFED7E18084D0E9DB9AE1E55B40212C4001D5B19BC93BC74CEE4BE3DDFC54E58BD56B40EC4A1E8DB3AE7C2CB982A47E147334868BD5AB4FCFF96389D90B0CA78A23C6CDF71CD155D2E2D20B7A7F21544475A4C10A90F304A174CABFF35450DC5185D505C45BBB034CC010AD2306909473C51ECC4F87019CF66959D07C83B4E6C29F946D8399E5E2BC4BD5B959BD29B87B82872514B0C8F86997C2BF78DA0E9BD6AC12F7109D2F05339FCE83C0A528A6894574D99EC76CA5F38C4E1A1E7FEF0110EA2B86F29BA2463448502BD725A90780F8F20C4DEAC5FBFD93BC48B4ADE4C814012BAF6C3EE604462F5B710D07D3FF86884D7BBFD755CBF136F2E51E693D205F1CA1FAE7C69932CBE89AA2706842B23271AB38A2639871B025D234B498EE34C04436670B2640471A3ADC444DD3ED165CD0DBCD0A22F5B34461E2BD6F0D13AA7408FDFFD5CE7F28DF3DC4CC44C5A5A33076125F78CBF5390C0829A83FCD10A7A73A56D94689BBDF3269E7F82085087B86E6F4AC449903C4CE7FC0948EF0EA57AE339F1A60EE0A299DF503561677C00F49ED61EBDC96670290DBC8C8EEE3D8B71C1EB0E49B95913739C8EE2049900610EE8FED70EE6B5D99FA11C5DA2B7336FA095B98BBD1E8545D1B4F35C73F4B5B501AFD2970BFC33078F66F4E86837BBEE43D3831065BFC889BE93CDCE21709DCD0A833D8C9A97E068EB4C7727499A7883C7A961555E64C6F6E2E2A577593C28A7D2F80F5C1230A74F3B1EBBB8380A8A185E7FD44F760C387C2BEA509A9E86C308F115F422D02A456E5261E3163745E3D22367ABC9F9BF1E6C75C1C7D271F568F06A344DF1BD84551FADCDBDE55DFE14743FFD36C8E071E0B85B6514A1F7780EF562D0DCE25AF095F7AA867A1B73CA9F6BEB2097DDD696D44CF4E645DEE67D159960C3AE7B8A587866C71F304E06451CCC62DA4C389B041369D6F58CB4C47E4E887475A6D84711A034C6D7EFA988C7A11E2E919CABF01AA2FA9D6216CD4A7F22FE692FFE1DB53E4CE1B5A7AEA2525E8F88B05D1297B5D435352D92A66035DB97FC06D1C74540A487DD48AF1BB462312A0EFBCE06B7317CC201EF86D48387421575294EA33282E65DD8D1BC87F575AB0E8FB92ED251D3D559A7ABAABD7D83F6E97189AC79D031449725B1F887070C02F9882073AFA471DA18DD15B4773A915AE3E23C8E70FAC216217928625D47D35EBE7C487432AD36DB44A1283D75616AB65E18CC3C4724882062FD50D8FA09DF41280304323330473322DC97233ED27461FFA436B6D194BC2F531454B3B80BBC4DC768F77FDEEB7D4E5D8AE6D97FAD09556799996D820990FAE21C3F2A91C2FD35D71BF0BC8AA26F00107EA708606D973C649C50AA0E09F082051C0AD5926567C512DF7971745E1CBB78CF8EE3EC075EFDDF9E53A060FF4CC4CE2A961630E46C8414074A2A5F92CE1BF236D0FEA264EA495DA9B925A62CA1E876D76E03B522B118F021BA817C2B624AF63EDED7AD7A48D30F9AD785AB30016AC34AF8F0D5FA057CA341E3D2A9B94F2C3CAACE30AE3A856DCF17BB43F8634915F3A2CCFEADEF07EB9B719D4509DB18CC10868EB4DDC7AFCC5536E009C1EE6EBF2BA8B1F60E3190E2F881C4DDC271E2E993246941B36C548092BCA953EA9CB946AAD1DE5A27B912DF856C09F2B4F4F658743C2629B1684B68A465E318A896A6E8FE4395058A26C95AFA6C46990A6B577FB41DF7ED8ED433663BD792B65308C921C5BD450C6253ECB33F4397DB7419BEADEB409D1D5FD9AE1AEAEC6AE31221002209076BBFE67F915F78B939133715493B32B97D5CA6D8C7C944346FD0F89058B35873EC808CA75C100A51C38010B6062B44C48EECFE49EA82943B94A812E9532753BE035F138ED92226D82F77CD18D945CB13F266198F511799865FE92D8B7BAA4D9CD6EABDC5E97B14962B86603F455E7EF457EAF9EA41323B4B0A7A93BC29520FC908C034AE3D660ED914F383C2F8F98534E536FA4ACA7C2B1A719D581D9C269837893C130FF3EAD5C98BA7B12D0BEECFC02FE6A8213FAEEBCB3B0376667B313FC62C831BAE913DE0BCE877881BB8060601700BE7853DDE98C121780F37D8C0C4A647F667A0E107E0DD6623D0B6533F1ED50450A9669D24F0A47FF3D532F846D7B2034E214B3B37C6EE1F36E9389837E0CB8CCB84970FC2A01AA189944E2DB2620E92B39DF0F2006F8F379C60CE38B88ADB3F14F6F6B216444FB0C63160EC03B397F552BDD3CA971066A6974E08F4BD4B60D219AE64EE1340752B5525E7133FF8F21803E77FA78C291FABF65D0ED54BBAEE1F0EFE6760C10BE545C405CBC597456FFCE829E0066AE53052CE56A7379E8B838A4A837A791A9798AE7F331F8E5C80B5EEAAA1127046D32A64AC23685EBA4F11335E1AB41AEE81B39A7B2A6741BD66CC40826F08ABC5EB5138E64D42F76BD641DCC5A46ED65D50AF5D7021DEFE796D71A8A7FFC01F889FC595734E0E07D6A24B2F36C28B70A08FFD9269A56ACF1B88F0C12ED0BC26733D9F78267D6AC77BD5A57F4D631DA8B9D73374230A8A9237A532F617EDE49AA4D00393B4D6874DD2D8B92D42C032B0ECB2326A77CEA9C02C0DABEB6C78242701561F5415674E6CD96C2EDD0E96EBA22A12EAD6502BE87B902A9988015EE0E675412600C7E4571A5C745E024295DE17427D9A69A355F176DCDE2C5BFDB1B548EAE6DFD8FA2E2A50CBFA90DFB69E0C939FC969DF9A501BBF7AB51017E7CC2B2752A3913451FE2CC061B0C9A95464A281E21976AC7287A431DAD74E287A3FEFD21978A75D9ACB35A9D10F54DAD84BEBF5A7A65F7F9419FD7E9101A04080D448701CDAA0D04413D1095CE33D39435C14A9798CEFF5C9FB8A9FB460C14157A28FA0F2BCE96E08A194CB27B656251AE24531DF2CF182B9009E104663DEF45AA9B3060922210FB531FCCE4137020CEB7C6E469DEECCC55FC04C822A7151F3B054F2CF33B052A1856FC31B6B90C4865D0CCC40806B2E8DC70334E86F285049F9836B414C406800DFF77B239C1F9DB0595639777E2581A5246158A50654F0C62911220A88C212F02EDE91161FD1DBC5269F6E6169BB57E5790EC1C4CDB21DA2D2F2C0BCB8EEC8BD349F128969E11B840D1947BAA65C79D8FBACB0D6FAA59FAF094DEF2F751F4F3E519A7D2AC8E5A3FE25E684648B3F6376C655EE912F19700AC3A0BE51A93D56EA67AC21D0BF6424DC2BE720AC23003A503BBE1FB5A0CEABADF7B26B71988A1403F3858247CBA9979ED4852EE31A156939ADD80574A1A230FD8812489D93D890DA7BA16900FD4DD51DC223AC82BCEBB52841A58E389608CFD01202132D35B846581BAF761DE5BE422FC6CE265FEAB725172D9D9E0545EBBBDF4C724F73217954EA64B522E08680EBE34F8B5AB163B798F5FFFD23C3F73F2B18F0D766084E6F4D830658867A7CB6909E055EFA391BA69B163246DCCBC96C38AB830E18D54CB1F54998082AA6A46C88AC43277DE95035BAE901A81AEB4DCCB41F93CDB9DC080396E9EF8A3A36A8ECD57CE8415972ECA84FA3715B9C0F5046F91C486B81ACB1544E7365AA7A248125A0B3A06E24EE55643F9FB9F6F9E99868E862E8810A6F5A6C25F7AEBA8EA1C1C8BEFD723ADE25D8C51E48912F05122FB54D91A196D41CADD54CFF5C41E9125CF3EEE2702D914C39449E6CB50138513F86A69B5D8FA6977F16AD026A1101BDBBA2A4D07ED50B2EC16CB12AD0544A4C09336637DA9DCF36C292850D229943ACE2FFC65C415C595CFE261335016C5F8B4F6FE11B9A8A396C7D352555353A3ACE365EDC9902D5D192267401FBE41FFC75912DE0B295BC49641BB96E92C10B451733893DE9C79F1B64810734B473631DA5649A90F4B878803AAD72D2A83C49E8A5B0815369F06F077A9F946EBF74918EE0D0433F3D0EBEAA987A1C97260BB7F35495501E62A5EF664E9D745C1804E5961542599EA43389203C539DD77F93909A3C7DE272A0F9D325B99E59B505F5DC8E409712E928A6F7962E728D466E5D42375891DEB0741298F1ED874B853E9FCA68F5562F9C5399BA5F59F43DC628D1C90FB7ECD60EB771FAD4A81A464A552CE62F1D8D05D990E9A9FCF787DDFB13010466A1B42ABED02E2F81DD66013C43744EB670BC6EC0740AA75925F2BC3C24B9F8A28FBD8AA5A8B5FFF106E0DD2B9BEAE5E01C4B725F1EB22ECDE0163B28E7CDF3B6CAA75B7772EF74D02603AC2BA16971EC69F96ECDC811BF0E7D4AF47ED133EAEB24FE1B93EC6C6FF85CD0E4CCC4332182260B8399997096A061748FEDA6C4B74C77DD74FE329A9547335D0F61264C8E2AF163296645C5F31851597CD034DC431DC0AAC0C3558E941ADA82A70CA246FD1191D989DC9CBD1DCEF334B82A0AEDCE2FD45475EC4F50E5F628CBABEDDF6102B809BD6ED242D3241C6CBDEE43157879CB6BC00000000000000000000000000000000000000000000030C141921272F35 diff --git a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium.c b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium.c index d3e78b6..f4b45a5 100644 --- a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium.c +++ b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium.c @@ -11,9 +11,19 @@ #define MLEN 65536 #define M_PRIME 1 +#ifndef PREHASH + #define PREHASH 0 +#endif + #define PHM_SIZE 64 // 512 bits = 64 bytes -#define OID_SIZE 11 // Size of OID (in bytes) -#define M_SIZE (2 + OID_SIZE + PHM_SIZE) // Size of final message M' + +#if PREHASH == 1 + #define OID_SIZE 11 // Size of OID (in bytes) + #define M_SIZE (2 + OID_SIZE + PHM_SIZE) // Size of final message M' +#else + #define M_SIZE (2 + PHM_SIZE) // Size of final message M' +#endif + // Function prototypes uint8_t hexCharToInt(char c); uint8_t hexStringToByte(const char* str); @@ -29,16 +39,28 @@ void create_message_prime(uint8_t *PHM, uint8_t *M_prime); const uint8_t rnd[32] = {0}; void create_message_prime(uint8_t *PHM, uint8_t *M_prime) { - // Step 1: Initialize M_prime with required sizes - M_prime[0] = 0x01; - M_prime[1] = 0x00; - - // Step 2: Add OID (0x0609608648016503040203) - uint8_t OID[OID_SIZE] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}; - memcpy(M_prime + 2, OID, OID_SIZE); - - // Step 3: Add 512-bit (64-byte) PHM - memcpy(M_prime + 2 + OID_SIZE, PHM, PHM_SIZE); + #if PREHASH == 1 + // pre-hash MLDSA + // Step 1: Initialize M_prime with required sizes + M_prime[0] = 0x01; + M_prime[1] = 0x00; + + // Step 2: Add OID (0x0609608648016503040203) + uint8_t OID[OID_SIZE] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}; + memcpy(M_prime + 2, OID, OID_SIZE); + + // Step 3: Add 512-bit (64-byte) PHM + memcpy(M_prime + 2 + OID_SIZE, PHM, PHM_SIZE); + + #else + // pure MLDSA + // Step 1: Initialize M_prime with required sizes + M_prime[0] = 0x00; + M_prime[1] = 0x00; + + // Step 2: Add 512-bit (64-byte) PHM + memcpy(M_prime + 2, PHM, PHM_SIZE); + #endif } diff --git a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium5 b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium5 index 2fac5b8..ae8ed65 100755 Binary files a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium5 and b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium5 differ diff --git a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium5_debug b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium5_debug index 53ecc5d..6d11d40 100755 Binary files a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium5_debug and b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/test_dilithium5_debug differ diff --git a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/verif_input.hex b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/verif_input.hex index 90f4b5c..e9ab93d 100644 --- a/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/verif_input.hex +++ b/src/mldsa_top/uvmf/Dilithium_ref/dilithium/ref/test/verif_input.hex @@ -1,3 +1,3 @@ 02 -AE57D1C40C0BDC22B2E521CA19C616063993A8013D8D2311D74AB6747A8A37F25683B6757900850E38F6B30CA0167FCC2A6431195AA244018D4FD9A86FD54A71765B6F2D4121D0591F99C28F12ADE0CC6682FBE38FD8CE53D735E013EF8F52B540D76FB6E5FA39FD0C202FE5F5E3D893A2C4EC7A4B2256DE91F8856335556AEBEADEAB1274881F799434ACCA3FBCBEB95DF8FC95CEA3DDBD75B5C8BF9CBF7A7CEC74EA242745CFE42FA3BBFA7616477184075A2C57B4D56852FB32CED0F92659966B8398D95131221561DFC2059C78B798DEF17C4C343BEF9AAF30B1A454E28D9E034A1483D0B675D95935B0FC38BB28B9676EC1FF779C68B32C6E51A62573D31EE7B9D5F450BE55165845FA9A5E52D5AD476E4B3FA8108692649171A62918B1B04CCCC2E02721E2821775ADA29AD242233118B795AD9E80208FEB9F1DC81FDB942896E3A2C595A8158479353AC22ABFE94AB0EB8514DCD910007B29A51FCF323CA3B03C5862C8A4E2AB30A2F4B0DC1BA6F7B1E93EF635BBBD5FA0B2C2186FD16D63A09F8F49BC74C4EA59818C4E5A5D8F0B224B29E57BE261EA7ED14DDEB9ED013B02AE0E17F0C2AE25267A22090B4FEA10F791C59E5ABCBD90301E22DEF0A2B33DFCC5D7582379EBC420129A93356CC5AEE6CD01E355317DC3A6CF64D2ECCC7E85AD008C2D0B93E08081910BF5D4B7F0A8568BF684F8C2887783DF690818FE02A7B872FD0F9216C93CBA079650A2F589FE6E1BE5B8D6C0FF9052A0A96FE42F427CD5F70B4D765C9D806E8EA7B5E6F5B53FA5E79E4155225D342CB15D1615936ADDCABD5E44C6A598C90F350F6E6F0A31FFD59309D81B4F4E2C12B214E3AAB5029E7A037BED2C7B3561EE2D298F46D6FE5992CE3A3BEEEE9DF709E0F76090B6C49C01C4C168C16B263B53535AF60969E8778114FCC2949752B337E5907280535354C26C5F22AAED80788087A5FD8C09CAA0C75B2BF7EE78E021E91C76773BC17A6925AE424B8564873DD24F632C00AD9BD96735D7299FAE1A6845476A6DD7CB0B0D9C0E0CC522E9A24BED4C257A5EEC3D8BDAED29BA8C004ADBE2125DDF27CAB871784232F923C8A130273263FA6B2E2E79CD1DD448FCC9602DE126CD6CB0CE591CF313106B93FF866E90947584F6FF4A37EBA85D8BFB3D4DAE1FB77B751FDD0440267082252007F908C69FFBCD4AD3D71693DC2CF16B5FAA7AA127686110585A17279A9542390FDE4F939925F8983862A2B855A2541B7A12A159D2136A90EB7A7567FCB11FA0E09D1B7C4B81A85C9EB9E5ECBE2A6F1AB5A035436807E5BF728D3A373289D4ACC80D124B3A9DE3E875BD894F9138BE5BFB8A3EC7F13ECAB3C11509F60AEF86B13DD91CFC3E68530B261F9A37B1DE877437A6D112005A26643596470BACA2659E4538F392207C62CFDD2B9B54892B861861A82665BB0DF229AAD6AEF63866442F33C2F70103459862D0222EB0A40ACFFDC6FE38B8B48465E1EDDB4F41D1EEFDE3FC2ED8CB6FD0273286CB21C8A159FA7B4677810D2AE12DDF3A77E717A1CA39B3B99DA32D2B4213E49CBF30803FDEF08BC3187D95DCF15B0531E28BBB73C21DD3233F36010F9CF6C9751F798B02C0FF7792099289E6ADA8121E6BDCCEC81FA9C057019A412A66E5D9908524AB11855F7BC963C8D3C3A37E898A7105EE6F866A7EDE1FD0D34A000976326A57D63CB3DF28A2313C3D9BAF713096AEAA5E3D5866F970F029E1932A95EE853A799231089C5EDC1C30168DF2F09D843B4185F5F7AA56E35BA0734C89DD919F788A30F4322ABB33251ACACA8F29C0AA53E702753399A1025626CA0FB6FFBC89B070C5C0E1D65D2AE16928B72A4811B973CDBFD5D97A418C10B16215F59CAB301BC248AE1DBA5ADC91F294CD9E26023AF54DBCE02F259934DF4EBE17D80314767F5643DB45E8F322ABD71DCFC55F4218E156221CC8C5C302B34B893909D87D2CB3C5E8725EC204C7ACCA92C9B4378153BAE4D4E1C1B2A4775ABCD2B3F086D4561302D90E98BB0F4F2B90016E090AA7ADFF084B03409CD465806140572DEEC45C238BB5AD46E5740048FDD616A603536A46CC5CEA0A6F46331835EF143B9A9287DF8A7EC9D501846B412203946B98FD40F603995E9A0FFA5815AFA50918714BEA056D00602E2DA2F3A2D5A1CDAD4725A76708194FBA81E9C6F66DEB7C8AC1381358CE766DAF364706FE6030ECADDE15D689AEFC0D74CBB403E8B93B081D8CA8A7ACE6C92C058BD4E767B6F1CE79DB8649A0000DD4F18BF277A39564FCEC7F28587309A6186232E22CCFF611F56473C9BD7CB8B93BD0185D8FE94C9E43DC7B0C70EC41483EADEEBE2FDE60725ACD9A4DCB65413B36BC1400D91D994C3B365C8AF568CC8C6C56828E9528233ED074AB3D57C396B86F23F62C0B30A09B0A7E1FB772499540B27838F37778249B75AF4E73310023FCAF36905D64D7CB265EA3D1BB58EAD5E4A443B55D43B94FC4A14AC9A30D42A47E37583E96367F3A4280AEF01F30EB70C46431ED729C5464FAAE577EE3BB9492D36345BC9F0D2C5F83D1A9F6CE6FE478E35C637014B9136D07231CD51D56D5C9F2AB3F4F277FCFBF2CCD226F8F0A58ED8D9356FEA490BDBCBC63CB91D7C96B0F456DA4131ACE7638E5CF0F24C374CF8291B75DC43A1F9CC705E90424774391B125EFC529C3AF6497ED4A4B939657D290B1554792580C1C895F554AD26942ED53C7C16C6D826E8C263D1A3F33FB3B7DB728EDCC20483E5C50D90D4CE697671E4092EB38AFF043A45B541510998597E419E1ECB090EBA9AF804A3FC778D73585DF9AE3B46F6421DF373B6AF735F1AFEC1EEB01661DB91C6B79660F29552B199372ECBB864E6EB5F16C71A6791918FEA4EA4A26204E867C26D16E138E6505523AC84D72393051C744C9D1BE927AD18E851273181890F8B32E086D74142C36A847E736C927280AE0C47C2720B8B0ADF557832AFDABCA80AD4DE8B0A79E41684C7C53F88C0A22FE0BCEBFE19BD657BC4251F870712D366C8D0306C1CA915154C6B6B82C1AAF941C489A1B7563702A8F7DBC287BB778F685D2055C9971CB0DDB529B0F4B5C8FC417D8579F26AA0C56B4583C3D11ACC3CD18B48ADE45FA09243907D3FE2B059F7F40F432613644A394F44977267D2EA2DFE56088B276CF5C9F364E30C2C71D78A8358EE3A5D8E99C9778742836D8BA2FB6642F244C68BBE2ED2B4855418BCBE122FEFA31D8575BFC5C98F9A8D3F01A28B1D50B1DD408C15205C57620DD623FC999EE8D1C02A3463EAE84C72B356B05CBF1634AFB247DF9FC3145E5D543B056D4C63E466903773B0AB794ED5E3BAD87611D5737D30426BA1CF76CA96209059FC2C8055C0894FECEF0B7526E1CA233B4D57B0F487447386EE83CF0DB5100BC1C161CF7D7E501681D5FAFA0DFF94535566CA0FAD9911B69DBDB33FB08ABB35D1F7DA09D5986BFE914C104FDBB9B53B41FF1935646F5F80AAE3B617130EEC2DB8A70E3BF1D11EF7D4A38DF4DCA74454BEC6B20A05B0A088B89B3FBF2CF7454D94465281263D4D2E01AF1D405189718155474DBE7EC64F92464F2F2E16686686EA01448DDFCFF053279EE27C0D840F430274D1E5C0FD16E4B6AA880E8971008140C7D3B63EEB4D4DEAF3F56768186C2C37AB0BF1FCCD2512156B6EA224C1F8A70FD6EBC77AFF4885AC5ED05DBD832E7792DB86BFC4546BEC3113B862A826812C06A827E3F034DC61ECF72740C438B55DC62F7E641B34FC5685574FD7A906984862128919D27091F06436DE302A05C22DC4882362F2F7737CCEF0E159EF34B307EAB62566E6165D6FFB1DC7E68702B32258D5EB2DE89F5F324D98079CEAA46C4FFCF61ED5A8881BA7C62F1F7B225C484C7505614A592EF3D32E883F9E71D398B4C63759ED6FC11CF38CD41373E0996875ADE0B48EAB4C750B9CEF7E9BAD217315F48E103DF380C32C950B1799F70B123854B763D97C60034BB34F5AA7699B07E3BCF99441586821447E48D582C3FE5E8206CBC439499ABAFC69BB0C884E2726A1878CE83EAE8BE5F3613155A398D4FCE09AF52A7DC0F09C88DAF3AD0F7236DA2BDB969D31D42B853725A34D6E4A4D67A7C1A1A95C1541F8E467CC35AF312FD1EC518C0D9A6D56EBD54F6453920C2026F9459CA0849EE62278E71F2B5DF57523790DE5DF1253C6C421FB11749FD73E557B77A67C4B9FDF79A441CA359C5C499526C122B33A2C2EB29387B33EF4E125CF7AB2423414933557B6DF4005F4BF60CE22FAFE031FEB450E5CCE7033D16BA9B2C47A63D60972BB7CB00B28E04CBDA578CC3D09556C092070373858E9969C4319952B71DDFAF0B4CC768F9129223F6B493E61292DD3EFC788747F7C6B0D9006B86C3AFC0DBE21DDDBEB385E568354B636E8C20ED17992FF016AC495DCD1BB387E31BAD5A3E9DDAC565D1EFAFE533AB661D20351FE85FE35AC5809A3D493C672D29F890C22C40392C9002B30BB478644F1CD6D3378B53747C6DA11E54237395AE64A7B54F9639DD1AF96E8798F665FC6C6DBBD4B865AA83CECA818BA9139F047C1F9BCD3932A6CF31EA0DEBA1AB1A86E9D5C3D1BC71FBB09476AE630BB8EB47814A83791547E3397F1944D05B754BB352A55CDCD582936DD8565EA42E2A010007519B88A0CA17E4C57EA2820D1833C37684A63B9519DF9465A8A6A15B8E80FC9119A9DE135CFB02770F3B6F7EAE0B69763D3855CA13E87659F2B3911B7A32307A9A232A5C1FB15B905E672E55FDC3C2C61137F37648B31D8612E61461FD474D4448FF3AB1C2E0E782EFAB358949CFA96DCB2C25EC173D75FED30CFE49AB44F01151713D10ACC8374368B0FEBECDF937941DC26724B5007330C77C0944FD48E6C4269AAC25513D22EA7AEAE8E94E3F4E73A5D632C8B89155478295EEDAFA26AE4FD34963B9FC80A347C2B8346012A9C6D95AF2BD0793899A82E40F66BB0EBAFB9967A464144B6E16E591E01C4DCC1FD7A8165ED755118D6823ECE467E28D1A571AC0541C0BF952C88C500954F685C4DFB31EB105DB9B12428E1A5DD42B6658B646A8103D9E137E8493861458117FCB2270B598F6697F4DAD3607523EFF54F980F54E4E791042FF6BC0BF077D3057C6A101E7EC1EAF8A25DBE420F078BA8E44C1CC78E0176FEA402F81FD572CC075E3AA52A911284A301C746520535726729F9928D4402AA37DC5B10B40DBE7C01E4272D9122D19ED7B41441F1402C1B81B16122F2F8048C57EE779DD145D3D20DE060E0929E49DEAA873F1198B99BDD8D50970F0B899E46DBB10D4AAE3F742EC62F0DB5168947307BFF2371CCAAA7036DBDF1AC9BE8F1DF27461FC5649B9E6C3AEAD67A6539B7843E3B22C17B70B96911A9E05894ECCC0A7D6C30016DD49EBA6C0A3F923E3A547C1E024AB2BD0256B7535608B25503641239B029C87016D78BA4E2686E0DCD97592EEBED209FA420D1C1BD42E99066B587F5370166934936AFDAE6F17EA39481F415F49AC65542C4D2FA14E11062133A682A8C66A4B1DAF43326C295BBA45F5CFAD64A1A0C97981E320C528D0F428921275A675B0F6D4413A00982ADD633240FF2B9B3F2811B00C6EC3870EECC933234EA128D73543FA4458EBE03855C09D591F23A666B4B9D79E31838D26321FA1A3E87813A9130492BB143D19B18AD61FED31E7E5754FD5DFACA22BA2F7F9B5986049497EC46527BFA8614D3E29CCEC3DA2A0B586FBBAFDB5442E60398F167DF4F47FE27691AB5BCAF84E8B07DD77A16782B6CFEE2543BC1CFC357FACF89E0AD547FE0EC2CA49D007CFB35B9818BE721D46C8683268422D37BEE9DC8D3B75E906F69B4C6C929318765043C84919347396E490BF839576EFDCE049FCD984350C8CC48418FA5FBEDEE7AD9A28C53FD88D849248FA23E4BD9927B083E3EA7C7DFD08F3BA9CE88D4B17BCCD286F6C82A8136E20B2F0FF8A71F18810CFF873E5EE3CE067FFB1EAC34332D226B1EEF78C081077152A84AC1A5540DC8BBFAD7BED3C7E42C2F55650FA407910AEB29C80F7D0EABEDD3A9BCF3687AA45F567638D6B61B0B6B0482A021177E70075F96A11D058B8154708CE5FBF9CF2F544F8482D0DE70E89FF7FB389ACFAA305F2999D36CB9A534CE22C77601962C6310A9B85521ACA7738BCFEB4E6AC6A1358F6C011F2CDD0DCE07ED3AAC4DF5027867DAA99DF3997CBBC964D27A135847533D3DDFA38BBDBA39EC1B88A1D99315A4FA8DA04F1BBAB6864F35E3DB57CCC7983B148F2C034FD8A6F61C54448EC516A83FB3742BFB6A7D43EF186FC5A1FD44B9282ADF5839DA760AB95947D02D8712E057EAF19A4FD34D7EF3EDDBDFB8F80A3AF4D6AD3EF283F0A2EEF69D1F5C33EF0CA5EC92A29E5B6C90FA6F6AF1A207A2ABF77942565347306988223A454CEE89F14185069A89263C394CE93C042648D2788E813EAEAAF01393E66D22C6A72D7D9E1F803A9AB37495D6A749497BF232836757D879DA6B5EC0E395D728FEAFBFE264774AAEE0F1F2C5A6276000000000000000000000000000000000000000000000000040B0E1620282D33BCE59D1F83462B9578534D7A05DC3F21C34EA93ED78387B32DE09ED3CD2A51EE2B8F7387C8C2D426EAF3795E99B158D467D9A039234FDF207D65D2577D1688E1 +38796E20B090704AA24C32C0C124A7DEF5F130609930B6E1AED360E513B596E661776CF8976D08F52605680DEF3C4EBDB95740C59650522ACB3CD56303D4D823E0C4BD7493B3B27047885BA8CFD93B4D71C0B9B300F56557C665ED9C953E894B02FE79219D32DBAF5AE4DBBADA3CBF2861EF00C40075142DE7552DFD76C76F18997884A8F00B9B6DCDB234C162000C37AFFD2D346128F84204DD5AF3612D45C0EBDCCF49C5F02ABF5E984AAF164A08E150F75A19C1BF0F64A70903B07254161BEE6742DF447DF312E408B7F00E6CA547280866574F050E0F8CA05E16F1001BDF6C5877D088B919D5754F2B4DC7BACCEA22431065A58F221F616CFB33289129C8891FB590D76E15DD76A94163B20B9D8DF203A1A6FF451E95E7B06936704DEB768F6A4FC95A333665064DB55D0CD5B28FD844C249D1DA5423F3F31665F42676BE1BF123C9A8BB26C76ADDFC6E8B66A940FF88283129BAB039EF285F1CEFA91C11178CCF37599D3857AEFA3D6D8B8F1C806D3154FC1D8995AFCCBC73EA0AE540726411A18CD0297201139A7F182D84FACA6DCE99D48C7A84BF5BFB3352E0B16943D96C5F758FA8AA111D8F3CD25CEA8D0B232BAF70FB8547728BA0E19BCB9A75509F4892B7826B3AEEABC56F3A45EF2B7A4F6BBDFA052EB1A7204BB59C9D4A3777E4D5EBEB1F7AF263E3614794A0E66250884BF9CFB777522398DA1B9C709C33F06E8C5E108D30218C199C5B097C823837A99AC786074052668C8A4B5AF0152AE4D92FE4E98C91F7D318AE67F482CBD19BB70AFC290B90ED5B630387410596BFC754764C81AFFB5931AE0A85E41E1DC950E65CA22D272B58CEEDBC6DE6635ED6C85B05A699DE77B6B921B6DC281A914159E26C77F84F7636D0A3D9B90E8965949CF1A04EA6D36838CD54530D1E9953442BEF130B25CBB733B43A324ED5898B0C8F8EF5C71FF164D5F37B2219E2CC3618DF2CEA8449C95BB3261C350E6BA81E7B72E6D46740DFC331CDB78D3074F79DCEED70BEF2B0467A73137058795AA933ED60E00AB9105ECE16193839EC4534012A2DB5910970E0BCECF04085D622EB92BBAAFE2A888E1B2F4E381E58518F7AD10445E21E40829ED18D61DE3856812D5AAF963F058C1203BD6D73B933518BB4A44DB2154E10C0B07830FA07E20001857D46D3CB541061EC6CBBDABA1731574B3A140E1CC1F3EF88AE1D78FE7E80A6565FAC737FA1E0A70BE706250C93DC1BAFD46BA50CFE07A3DDB8CAC3943BEC70044D9D374EA8D8C3634FA270A6701DD69C251A7229A0F37F49649195252E9B74D03B6256565E26BF484FAF02181D6457BE6F615FF54E21356B36E119DFAB1673984A31A47365F766C9C4229EEA10B483B219AEE164162A54F3A9D7A474D8C8AD1A2D82B95F42E88E6EE7B67C2D103A1E939D4377A59FA56673DC1F0EF642B3B7541ACA2D21AAE4044E53B29C04C16D510575C2D5F104BDBA6D3102DD46589E690C34DB73245D0A299DF65974BF462FC35B58A6465518988F5E2D3C2B5C60C728C0F21E311228A7AE2F7481C9EC12183FFBD2314BC065BE9E5A7ABCA9627E9360EC13AA078953FFE49C981E29D9FC0117929BC51056CE6F9E3CD6D65877C95A6C7B6E4BD0B2BAD131DF0477645FCEDA0E5328638D094F618FF61932B7B2ECC280D26C9BB72AAEF2B34E55A2527A34E76406AD6917C95085A228CD7EF3DC63FEF65CE8A33B1B4BF784D008686B6471D0E9E699CA6E589DBB666D6C11B608B3F4030FCDD476F381CE03FE12DCBA93E2AF7BEF259BB86BC39AE969BEACCED93FACFD3707C5DCBE449245F6E2E0D0E689CF5B534C9EAAC4F083A38B5F869E025290C07DA6AB972158A1A07F2A1BE774848D05A1B7DB112CFEFD66CC91911DB54906557DC52036685F76B2BE5557D14E1B58C7A962F7A8706787F726076FFAB03997E438DBAFDC5FC38E1BBACA4533694069371FBEFA4E271AE66B876020C3C7543FB2BAFA40FBB08125EFB057FF3E14E253F3949745AD6AC708B87B598B9A28020FFD44A243661D0DF1B2F26E047B55BF1E502B5DDC5EFBFED7E18084D0E9DB9AE1E55B40212C4001D5B19BC93BC74CEE4BE3DDFC54E58BD56B40EC4A1E8DB3AE7C2CB982A47E147334868BD5AB4FCFF96389D90B0CA78A23C6CDF71CD155D2E2D20B7A7F21544475A4C10A90F304A174CABFF35450DC5185D505C45BBB034CC010AD2306909473C51ECC4F87019CF66959D07C83B4E6C29F946D8399E5E2BC4BD5B959BD29B87B82872514B0C8F86997C2BF78DA0E9BD6AC12F7109D2F05339FCE83C0A528A6894574D99EC76CA5F38C4E1A1E7FEF0110EA2B86F29BA2463448502BD725A90780F8F20C4DEAC5FBFD93BC48B4ADE4C814012BAF6C3EE604462F5B710D07D3FF86884D7BBFD755CBF136F2E51E693D205F1CA1FAE7C69932CBE89AA2706842B23271AB38A2639871B025D234B498EE34C04436670B2640471A3ADC444DD3ED165CD0DBCD0A22F5B34461E2BD6F0D13AA7408FDFFD5CE7F28DF3DC4CC44C5A5A33076125F78CBF5390C0829A83FCD10A7A73A56D94689BBDF3269E7F82085087B86E6F4AC449903C4CE7FC0948EF0EA57AE339F1A60EE0A299DF503561677C00F49ED61EBDC96670290DBC8C8EEE3D8B71C1EB0E49B95913739C8EE2049900610EE8FED70EE6B5D99FA11C5DA2B7336FA095B98BBD1E8545D1B4F35C73F4B5B501AFD2970BFC33078F66F4E86837BBEE43D3831065BFC889BE93CDCE21709DCD0A833D8C9A97E068EB4C7727499A7883C7A961555E64C6F6E2E2A577593C28A7D2F80F5C1230A74F3B1EBBB8380A8A185E7FD44F760C387C2BEA509A9E86C308F115F422D02A456E5261E3163745E3D22367ABC9F9BF1E6C75C1C7D271F568F06A344DF1BD84551FADCDBDE55DFE14743FFD36C8E071E0B85B6514A1F7780EF562D0DCE25AF095F7AA867A1B73CA9F6BEB2097DDD696D44CF4E645DEE67D159960C3AE7B8A587866C71F304E06451CCC62DA4C389B041369D6F58CB4C47E4E887475A6D84711A034C6D7EFA988C7A11E2E919CABF01AA2FA9D6216CD4A7F22FE692FFE1DB53E4CE1B5A7AEA2525E8F88B05D1297B5D435352D92A66035DB97FC06D1C74540A487DD48AF1BB462312A0EFBCE06B7317CC201EF86D48387421575294EA33282E65DD8D1BC87F575AB0E8FB92ED251D3D559A7ABAABD7D83F6E97189AC79D031449725B1F887070C02F9882073AFA471DA18DD15B4773A915AE3E23C8E70FAC216217928625D47D35EBE7C487432AD36DB44A1283D75616AB65E18CC3C4724882062FD50D8FA09DF41280304323330473322DC97233ED27461FFA436B6D194BC2F531454B3B80BBC4DC768F77FDEEB7D4E5D8AE6D97FAD09556799996D820990FAE21C3F2A91C2FD35D71BF0BC8AA26F00107EA708606D973C649C50AA0E09F082051C0AD5926567C512DF7971745E1CBB78CF8EE3EC075EFDDF9E53A060FF4CC4CE2A961630E46C8414074A2A5F92CE1BF236D0FEA264EA495DA9B925A62CA1E876D76E03B522B118F021BA817C2B624AF63EDED7AD7A48D30F9AD785AB30016AC34AF8F0D5FA057CA341E3D2A9B94F2C3CAACE30AE3A856DCF17BB43F8634915F3A2CCFEADEF07EB9B719D4509DB18CC10868EB4DDC7AFCC5536E009C1EE6EBF2BA8B1F60E3190E2F881C4DDC271E2E993246941B36C548092BCA953EA9CB946AAD1DE5A27B912DF856C09F2B4F4F658743C2629B1684B68A465E318A896A6E8FE4395058A26C95AFA6C46990A6B577FB41DF7ED8ED433663BD792B65308C921C5BD450C6253ECB33F4397DB7419BEADEB409D1D5FD9AE1AEAEC6AE31221002209076BBFE67F915F78B939133715493B32B97D5CA6D8C7C944346FD0F89058B35873EC808CA75C100A51C38010B6062B44C48EECFE49EA82943B94A812E9532753BE035F138ED92226D82F77CD18D945CB13F266198F511799865FE92D8B7BAA4D9CD6EABDC5E97B14962B86603F455E7EF457EAF9EA41323B4B0A7A93BC29520FC908C034AE3D660ED914F383C2F8F98534E536FA4ACA7C2B1A719D581D9C269837893C130FF3EAD5C98BA7B12D0BEECFC02FE6A8213FAEEBCB3B0376667B313FC62C831BAE913DE0BCE877881BB8060601700BE7853DDE98C121780F37D8C0C4A647F667A0E107E0DD6623D0B6533F1ED50450A9669D24F0A47FF3D532F846D7B2034E214B3B37C6EE1F36E9389837E0CB8CCB84970FC2A01AA189944E2DB2620E92B39DF0F2006F8F379C60CE38B88ADB3F14F6F6B216444FB0C63160EC03B397F552BDD3CA971066A6974E08F4BD4B60D219AE64EE1340752B5525E7133FF8F21803E77FA78C291FABF65D0ED54BBAEE1F0EFE6760C10BE545C405CBC597456FFCE829E0066AE53052CE56A7379E8B838A4A837A791A9798AE7F331F8E5C80B5EEAAA1127046D32A64AC23685EBA4F11335E1AB41AEE81B39A7B2A6741BD66CC40826F08ABC5EB5138E64D42F76BD641DCC5A46ED65D50AF5D7021DEFE796D71A8A7FFC01F889FC595734E0E07D6A24B2F36C28B70A08FFD9269A56ACF1B88F0C12ED0BC26733D9F78267D6AC77BD5A57F4D631DA8B9D73374230A8A9237A532F617EDE49AA4D00393B4D6874DD2D8B92D42C032B0ECB2326A77CEA9C02C0DABEB6C78242701561F5415674E6CD96C2EDD0E96EBA22A12EAD6502BE87B902A9988015EE0E675412600C7E4571A5C745E024295DE17427D9A69A355F176DCDE2C5BFDB1B548EAE6DFD8FA2E2A50CBFA90DFB69E0C939FC969DF9A501BBF7AB51017E7CC2B2752A3913451FE2CC061B0C9A95464A281E21976AC7287A431DAD74E287A3FEFD21978A75D9ACB35A9D10F54DAD84BEBF5A7A65F7F9419FD7E9101A04080D448701CDAA0D04413D1095CE33D39435C14A9798CEFF5C9FB8A9FB460C14157A28FA0F2BCE96E08A194CB27B656251AE24531DF2CF182B9009E104663DEF45AA9B3060922210FB531FCCE4137020CEB7C6E469DEECCC55FC04C822A7151F3B054F2CF33B052A1856FC31B6B90C4865D0CCC40806B2E8DC70334E86F285049F9836B414C406800DFF77B239C1F9DB0595639777E2581A5246158A50654F0C62911220A88C212F02EDE91161FD1DBC5269F6E6169BB57E5790EC1C4CDB21DA2D2F2C0BCB8EEC8BD349F128969E11B840D1947BAA65C79D8FBACB0D6FAA59FAF094DEF2F751F4F3E519A7D2AC8E5A3FE25E684648B3F6376C655EE912F19700AC3A0BE51A93D56EA67AC21D0BF6424DC2BE720AC23003A503BBE1FB5A0CEABADF7B26B71988A1403F3858247CBA9979ED4852EE31A156939ADD80574A1A230FD8812489D93D890DA7BA16900FD4DD51DC223AC82BCEBB52841A58E389608CFD01202132D35B846581BAF761DE5BE422FC6CE265FEAB725172D9D9E0545EBBBDF4C724F73217954EA64B522E08680EBE34F8B5AB163B798F5FFFD23C3F73F2B18F0D766084E6F4D830658867A7CB6909E055EFA391BA69B163246DCCBC96C38AB830E18D54CB1F54998082AA6A46C88AC43277DE95035BAE901A81AEB4DCCB41F93CDB9DC080396E9EF8A3A36A8ECD57CE8415972ECA84FA3715B9C0F5046F91C486B81ACB1544E7365AA7A248125A0B3A06E24EE55643F9FB9F6F9E99868E862E8810A6F5A6C25F7AEBA8EA1C1C8BEFD723ADE25D8C51E48912F05122FB54D91A196D41CADD54CFF5C41E9125CF3EEE2702D914C39449E6CB50138513F86A69B5D8FA6977F16AD026A1101BDBBA2A4D07ED50B2EC16CB12AD0544A4C09336637DA9DCF36C292850D229943ACE2FFC65C415C595CFE261335016C5F8B4F6FE11B9A8A396C7D352555353A3ACE365EDC9902D5D192267401FBE41FFC75912DE0B295BC49641BB96E92C10B451733893DE9C79F1B64810734B473631DA5649A90F4B878803AAD72D2A83C49E8A5B0815369F06F077A9F946EBF74918EE0D0433F3D0EBEAA987A1C97260BB7F35495501E62A5EF664E9D745C1804E5961542599EA43389203C539DD77F93909A3C7DE272A0F9D325B99E59B505F5DC8E409712E928A6F7962E728D466E5D42375891DEB0741298F1ED874B853E9FCA68F5562F9C5399BA5F59F43DC628D1C90FB7ECD60EB771FAD4A81A464A552CE62F1D8D05D990E9A9FCF787DDFB13010466A1B42ABED02E2F81DD66013C43744EB670BC6EC0740AA75925F2BC3C24B9F8A28FBD8AA5A8B5FFF106E0DD2B9BEAE5E01C4B725F1EB22ECDE0163B28E7CDF3B6CAA75B7772EF74D02603AC2BA16971EC69F96ECDC811BF0E7D4AF47ED133EAEB24FE1B93EC6C6FF85CD0E4CCC4332182260B8399997096A061748FEDA6C4B74C77DD74FE329A9547335D0F61264C8E2AF163296645C5F31851597CD034DC431DC0AAC0C3558E941ADA82A70CA246FD1191D989DC9CBD1DCEF334B82A0AEDCE2FD45475EC4F50E5F628CBABEDDF6102B809BD6ED242D3241C6CBDEE43157879CB6BC00000000000000000000000000000000000000000000030C141921272F35 6924BB4257A7B9AFF095C30BB35C6AE4198263120F8039AA4E78E174A786CE008301E666F59D3EC5044DE456788FDE19EB39677B5F9FE14150DA463A706F3BAF715B95336B2D685A7CD7880713E4587BF7D857BF7E315696B8D0D9D49E142918BF0974E7F43237D4BE3AD394599E3D39BB7649932553447E5D5ACC3499930176ECD3A844A425F50D0511C9226C4B9A24F2A011CD88D32308E0312A0C87CC34A995823C65F4F0F98E50C37788CE38DC28FB8B9BFAAFA904B541EE712F6A041E0611374F6BF17EAC0BD56F3B6BF336DA9242070C2469A20C4D1616149A6159252011D299F93F986D875DD30B38A22549174570138C2BB3AA9CBEA91974F3D89BF5AE32BE9E58B854A2F8E86FF76780C03490F467DB0651C20B1DF60EB97A3C99D9BD664BE6A5E4C8A8AD4CC36390D7004E4BB421DAED654C357DA4D68498933EC71777AD64C2AE013C73EB457C68EF9A745ADEEB4FDFC879E774D03FAF6B14AAB10752E24B52D0F2D94D540A1EBE10F597E514442D6C13C2E2498E8AF3017C52DB233A90717DF25B4D072B7D88EE8731D16824C95D1FB983C449DEB466276060FEE4C7EE381451F232C29C7C3220850C61D1C3C00DB1CD9726A02A56609F3A65D3D164604588CD9B431412F1ADD914C5C2DABBC90467C0C4EA5F76E24AA618765F8B0636D7B065E1F4E6F622EAE17152458C766586772D363FA99214F472B0DB8A1E49D82D0278F2958B0AAA1586DB134BDFD2438742495007E2FE5B60E246399226947A12EA17631CAA534687CB75C060B4797EAB8277CC4F8A7A20387606EFE2DBD3E736249277D90FCAB992A8C99E85AB03EB4CAC5D88553958528AF92974718135F1D0C793EB000EA0AEC3EC1858FDD18688D1DA27278DEBF2CA8110BA4A204F7930E1C8CEECAFB73F75DDB34C5C55968A7933058426B55D039F7292AC43F64584F6DF187A1D6B003F514CC13B26C2F348195AA321DE6A27EC11348DE50D825A2964C631992E4B0B425B1BEB4F9600E3ADC4431CF2E88B4223D2DB663C3CE70EF85DDD56A9BAF138A9D7EDD894131C3A8F41A04EF9F86752B72181FABB37C86B877E61D60EED95EEFFABE6376E14ACA817C5F41961AF8A7849BAC094917B2D132276B6B3486AFF950D23D4AADC24CE98A5269E1C69917960A31EE09A527C358175CAA0CB1B018E9526D93534EADBACB52B273D735E22DD0D5C28FA3E47CFE90B5215AE24F146C3464BFEAF01D28DAA553C1E94428A104A9D78AEC762591E8879F76851CFB4648566721B0CAC1F14FE16149A9D8210CC8F2F50DEF7B46C843BE93BD8D55602493350AB560EA5BA17716423BE0EB8360AB109D8FB18BFEA040847B7335145D4F200D19CF6FE7BAC917F426C9B3D39A9CA4329818F240E7DA382761072F4A6505EA8E76C1E446FEB6625E38DDBCD3CDA81E83BF768F3E01D9D263B367303AE156C0B7183364A1E7941A09298A3ADF7BD231E6114B9DCE7952B113F78163138B9266F843F1ED97D9C2B163A6E8BD4C1AB4E179367C5AC96CECF5050FE821FDFA44E9E680B61C6018932DF717811459AF2542E2CDE77178C2E9880F011E405EAFA59C8CBBED76E5A1941104B1B9D3A60491C954755E02E894103F1F4977475E9EA36609FD67C9DE318EDA2370DCCDBB9CEF7AE6360905EC220838C9769823441CDD0DA8EF0ABE5F2D1D76E2FE08FEF53DE1D6166AB1A92B1AC093E5ABF7658C4B57287F2D1FD7B82DEDAF8D5A4FBAC4B35D58231694E162497578ABD7AA7C8FE7B3541A7F18E54E8B7F08764C5E68449DF655901549832D628FA63D2B2C5A150933994A9863317AD40D778D9D2C05C7898850B90173223C7A0AF890FD7E66221B6F06318B2ED5E199CB424885AB841E7A4726FABA2F9BB53BC3236434C35FBBE4B1A0F93F50C37896C29F8E302AD31ED3331D620E3B629455101A1F1CC7BA5E46E68ED4A8CCC87B4DC75BC0162B6330F833FBA2575DFAF5B5F28BC54FF2BA81E7A47313C15482B605E66BB38C6198F1392104080FBE78B86B1BC9A6FB881F5C7820147E6BA14B81ACCF20CAE96641094C216902EA5C125F6C935A150D7C9ACC5D9E2E5D90E38C0503AA9426017C76AAFCD5261B506274EC13A9679FB09796027A4BB759D928279B94D841A097393BF7E5BD69A496CC3DECD2B0F07F83392AADE33DC51B2A84F6A07635DC0EF57A9AD5959B6A50B7BA509AD5B11FAD26B419F9F1E3F9C7329B5A953D7CC87B2DE210611CF52A639EF2B3908012CB88E1D6F57625079CB103D6C98101A11BD2233B65602CA3049BD320520419F76B061E3598DE38152C88767D1A24FBD02BB10C38EACAE317DE6BB287B4D2CAE5DA0214965D8773778626E9B972859D8482B8D0547E4F56DFF87681D5BC5120F613FBBD91E1F14E6DEFE672E2A7EABCBBB9B11082C5E700AA0B1F7C1785FCED19A93AFE7C59FA2519BCDEB494C3D13B2125F385323B816C68F8F5628C7C2ABFD0278A337073DA74D16099698C4B114E8A8CE344E0A15D0FC7ED497B001D53D4C96DC3954D3B4B956CB9D2A272C51F1559B22904B40CC8531E40CC412C68CB6EEA4A4090B38E2797329985467E818A524D3228EACAE7825D3DAD2EAA422FDC77AED71A205DA7838D945E7FEC37E4DCA67E504CE35E5B045F56F1E8D7529EBD6F1AF7B6E939E2B7AB4027D37A5135D172DA1AF9CA2F728A6F37DE60DD23D97D11E75AB1FD51F8E9A1397E5822159DB583802B32EEBB4567ECE3746D1AE33314785643DD2A0741E7F1BF2D261F22124E8DDD08C640A48B54717517C21CD325328BC239CA028B2630D063C8CC20BE9BDB48502DADDE73FFED5963816533E020AED1208536255B1CCE985433127FF4F04D5B1E2F2108704B8B966588C0156AFC2AE192986FBEC443BAEF6CB85A6F29C7792405A24114710AE1C746444FDF5FB659E5E346826207B8C54463A0617CE17FF33E40F931FE576715C932EF29FD76B04A69B58E0303D8EF25678C8B70AF12E9045591C04E8B77106940415177E868593A09C7E14619A4B332F9ADC3A658B86017F32656C5429C115E110037A8CC7E544677D2DD239A59D54D0F3C7460EC15208346BA56DF5086C5DBCC41E0C95FCB6861C2C0C32AAF3454EFEE2FFBA214B430EF248A59B32444D8D0D3DB87C9D4B1536D157728EE7585EF532776A003A023C0AB0E9FF557108C390684D565A665063266AE6670ED53B0FAF8FF67829BB737825B153A9338CBE3DF1A462849B93A81F84ED07BE6D6240003274737F618DCB26E48252CE4204DD3139FF6876F43B305D835620FEDF79AA67433DC25287320E9917967B70B2D866D17B698BFFF2B3AB9514949E58B57C68A45412C1FC421C768BF5EE8A10C8AEF56926F51EC62C11569F31AA517868E5CAD89E958066EB9EDD7271B31CB4B1D6CE211225AEB5B57F749719DA07ECBEFE03881DDE3D81E4135F2DC81AF779776C1B8057162A6C982FBB4DA6A9AD284AB10C70022044F46D400BF6AD7182D197789983BE99227979A1334BA149D869BA1C4088123435BF978541356DAF171F33ADB1C97907A0FB5845074A85D26F546135AED0F91BE4539C12BF9411E4B556F687D069DB6B21FE2B7F321887448CEA55DB19FBB8B0482A55AEC16738D74CD265093836BE99D4FB53E9B014B037CDBFE9 \ No newline at end of file