diff --git a/Common/config/default.json b/Common/config/default.json index 6c867a73..12f9f3d0 100644 --- a/Common/config/default.json +++ b/Common/config/default.json @@ -97,14 +97,14 @@ "cellEdit": ["xlsx", "xlsm", "ods", "csv"], "slideView": ["ppt", "ppsx", "ppsm", "pps", "potx", "potm", "pot", "fodp", "otp", "sxi", "dps", "dpt"], "slideEdit": ["pptx", "pptm", "odp"], - "publicKey": "BgIAAACkAABSU0ExAAgAAAEAAQD/NVqekFNi8X3p6Bvdlaxm0GGuggW5kKfVEQzPGuOkGVrz6DrOMNR+k7Pq8tONY+1NHgS6Z+v3959em78qclVDuQX77Tkml0xMHAQHN4sAHF9iQJS8gOBUKSVKaHD7Z8YXch6F212YSUSc8QphpDSHWVShU7rcUeLQsd/0pkflh5+um4YKEZhm4Mou3vstp5p12NeffyK1WFZF7q4jB7jclAslYKQsP82YY3DcRwu5Tl/+W0ifVcXze0mI7v1reJ12pKn8ifRiq+0q5oJST3TRSrvmjLg9Gt3ozhVIt2HUi3La7Qh40YOAUXm0g/hUq2BepeOp1C7WSvaOFHXe6Hqq", - "modulus": "qnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/w==", + "publicKey": "BgIAAACkAABSU0ExAAgAAAEAAQBpTpiJQ2hD8plpGTfEEmcq4IKyr31HikXpuVSBraMfqyodn2PGXBJ3daNSmdPOc0Nz4HO9Auljn8YYXDPBdpiABptSKvEDPF23Q+Qytg0+vCRyondyBcW91w7KLzXce3fnk8ZfJ8QtbZPL9m11wJIWZueQF+l0HKYx4lty+nccbCanytFTADkGQ3SnmExGEF3rBz6I9+OcrDDK9NKPJgEmCiuyei/d4XbPgKls3EIG0h38X5mVF2VytfWm2Yu850B6z3N4MYhj4b4vsYT62zEC4pMRUeb8dIBy4Jsmr3avtmeO00MUH6DVyPC8nirixj2YIOPKk13CdVqGDSXA3cvl", + "modulus": "E5CBDDC0250D865A75C25D93CAE320983DC6E22A9EBCF0C8D5A01F1443D38E67B6AF76AF269BE0728074FCE6511193E20231DBFA84B12FBEE16388317873CF7A40E7BC8BD9A6F5B572651795995FFC1DD20642DC6CA980CF76E1DD2F7AB22B0A2601268FD2F4CA30AC9CE3F7883E07EB5D10464C98A7744306390053D1CAA7266C1C77FA725BE231A61C74E91790E7661692C0756DF6CB936D2DC4275FC693E7777BDC352FCA0ED7BDC5057277A27224BC3E0DB632E443B75D3C03F12A529B06809876C1335C18C69F63E902BD73E0734373CED39952A37577125CC6639F1D2AAB1FA3AD8154B9E9458A477DAFB282E02A6712C437196999F243684389984E69", "exponent": "AQAB", - "privateKey": "MIIEowIBAAKCAQEAqnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/wIDAQABAoIBAQCKtUSBs8tNYrGTQTlBHXrwpkDg+u7WSZt5sEcfnkxA39BLtlHU8gGO0E9Ihr8GAL+oWjUsEltJ9GTtN8CJ9lFdPVS8sTiCZR/YQOggmFRZTJyVzMrkXgF7Uwwiu3+KxLiTOZx9eRhfDBlTD8W9fXaegX2i2Xp2ohUhBHthEBLdaZTWFi5Sid/Y0dDzBeP6UIJorZ5D+1ybaeIVHjndpwNsIEUGUxPFLrkeiU8Rm4MJ9ahxfywcP7DjQoPGY9Ge5cBhpxfzERWf732wUD6o3+L9tvOBU00CLVjULbGZKTVE2FJMyXK9jr6Zor9Mkhomp6/8Agkr9rp+TPyelFGYEz8hAoGBAOEc09CrL3eYBkhNEcaMQzxBLvOGpg8kaDX5SaArHfl9+U9yzRqss4ARECanp9HuHfjMQo7iejao0ngDjL7BNMSaH74QlSsPOY2iOm8Qvx8/zb7g4h9r1zLjFZb3mpSA4snRZvvdiZ9ugbuVPmhXnDzRRMg45MibJeeOTJNylofRAoGBAMHfF/WutqKDoX25qZo9m74W4bttOj6oIDk1N4/c6M1Z1v/aptYSE06bkWngj9P46kqjaay4hgMtzyGruc5aojPx5MHHf5bo14+Jv4NzYtR2llrUxO+UJX7aCfUYXI7RC93GUmhpeQ414j7SNAXec58d7e+ETw+6cHiAWO4uOSTPAoGATPq5qDLR4Zi4FUNdn8LZPyKfNqHF6YmupT5hIgd8kZO1jKiaYNPL8jBjkIRmjBBcaXcYD5p85nImvumf2J9jNxPpZOpwyC/Fo5xlVROp97qu1eY7DTmodntXJ6/2SXAlnZQhHmHsrPtyG752f+HtyJJbbgiem8cKWDu+DfHybfECgYBbSLo1WiBwgN4nHqZ3E48jgA6le5azLeKOTTpuKKwNFMIhEkj//t7MYn+jhLL0Mf3PSwZU50Vidc1To1IHkbFSGBGIFHFFEzl8QnXEZS4hr/y3o/teezj0c6HAn8nlDRUzRVBEDXWMdV6kCcGpCccTIrqHzpqTY0vV0UkOTQFnDQKBgAxSEhm/gtCYJIMCBe+KBJT9uECV5xDQopTTjsGOkd4306EN2dyPOIlAfwM6K/0qWisa0Ei5i8TbRRuBeTTdLEYLqXCJ7fj5tdD1begBdSVtHQ2WHqzPJSuImTkFi9NXxd1XUyZFM3y6YQvlssSuL7QSxUIEtZHnrJTt3QDd10dj", - "publicKeyOld": "BgIAAACkAABSU0ExAAgAAAEAAQD/NVqekFNi8X3p6Bvdlaxm0GGuggW5kKfVEQzPGuOkGVrz6DrOMNR+k7Pq8tONY+1NHgS6Z+v3959em78qclVDuQX77Tkml0xMHAQHN4sAHF9iQJS8gOBUKSVKaHD7Z8YXch6F212YSUSc8QphpDSHWVShU7rcUeLQsd/0pkflh5+um4YKEZhm4Mou3vstp5p12NeffyK1WFZF7q4jB7jclAslYKQsP82YY3DcRwu5Tl/+W0ifVcXze0mI7v1reJ12pKn8ifRiq+0q5oJST3TRSrvmjLg9Gt3ozhVIt2HUi3La7Qh40YOAUXm0g/hUq2BepeOp1C7WSvaOFHXe6Hqq", - "modulusOld": "qnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/w==", + "privateKey": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tDQpNSUlFdndJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLa3dnZ1NsQWdFQUFvSUJBUURseTkzQUpRMkdXblhDDQpYWlBLNHlDWVBjYmlLcDY4OE1qVm9COFVROU9PWjdhdmRxOG1tK0J5Z0hUODVsRVJrK0lDTWR2NmhMRXZ2dUZqDQppREY0Yzg5NlFPZThpOW1tOWJWeVpSZVZtVi84SGRJR1F0eHNxWURQZHVIZEwzcXlLd29tQVNhUDB2VEtNS3ljDQo0L2VJUGdmclhSQkdUSmluZEVNR09RQlQwY3FuSm13Y2QvcHlXK0l4cGh4MDZSZVE1MllXa3NCMWJmYkxrMjB0DQp4Q2RmeHBQbmQzdmNOUy9LRHRlOXhRVnlkNkp5Skx3K0RiWXk1RU8zWFR3RDhTcFNtd2FBbUhiQk0xd1l4cDlqDQo2UUs5YytCelEzUE8wNWxTbzNWM0VsekdZNThkS3FzZm82MkJWTG5wUllwSGZhK3lndUFxWnhMRU54bHBtZkpEDQphRU9KbUU1cEFnTUJBQUVDZ2dFQUxpTCtSS09yMFh1OEJPZ1EwajFEd0EwM0x4VnJoWGU2ZXRtSkkrSnlTVGNkDQpnS0VOald6aVpWclJJaTJEdlVtNXFNTWw3V2hTd3NsS0sxZWV4eFpKWTd4QVNxU3hjRW9Jd2d6MTdUMDcvanhtDQpmSWRVQmlVS0RaMUt2OFBXbUlyM29LVytma1hXaS9tMXpsSWUwcVhScFRtc0dORXNIUUxFcWkwcm1haVhUWE9SDQovMkxkd2k2a1pSM3NXRng5N1lTNE14L3B1ZUdKVFhFYWk2QVZFWnpONUdvZzZ4RDhIWFIxUnZxK2hoZCtNb2NHDQpmblU0SGdpbEtSZm9KbFdkOUZPc2NnU3VmS0cwTDNWaU80ZlNLVTQ2bDVhdWxsRFlVazVFQ01XaXd1S1NxU0U3DQpxRDQ1akkzbWJPcmU3UzR1M1MzVFdkRDNsendpWEw0OUxkd0tsRUM0bVFLQmdRRDBzTHIwR0g0V3IrUVgyeEpFDQp1QS9DYjhRVzQxbDhpU0NCVFJaWlIvc0pPZCtvM3JiY1ZpZGx6Ty9FYlpibFhHNFpQRG1SamdCQ0dLSVA1RVppDQowRHNMK1d2MzJXT280NExweEpHaHFFeGJtMEgxaVoxelo5N2wwUDhmdkloSEU0MmdtYUxUb09JR0RoUFNYR3Z2DQp6bHFPSGJHYnE0anNFUmMxanAxYmVqNXE2d0tCZ1FEd2F1ZUljNHBSY2hIOThRWWlkY3lyOFZ3ZzlLaGJuZllYDQp5M1c0UlBsWnRCZEYzNGlKYWlvK0FTenVnby96eTFSVGNWcnNDc2tZV1h5S0RVUXoxeXUwaUNuZytmRENVblRtDQpYR21Fb0VHTmhrNHZUSk90N2hCYXYxL0phL2RVaXBHZjZtWFV1YW53SjBlKzEvRXQvQjBhaDVYMVVtNUF5TlpJDQpNK1N5UnozdSt3S0JnUUNqdnRVTlhvcWFnaENCQ21CNlRqWjFwcmV4bldrWUZ1Z0N2MlNTVU1JazFXN2dJbEo2DQp0c2pjcmoxUjFRaWk2cXpmQkZkK0dXb0EwVjA2aDBlMi9xUlZDZy8vcDZHeXRyVzMzSXljZ3ZTK1pQTEo3dExJDQpGUjJyNjZXZlJscG9QaVNMOGVSdC9QN2trRzBoWENuN0s3dWIyVEV1L0thL1cxeU53YWQ2UFI4aUN3S0JnUUM4DQpYY1pTcnRRc3hBYzh3OTllbUpWb0VvOXdjc0NHSjlsdEEwaVV1OVh5WnB2bGJ5SjNKK3M0OFlyV3hRMHNvcDdMDQpVZ0UrOTZSZm81MWtQTWkzSlZ0azgxcDhudGY0S01yV3dva2FGTVhIc1BjSk1DSjFJQlZJUkxFMEM1ZVpjWWh2DQpseU41N0k0dFQxbHpPWllKeFlLNENvdC96cm43b0YvajZtVEJHZmg0aVFLQmdRQ2lKTVV4UnowMS9jekgvWFNYDQpnbzNkVmJIUTRGRU91ZlduRTNFYjkzUzhyMC9lcTFSTTExOHJiMFRxenVpYWRXMnhZRFU0bnVjV1FscmxtcTBkDQpGWS9tK0h5OTdwcXlrNmptb1U1SS9EK3NzQklvWUhXTG5IOS94ZnZERWsySkdTSlNIdHp1MEQ0RURDL3JnUTQ5DQpNYllzTzVvVXJGOHRQbGhqNXZ6YmYzR0tMQT09DQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tDQo=", + "publicKeyOld": "BgIAAACkAABSU0ExAAgAAAEAAQBpTpiJQ2hD8plpGTfEEmcq4IKyr31HikXpuVSBraMfqyodn2PGXBJ3daNSmdPOc0Nz4HO9Auljn8YYXDPBdpiABptSKvEDPF23Q+Qytg0+vCRyondyBcW91w7KLzXce3fnk8ZfJ8QtbZPL9m11wJIWZueQF+l0HKYx4lty+nccbCanytFTADkGQ3SnmExGEF3rBz6I9+OcrDDK9NKPJgEmCiuyei/d4XbPgKls3EIG0h38X5mVF2VytfWm2Yu850B6z3N4MYhj4b4vsYT62zEC4pMRUeb8dIBy4Jsmr3avtmeO00MUH6DVyPC8nirixj2YIOPKk13CdVqGDSXA3cvl", + "modulusOld": "E5CBDDC0250D865A75C25D93CAE320983DC6E22A9EBCF0C8D5A01F1443D38E67B6AF76AF269BE0728074FCE6511193E20231DBFA84B12FBEE16388317873CF7A40E7BC8BD9A6F5B572651795995FFC1DD20642DC6CA980CF76E1DD2F7AB22B0A2601268FD2F4CA30AC9CE3F7883E07EB5D10464C98A7744306390053D1CAA7266C1C77FA725BE231A61C74E91790E7661692C0756DF6CB936D2DC4275FC693E7777BDC352FCA0ED7BDC5057277A27224BC3E0DB632E443B75D3C03F12A529B06809876C1335C18C69F63E902BD73E0734373CED39952A37577125CC6639F1D2AAB1FA3AD8154B9E9458A477DAFB282E02A6712C437196999F243684389984E69", "exponentOld": "AQAB", - "privateKeyOld": "MIIEowIBAAKCAQEAqnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/wIDAQABAoIBAQCKtUSBs8tNYrGTQTlBHXrwpkDg+u7WSZt5sEcfnkxA39BLtlHU8gGO0E9Ihr8GAL+oWjUsEltJ9GTtN8CJ9lFdPVS8sTiCZR/YQOggmFRZTJyVzMrkXgF7Uwwiu3+KxLiTOZx9eRhfDBlTD8W9fXaegX2i2Xp2ohUhBHthEBLdaZTWFi5Sid/Y0dDzBeP6UIJorZ5D+1ybaeIVHjndpwNsIEUGUxPFLrkeiU8Rm4MJ9ahxfywcP7DjQoPGY9Ge5cBhpxfzERWf732wUD6o3+L9tvOBU00CLVjULbGZKTVE2FJMyXK9jr6Zor9Mkhomp6/8Agkr9rp+TPyelFGYEz8hAoGBAOEc09CrL3eYBkhNEcaMQzxBLvOGpg8kaDX5SaArHfl9+U9yzRqss4ARECanp9HuHfjMQo7iejao0ngDjL7BNMSaH74QlSsPOY2iOm8Qvx8/zb7g4h9r1zLjFZb3mpSA4snRZvvdiZ9ugbuVPmhXnDzRRMg45MibJeeOTJNylofRAoGBAMHfF/WutqKDoX25qZo9m74W4bttOj6oIDk1N4/c6M1Z1v/aptYSE06bkWngj9P46kqjaay4hgMtzyGruc5aojPx5MHHf5bo14+Jv4NzYtR2llrUxO+UJX7aCfUYXI7RC93GUmhpeQ414j7SNAXec58d7e+ETw+6cHiAWO4uOSTPAoGATPq5qDLR4Zi4FUNdn8LZPyKfNqHF6YmupT5hIgd8kZO1jKiaYNPL8jBjkIRmjBBcaXcYD5p85nImvumf2J9jNxPpZOpwyC/Fo5xlVROp97qu1eY7DTmodntXJ6/2SXAlnZQhHmHsrPtyG752f+HtyJJbbgiem8cKWDu+DfHybfECgYBbSLo1WiBwgN4nHqZ3E48jgA6le5azLeKOTTpuKKwNFMIhEkj//t7MYn+jhLL0Mf3PSwZU50Vidc1To1IHkbFSGBGIFHFFEzl8QnXEZS4hr/y3o/teezj0c6HAn8nlDRUzRVBEDXWMdV6kCcGpCccTIrqHzpqTY0vV0UkOTQFnDQKBgAxSEhm/gtCYJIMCBe+KBJT9uECV5xDQopTTjsGOkd4306EN2dyPOIlAfwM6K/0qWisa0Ei5i8TbRRuBeTTdLEYLqXCJ7fj5tdD1begBdSVtHQ2WHqzPJSuImTkFi9NXxd1XUyZFM3y6YQvlssSuL7QSxUIEtZHnrJTt3QDd10dj", + "privateKeyOld": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tDQpNSUlFdndJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLa3dnZ1NsQWdFQUFvSUJBUURseTkzQUpRMkdXblhDDQpYWlBLNHlDWVBjYmlLcDY4OE1qVm9COFVROU9PWjdhdmRxOG1tK0J5Z0hUODVsRVJrK0lDTWR2NmhMRXZ2dUZqDQppREY0Yzg5NlFPZThpOW1tOWJWeVpSZVZtVi84SGRJR1F0eHNxWURQZHVIZEwzcXlLd29tQVNhUDB2VEtNS3ljDQo0L2VJUGdmclhSQkdUSmluZEVNR09RQlQwY3FuSm13Y2QvcHlXK0l4cGh4MDZSZVE1MllXa3NCMWJmYkxrMjB0DQp4Q2RmeHBQbmQzdmNOUy9LRHRlOXhRVnlkNkp5Skx3K0RiWXk1RU8zWFR3RDhTcFNtd2FBbUhiQk0xd1l4cDlqDQo2UUs5YytCelEzUE8wNWxTbzNWM0VsekdZNThkS3FzZm82MkJWTG5wUllwSGZhK3lndUFxWnhMRU54bHBtZkpEDQphRU9KbUU1cEFnTUJBQUVDZ2dFQUxpTCtSS09yMFh1OEJPZ1EwajFEd0EwM0x4VnJoWGU2ZXRtSkkrSnlTVGNkDQpnS0VOald6aVpWclJJaTJEdlVtNXFNTWw3V2hTd3NsS0sxZWV4eFpKWTd4QVNxU3hjRW9Jd2d6MTdUMDcvanhtDQpmSWRVQmlVS0RaMUt2OFBXbUlyM29LVytma1hXaS9tMXpsSWUwcVhScFRtc0dORXNIUUxFcWkwcm1haVhUWE9SDQovMkxkd2k2a1pSM3NXRng5N1lTNE14L3B1ZUdKVFhFYWk2QVZFWnpONUdvZzZ4RDhIWFIxUnZxK2hoZCtNb2NHDQpmblU0SGdpbEtSZm9KbFdkOUZPc2NnU3VmS0cwTDNWaU80ZlNLVTQ2bDVhdWxsRFlVazVFQ01XaXd1S1NxU0U3DQpxRDQ1akkzbWJPcmU3UzR1M1MzVFdkRDNsendpWEw0OUxkd0tsRUM0bVFLQmdRRDBzTHIwR0g0V3IrUVgyeEpFDQp1QS9DYjhRVzQxbDhpU0NCVFJaWlIvc0pPZCtvM3JiY1ZpZGx6Ty9FYlpibFhHNFpQRG1SamdCQ0dLSVA1RVppDQowRHNMK1d2MzJXT280NExweEpHaHFFeGJtMEgxaVoxelo5N2wwUDhmdkloSEU0MmdtYUxUb09JR0RoUFNYR3Z2DQp6bHFPSGJHYnE0anNFUmMxanAxYmVqNXE2d0tCZ1FEd2F1ZUljNHBSY2hIOThRWWlkY3lyOFZ3ZzlLaGJuZllYDQp5M1c0UlBsWnRCZEYzNGlKYWlvK0FTenVnby96eTFSVGNWcnNDc2tZV1h5S0RVUXoxeXUwaUNuZytmRENVblRtDQpYR21Fb0VHTmhrNHZUSk90N2hCYXYxL0phL2RVaXBHZjZtWFV1YW53SjBlKzEvRXQvQjBhaDVYMVVtNUF5TlpJDQpNK1N5UnozdSt3S0JnUUNqdnRVTlhvcWFnaENCQ21CNlRqWjFwcmV4bldrWUZ1Z0N2MlNTVU1JazFXN2dJbEo2DQp0c2pjcmoxUjFRaWk2cXpmQkZkK0dXb0EwVjA2aDBlMi9xUlZDZy8vcDZHeXRyVzMzSXljZ3ZTK1pQTEo3dExJDQpGUjJyNjZXZlJscG9QaVNMOGVSdC9QN2trRzBoWENuN0s3dWIyVEV1L0thL1cxeU53YWQ2UFI4aUN3S0JnUUM4DQpYY1pTcnRRc3hBYzh3OTllbUpWb0VvOXdjc0NHSjlsdEEwaVV1OVh5WnB2bGJ5SjNKK3M0OFlyV3hRMHNvcDdMDQpVZ0UrOTZSZm81MWtQTWkzSlZ0azgxcDhudGY0S01yV3dva2FGTVhIc1BjSk1DSjFJQlZJUkxFMEM1ZVpjWWh2DQpseU41N0k0dFQxbHpPWllKeFlLNENvdC96cm43b0YvajZtVEJHZmg0aVFLQmdRQ2lKTVV4UnowMS9jekgvWFNYDQpnbzNkVmJIUTRGRU91ZlduRTNFYjkzUzhyMC9lcTFSTTExOHJiMFRxenVpYWRXMnhZRFU0bnVjV1FscmxtcTBkDQpGWS9tK0h5OTdwcXlrNmptb1U1SS9EK3NzQklvWUhXTG5IOS94ZnZERWsySkdTSlNIdHp1MEQ0RURDL3JnUTQ5DQpNYllzTzVvVXJGOHRQbGhqNXZ6YmYzR0tMQT09DQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tDQo=", "refreshLockInterval": "10m", "dummy" : { "enable": false, diff --git a/DocService/sources/canvasservice.js b/DocService/sources/canvasservice.js index c34b8b17..6cbfcdb2 100644 --- a/DocService/sources/canvasservice.js +++ b/DocService/sources/canvasservice.js @@ -1646,7 +1646,7 @@ exports.downloadFile = function(req, res) { //editnew case fromTemplate = pathModule.extname(decoded.fileInfo.BaseFileName).substring(1); } else { - ({url, headers} = wopiClient.getWopiFileUrl(ctx, decoded.fileInfo, decoded.userAuth)); + ({url, headers} = yield wopiClient.getWopiFileUrl(ctx, decoded.fileInfo, decoded.userAuth)); let filterStatus = yield wopiClient.checkIpFilter(ctx, url); if (0 === filterStatus) { //todo false? (true because it passed checkIpFilter for wopi) diff --git a/DocService/sources/wopiClient.js b/DocService/sources/wopiClient.js index 3272e410..818c1f7f 100644 --- a/DocService/sources/wopiClient.js +++ b/DocService/sources/wopiClient.js @@ -35,6 +35,7 @@ const path = require('path'); const { pipeline } = require('node:stream/promises'); const crypto = require('crypto'); +let util = require('util'); const {URL} = require('url'); const co = require('co'); const jwt = require('jsonwebtoken'); @@ -90,6 +91,8 @@ const cfgWopiPrivateKeyOld = config.get('wopi.privateKeyOld'); const cfgWopiHost = config.get('wopi.host'); const cfgWopiDummySampleFilePath = config.get('wopi.dummy.sampleFilePath'); +let cryptoSign = util.promisify(crypto.sign); + let templatesFolderLocalesCache = null; let templatesFolderExtsCache = null; const templateFilesSizeCache = {}; @@ -334,7 +337,7 @@ function getFileTypeByInfo(fileInfo) { fileType = fileInfo.FileExtension ? fileInfo.FileExtension.substr(1) : fileType; return fileType.toLowerCase(); } -function getWopiFileUrl(ctx, fileInfo, userAuth) { +async function getWopiFileUrl(ctx, fileInfo, userAuth) { const tenMaxDownloadBytes = ctx.getCfg('FileConverter.converter.maxDownloadBytes', cfgMaxDownloadBytes); let url; let headers = {'X-WOPI-MaxExpectedSize': tenMaxDownloadBytes}; @@ -345,7 +348,7 @@ function getWopiFileUrl(ctx, fileInfo, userAuth) { url = fileInfo.TemplateSource; } else if (userAuth) { url = `${userAuth.wopiSrc}/contents?access_token=${userAuth.access_token}`; - fillStandardHeaders(ctx, headers, url, userAuth.access_token); + await fillStandardHeaders(ctx, headers, url, userAuth.access_token); } ctx.logger.debug('getWopiFileUrl url=%s; headers=%j', url, headers); return {url, headers}; @@ -660,7 +663,7 @@ function putFile(ctx, wopiParams, data, dataStream, dataSize, userLastChangeId, let commonInfo = wopiParams.commonInfo; //todo add all the users who contributed changes to the document in this PutFile request to X-WOPI-Editors let headers = {'X-WOPI-Override': 'PUT', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-Editors': userLastChangeId}; - fillStandardHeaders(ctx, headers, uri, userAuth.access_token); + yield fillStandardHeaders(ctx, headers, uri, userAuth.access_token); headers['X-LOOL-WOPI-IsModifiedByUser'] = isModifiedByUser; headers['X-LOOL-WOPI-IsAutosave'] = isAutosave; headers['X-LOOL-WOPI-IsExitSave'] = isExitSave; @@ -702,7 +705,7 @@ function putRelativeFile(ctx, wopiSrc, access_token, data, dataStream, dataSize, if (isFileConversion) { headers['X-WOPI-FileConversion'] = isFileConversion; } - fillStandardHeaders(ctx, headers, uri, access_token); + yield fillStandardHeaders(ctx, headers, uri, access_token); headers['Content-Type'] = mime.getType(suggestedTarget); ctx.logger.debug('wopi putRelativeFile request uri=%s headers=%j', uri, headers); @@ -741,7 +744,7 @@ function renameFile(ctx, wopiParams, name) { let commonInfo = wopiParams.commonInfo; let headers = {'X-WOPI-Override': 'RENAME_FILE', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-RequestedName': utf7.encode(name)}; - fillStandardHeaders(ctx, headers, uri, userAuth.access_token); + yield fillStandardHeaders(ctx, headers, uri, userAuth.access_token); ctx.logger.debug('wopi RenameFile request uri=%s headers=%j', uri, headers); let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers); @@ -779,7 +782,7 @@ function checkFileInfo(ctx, wopiSrc, access_token, opt_sc) { if (opt_sc) { headers['X-WOPI-SessionContext'] = opt_sc; } - fillStandardHeaders(ctx, headers, uri, access_token); + yield fillStandardHeaders(ctx, headers, uri, access_token); ctx.logger.debug('wopi checkFileInfo request uri=%s headers=%j', uri, headers); //todo false? (true because it passed checkIpFilter for wopi) //todo use directIfIn @@ -815,7 +818,7 @@ function lock(ctx, command, lockId, fileInfo, userAuth) { } let headers = {"X-WOPI-Override": command, "X-WOPI-Lock": lockId}; - fillStandardHeaders(ctx, headers, uri, access_token); + yield fillStandardHeaders(ctx, headers, uri, access_token); ctx.logger.debug('wopi %s request uri=%s headers=%j', command, uri, headers); let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers); ctx.logger.debug('wopi %s response headers=%j', command, postRes.response.headers); @@ -852,7 +855,7 @@ function unlock(ctx, wopiParams) { } let headers = {"X-WOPI-Override": "UNLOCK", "X-WOPI-Lock": lockId}; - fillStandardHeaders(ctx, headers, uri, access_token); + yield fillStandardHeaders(ctx, headers, uri, access_token); ctx.logger.debug('wopi Unlock request uri=%s headers=%j', uri, headers); let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers); ctx.logger.debug('wopi Unlock response headers=%j', postRes.response.headers); @@ -885,28 +888,20 @@ function generateProofBuffer(url, accessToken, timeStamp) { buffer.writeBigUInt64BE(timeStamp, offset); return buffer; } -function generateProofSign(url, accessToken, timeStamp, privateKey) { - let signer = crypto.createSign('RSA-SHA256'); - signer.update(generateProofBuffer(url, accessToken, timeStamp)); - return signer.sign({key:privateKey}, "base64"); + +async function generateProofSign(url, accessToken, timeStamp, privateKey) { + let data = generateProofBuffer(url, accessToken, timeStamp); + let sign = await cryptoSign('RSA-SHA256', data, privateKey); + return sign.toString('base64'); } -function generateProof(ctx, url, accessToken, timeStamp) { - const tenWopiPrivateKey = ctx.getCfg('wopi.privateKey', cfgWopiPrivateKey); - let privateKey = `-----BEGIN RSA PRIVATE KEY-----\n${tenWopiPrivateKey}\n-----END RSA PRIVATE KEY-----`; - return generateProofSign(url, accessToken, timeStamp, privateKey); -} -function generateProofOld(ctx, url, accessToken, timeStamp) { - const tenWopiPrivateKeyOld = ctx.getCfg('wopi.privateKeyOld', cfgWopiPrivateKeyOld); - let privateKey = `-----BEGIN RSA PRIVATE KEY-----\n${tenWopiPrivateKeyOld}\n-----END RSA PRIVATE KEY-----`; - return generateProofSign(url, accessToken, timeStamp, privateKey); -} -function fillStandardHeaders(ctx, headers, url, access_token) { + +async function fillStandardHeaders(ctx, headers, url, access_token) { let timeStamp = utils.getDateTimeTicks(new Date()); const tenWopiPrivateKey = ctx.getCfg('wopi.privateKey', cfgWopiPrivateKey); const tenWopiPrivateKeyOld = ctx.getCfg('wopi.privateKeyOld', cfgWopiPrivateKeyOld); if (tenWopiPrivateKey && tenWopiPrivateKeyOld) { - headers['X-WOPI-Proof'] = generateProof(ctx, url, access_token, timeStamp); - headers['X-WOPI-ProofOld'] = generateProofOld(ctx, url, access_token, timeStamp); + headers['X-WOPI-Proof'] = await generateProofSign(url, access_token, timeStamp, Buffer.from(tenWopiPrivateKey, 'base64')); + headers['X-WOPI-ProofOld'] = await generateProofSign(url, access_token, timeStamp, Buffer.from(tenWopiPrivateKeyOld, 'base64')); headers['X-WOPI-TimeStamp'] = timeStamp; headers['X-WOPI-ClientVersion'] = commonDefines.buildVersion + '.' + commonDefines.buildNumber; // todo @@ -1019,8 +1014,6 @@ exports.putRelativeFile = putRelativeFile; exports.renameFile = renameFile; exports.lock = lock; exports.unlock = unlock; -exports.generateProof = generateProof; -exports.generateProofOld = generateProofOld; exports.fillStandardHeaders = fillStandardHeaders; exports.getWopiUnlockMarker = getWopiUnlockMarker; exports.getWopiModifiedMarker = getWopiModifiedMarker; diff --git a/FileConverter/sources/converter.js b/FileConverter/sources/converter.js index fb80e2af..fc14c271 100644 --- a/FileConverter/sources/converter.js +++ b/FileConverter/sources/converter.js @@ -1050,7 +1050,7 @@ function* ExecuteTask(ctx, task) { isInJwtToken = true; let fileInfo = wopiParams.commonInfo?.fileInfo; fileSize = fileInfo?.Size; - ({url, headers} = wopiClient.getWopiFileUrl(ctx, fileInfo, wopiParams.userAuth)); + ({url, headers} = yield wopiClient.getWopiFileUrl(ctx, fileInfo, wopiParams.userAuth)); } if (undefined === fileSize || fileSize > 0) { error = yield* downloadFile(ctx, url, dataConvert.fileFrom, withAuthorization, isInJwtToken, headers);