diff --git a/test/general/key.js b/test/general/key.js index c79e6c1e..703b1a64 100644 --- a/test/general/key.js +++ b/test/general/key.js @@ -6,424 +6,8 @@ chai.use(require('chai-as-promised')); const { expect } = chai; -describe('Key', function() { - let rsaGenStub; - let rsaGenValue = openpgp.crypto.publicKey.rsa.generate(openpgp.util.getWebCryptoAll() ? 2048 : 512, "10001"); - - beforeEach(function() { - rsaGenStub = stub(openpgp.crypto.publicKey.rsa, 'generate'); - rsaGenStub.returns(rsaGenValue); - }); - - afterEach(function() { - rsaGenStub.restore(); - }); - - describe('V4', tests); - - describe('V5', function() { - let aead_protectVal; - let aead_protect_versionVal; - beforeEach(function() { - aead_protectVal = openpgp.config.aead_protect; - aead_protect_versionVal = openpgp.config.aead_protect_version; - openpgp.config.aead_protect = true; - openpgp.config.aead_protect_version = 4; - }); - afterEach(function() { - openpgp.config.aead_protect = aead_protectVal; - openpgp.config.aead_protect_version = aead_protect_versionVal; - }); - - tests(); - }); -}); - -function tests() { - const priv_key_arm2 = - ['-----BEGIN PGP PRIVATE KEY BLOCK-----', - 'Version: GnuPG v2.0.19 (GNU/Linux)', - '', - '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', - '=lw5e', - '-----END PGP PRIVATE KEY BLOCK-----'].join('\n'); - - const pub_key_arm2 = - ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: GnuPG v2.0.19 (GNU/Linux)', - '', - 'mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+', - 'fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5', - 'GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0', - 'JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS', - 'YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6', - 'AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki', - 'Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf', - '9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa', - 'JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag', - 'Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr', - 'woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb', - 'LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA', - 'SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP', - 'GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2', - 'bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X', - 'W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD', - 'AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY', - 'hz3tYjKhoFTKEIq3y3Pp', - '=h/aX', - '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - - const pub_key_arm4 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG 2.1.15 (GNU/Linux) - -mI0EWpoNLAEEAMoO8dfnLvvCze1hjWcr8t1fMdndFQc1fAM7dm6sbqrdlaAz+Dab -zF3F9UhIOCcABRm+QHyZlgEsoQpHF/7sWflUK1FpoxdORINtIDilukUkMZ0NnIaD -+8pRutdSczPNFvSImSzZNCyLzvDCGMO3+Xeaa6pViSPEeBwhXWJUuHYtABEBAAG0 -IkpvZSBVc2VyIDxqb2UudXNlckBwcm90b25tYWlsLmNvbT6ItwQTAQgAIQUCWpoN -LAIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBYtrN4WUnCtoUjBACi6qVb -noQJ1aOaOyoBZscDIO5XZHZK4L9V9uJJhD9v1qRF5s0PRiG969EwFlvjqIlLiRej -KSxvE/1rcym4GwBUndku1fMM+weTWHNtRn9+BPzN/4eKZbUbY3fHtlk+Lde3N+CZ -vrGKS/ICtbtuAfZL0LdzzqnNuBUXlO6EpG5C3riNBFqaDSwBBADDURzGkpTn/FTT -xHyheai+zTOUmy7N1ViCRPkErIeD606tZf/sKqAnEChfECeZJReYydN1B3O8QOyI -Ly/rH0DS2bt/6juhknPVGHPUAyNxHmiHYXTUgGPEX1QfusjzBcfIk6vHjYBiRm/I -u9iwrzCwypA4dWDZSTZuFrVsf4n+twARAQABiJ8EGAEIAAkFAlqaDSwCGwwACgkQ -WLazeFlJwrZQEAQAuUrp9Qp76CnKqUsUjcVxq7DJBi/lewyGGYSVAFt6/0Xyg/8Y -TEa/c4Dri/HMOtrfbgjp/doIVaZLOXZYfqRcpy3z0M6BierOPB3D+fdaTfd7gIrQ -nGHIp2NmbJZnYgl8Ps23qF+LKTa1eE+AmMQYzUHSGuka2lp6OglwWzg/dEw= -=/vbH ------END PGP PUBLIC KEY BLOCK-----`; - - const priv_key_arm4 = `-----BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG 2.1.15 (GNU/Linux) - -lQIGBFqaDSwBBADKDvHX5y77ws3tYY1nK/LdXzHZ3RUHNXwDO3ZurG6q3ZWgM/g2 -m8xdxfVISDgnAAUZvkB8mZYBLKEKRxf+7Fn5VCtRaaMXTkSDbSA4pbpFJDGdDZyG -g/vKUbrXUnMzzRb0iJks2TQsi87wwhjDt/l3mmuqVYkjxHgcIV1iVLh2LQARAQAB -/gcDAoZ8RULY7umS4fVGPmTuETCnOOTGancXT5r7chKyfFXlyVU4ULvTdLwdFtqx -Vl9tNyED31nIiRP1CTmZLeaVScNGfVLjo8nvpMZUVopw5UdaFADeVTpwVdtp7ru+ -IgH4ynrRMgMGh7/dgBzIP8WN4w8uBPK5G4bS34NNiREkVoZ3oh4dA/6aeYfW7lVV -cYRl2F7++AGfqS+FpLsE8KjFU2z8POJjWMN1nYKwjNa+beEO0BFYdUFvMzU7eUHA -/G0xWAhYvNyuJHE4imgYmCy1OZeawc9h8YGeaQJCh2NTVzaD9HRu0xmz93bNF19q -bfUZJC7mC6WzKsRXHX0JmzH+9DShUqGnkRl5fMo2UhQMpSxsMT4dU/Ji4q+t96oy -K6g3DMJr5OtZML3XKxGmdy0CgepkG1aikrC9qLfBgxjqi+uTewcbrS9lAOfrZg4N -jwt1FLEK8gu7aOeczdW/pFOHOCrX1DnpF81JKJ1a7hz5JRP1m+ffqwm0IkpvZSBV -c2VyIDxqb2UudXNlckBwcm90b25tYWlsLmNvbT6ItwQTAQgAIQUCWpoNLAIbAwUL -CQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBYtrN4WUnCtoUjBACi6qVbnoQJ1aOa -OyoBZscDIO5XZHZK4L9V9uJJhD9v1qRF5s0PRiG969EwFlvjqIlLiRejKSxvE/1r -cym4GwBUndku1fMM+weTWHNtRn9+BPzN/4eKZbUbY3fHtlk+Lde3N+CZvrGKS/IC -tbtuAfZL0LdzzqnNuBUXlO6EpG5C3p0CBgRamg0sAQQAw1EcxpKU5/xU08R8oXmo -vs0zlJsuzdVYgkT5BKyHg+tOrWX/7CqgJxAoXxAnmSUXmMnTdQdzvEDsiC8v6x9A -0tm7f+o7oZJz1Rhz1AMjcR5oh2F01IBjxF9UH7rI8wXHyJOrx42AYkZvyLvYsK8w -sMqQOHVg2Uk2bha1bH+J/rcAEQEAAf4HAwLwNvRIoBFS3OHTIYirkr4sHzSkWFJx -xDPozovXgCq7BoCXDMaSIQLwZqEfb+SabYtk7nLSnG2Y2mgwb9swZuBZEWuQjZk7 -lX1MvuZ0Ih2QdQSMEJk8sEsMoBGHHdHh/MZO4a27+5B9OceDfnEZZcGSOweUuu1n -IlgWcgrM40q4S3Mt39FXFgdJWnpd93hAokKDHklUGMdMLw/02dGVRkJmvUp9qdhe -c2njq9HSeYwqbY2rYgcNsF2ZcCLt9UXA2dOG4X2c2mPfjKuTRZUPxNKh6JfL3mlu -rBdd/z8gQHoKObyaarVwN3HAbtP0+6Z8a9/wDYj1K9ZCoHuEtKq1qq5J2Ec8+Yzl -K0Zlcs760LiYUr69CninMrnbDNnAhrYAcyJS42viUADPv9g+CBbyanB4KyE4UNrZ -BCB296lOEW4v1IZVNrNvqrbka3/p0qqBJiFTh7eT3zXpRNArFZDmLCUEEm53qT1a -PO/MyYUGTTMRAzTmNTiPiJ8EGAEIAAkFAlqaDSwCGwwACgkQWLazeFlJwrZQEAQA -uUrp9Qp76CnKqUsUjcVxq7DJBi/lewyGGYSVAFt6/0Xyg/8YTEa/c4Dri/HMOtrf -bgjp/doIVaZLOXZYfqRcpy3z0M6BierOPB3D+fdaTfd7gIrQnGHIp2NmbJZnYgl8 -Ps23qF+LKTa1eE+AmMQYzUHSGuka2lp6OglwWzg/dEw= -=mr3M ------END PGP PRIVATE KEY BLOCK-----`; - - const revocation_certificate_arm4 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG 2.1.15 (GNU/Linux) -Comment: This is a revocation certificate - -iJ8EIAEIAAkFAlqaDT0CHQAACgkQWLazeFlJwrbOaAP/V38FhBrUy4XYgt8ZX22G -ov6IFDNoyRKafSuz7Rg+8K8cf+0MAsSi52ueKfsbPxQ+I1vPeaEuEYbwTjtbvM+M -vZcX+VNYdsc1iZeNaT4ayA+2LrCN/xgFj0nrExHqcZAjgBZ9pvKghAqdK4Zb2Ghb -7chPiLLNWJCMtL4bo7a1X84= -=HcWg ------END PGP PUBLIC KEY BLOCK-----`; - - const revoked_key_arm4 = `-----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG 2.1.15 (GNU/Linux) - -mI0EWpoNLAEEAMoO8dfnLvvCze1hjWcr8t1fMdndFQc1fAM7dm6sbqrdlaAz+Dab -zF3F9UhIOCcABRm+QHyZlgEsoQpHF/7sWflUK1FpoxdORINtIDilukUkMZ0NnIaD -+8pRutdSczPNFvSImSzZNCyLzvDCGMO3+Xeaa6pViSPEeBwhXWJUuHYtABEBAAGI -nwQgAQgACQUCWpoNPQIdAAAKCRBYtrN4WUnCts5oA/9XfwWEGtTLhdiC3xlfbYai -/ogUM2jJEpp9K7PtGD7wrxx/7QwCxKLna54p+xs/FD4jW895oS4RhvBOO1u8z4y9 -lxf5U1h2xzWJl41pPhrID7YusI3/GAWPSesTEepxkCOAFn2m8qCECp0rhlvYaFvt -yE+Iss1YkIy0vhujtrVfzrQiSm9lIFVzZXIgPGpvZS51c2VyQHByb3Rvbm1haWwu -Y29tPoi3BBMBCAAhBQJamg0sAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJ -EFi2s3hZScK2hSMEAKLqpVuehAnVo5o7KgFmxwMg7ldkdkrgv1X24kmEP2/WpEXm -zQ9GIb3r0TAWW+OoiUuJF6MpLG8T/WtzKbgbAFSd2S7V8wz7B5NYc21Gf34E/M3/ -h4pltRtjd8e2WT4t17c34Jm+sYpL8gK1u24B9kvQt3POqc24FReU7oSkbkLeuI0E -WpoNLAEEAMNRHMaSlOf8VNPEfKF5qL7NM5SbLs3VWIJE+QSsh4PrTq1l/+wqoCcQ -KF8QJ5klF5jJ03UHc7xA7IgvL+sfQNLZu3/qO6GSc9UYc9QDI3EeaIdhdNSAY8Rf -VB+6yPMFx8iTq8eNgGJGb8i72LCvMLDKkDh1YNlJNm4WtWx/if63ABEBAAGInwQY -AQgACQUCWpoNLAIbDAAKCRBYtrN4WUnCtlAQBAC5Sun1CnvoKcqpSxSNxXGrsMkG -L+V7DIYZhJUAW3r/RfKD/xhMRr9zgOuL8cw62t9uCOn92ghVpks5dlh+pFynLfPQ -zoGJ6s48HcP591pN93uAitCcYcinY2ZslmdiCXw+zbeoX4spNrV4T4CYxBjNQdIa -6RraWno6CXBbOD90TA== -=8d2d ------END PGP PUBLIC KEY BLOCK-----`; - - const twoKeys = - ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: GnuPG v2.0.19 (GNU/Linux)', - '', - 'mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+', - 'fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5', - 'GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0', - 'JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS', - 'YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6', - 'AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki', - 'Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf', - '9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa', - 'JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag', - 'Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr', - 'woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb', - 'LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA', - 'SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP', - 'GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2', - 'bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X', - 'W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD', - 'AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY', - 'hz3tYjKhoFTKEIq3y3PpmQENBFKV0FUBCACtZliApy01KBGbGNB36YGH4lpr+5Ko', - 'qF1I8A5IT0YeNjyGisOkWsDsUzOqaNvgzQ82I3MY/jQV5rLBhH/6LiRmCA16WkKc', - 'qBrHfNGIxJ+Q+ofVBHUbaS9ClXYI88j747QgWzirnLuEA0GfilRZcewII1pDA/G7', - '+m1HwV4qHsPataYLeboqhPA3h1EVVQFMAcwlqjOuS8+weHQRfNVRGQdRMm6H7166', - 'PseDVRUHdkJpVaKFhptgrDoNI0lO+UujdqeF1o5tVZ0j/s7RbyBvdLTXNuBbcpq9', - '3ceSWuJPZmi1XztQXKYey0f+ltgVtZDEc7TGV5WDX9erRECCcA3+s7J3ABEBAAG0', - 'G0pTIENyeXB0byA8ZGlmZmllQGhvbWUub3JnPokBPwQTAQIAKQUCUpXQVQIbAwUJ', - 'CWYBgAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJENvyI+hwU030yRAIAKX/', - 'mGEgi/miqasbbQoyK/CSa7sRxgZwOWQLdi2xxpE5V4W4HJIDNLJs5vGpRN4mmcNK', - '2fmJAh74w0PskmVgJEhPdFJ14UC3fFPq5nbqkBl7hU0tDP5jZxo9ruQZfDOWpHKx', - 'OCz5guYJ0CW97bz4fChZNFDyfU7VsJQwRIoViVcMCipP0fVZQkIhhwpzQpmVmN8E', - '0a6jWezTZv1YpMdlzbEfH79l3StaOh9/Un9CkIyqEWdYiKvIYms9nENyehN7r/OK', - 'YN3SW+qlt5GaL+ws+N1w6kEZjPFwnsr+Y4A3oHcAwXq7nfOz71USojSmmo8pgdN8', - 'je16CP98vw3/k6TncLS5AQ0EUpXQVQEIAMEjHMeqg7B04FliUFWr/8C6sJDb492M', - 'lGAWgghIbnuJfXAnUGdNoAzn0S+n93Y/qHbW6YcjHD4/G+kK3MuxthAFqcVjdHZQ', - 'XK0rkhXO/u1co7v1cdtkOTEcyOpyLXolM/1S2UYImhrml7YulTHMnWVja7xu6QIR', - 'so+7HBFT/u9D47L/xXrXMzXFVZfBtVY+yoeTrOY3OX9cBMOAu0kuN9eT18Yv2yi6', - 'XMzP3iONVHtl6HfFrAA7kAtx4ne0jgAPWZ+a8hMy59on2ZFs/AvSpJtSc1kw/vMT', - 'WkyVP1Ky20vAPHQ6Ej5q1NGJ/JbcFgolvEeI/3uDueLjj4SdSIbLOXMAEQEAAYkB', - 'JQQYAQIADwUCUpXQVQIbDAUJCWYBgAAKCRDb8iPocFNN9NLkB/wO4iRxia0zf4Kw', - '2RLVZG8qcuo3Bw9UTXYYlI0AutoLNnSURMLLCq6rcJ0BCXGj/2iZ0NBxZq3t5vbR', - 'h6uUv+hpiSxK1nF7AheN4aAAzhbWx0UDTF04ebG/neE4uDklRIJLhif6+Bwu+EUe', - 'TlGbDj7fqGSsNe8g92w71e41rF/9CMoOswrKgIjXAou3aexogWcHvKY2D+1q9exO', - 'Re1rIa1+sUGl5PG2wsEsznN6qtN5gMlGY1ofWDY+I02gO4qzaZ/FxRZfittCw7v5', - 'dmQYKot9qRi2Kx3Fvw+hivFBpC4TWgppFBnJJnAsFXZJQcejMW4nEmOViRQXY8N8', - 'PepQmgsu', - '=w6wd', - '-----END PGP PUBLIC KEY BLOCK-----'].join("\n"); - - const pub_revoked_subkeys = - ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: GnuPG v2.0.19 (GNU/Linux)', - '', - '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', - 'pMiJM+NJAQ==', - '=ok+o', - '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - - const pub_revoked_with_cert = - ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Comment: GPGTools - https://gpgtools.org', - '', - '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', - 'onCOcv4DKguN2w==', - '=OqO3', - '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - - const pub_sig_test = - ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: GnuPG v2.0.19 (GNU/Linux)', - '', - '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', - 'yeSTTh8ZnzRiwuUH1t90E7w=', - '=e8xo', - '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - - const priv_key_rsa = - ['-----BEGIN PGP PRIVATE KEY BLOCK-----', +const priv_key_arm2 = + ['-----BEGIN PGP PRIVATE KEY BLOCK-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', 'lQH+BFJhL04BBADclrUEDDsm0PSZbQ6pml9FpzTyXiyCyDN+rMOsy9J300Oc10kt', @@ -462,9 +46,9 @@ zoGJ6s48HcP591pN93uAitCcYcinY2ZslmdiCXw+zbeoX4spNrV4T4CYxBjNQdIa '=lw5e', '-----END PGP PRIVATE KEY BLOCK-----'].join('\n'); - const user_attr_key = - ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: GnuPG v2.0.22 (GNU/Linux)', +const pub_key_arm2 = + ['-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Version: GnuPG v2.0.19 (GNU/Linux)', '', 'mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+', 'fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5', @@ -473,430 +57,803 @@ zoGJ6s48HcP591pN93uAitCcYcinY2ZslmdiCXw+zbeoX4spNrV4T4CYxBjNQdIa 'YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6', 'AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki', 'Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf', - '9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rDRwc7BzAEQAAEBAAAAAAAA', - 'AAAAAAAA/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQN', - 'DAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/', - '2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy', - 'MjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAFABQDASIAAhEBAxEB/8QAHwAAAQUB', - 'AQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQID', - 'AAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0', - 'NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKT', - 'lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl', - '5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL', - '/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHB', - 'CSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpj', - 'ZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3', - 'uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIR', - 'AxEAPwD3+iiigAooooA//9mIuQQTAQIAIwUCUzxDqQIbLwcLCQgHAwIBBhUIAgkK', - 'CwQWAgMBAh4BAheAAAoJEEpjYTpNbkCU9PEEAKMMaXjhGdgDISBXAAEVXL6MB3x1', - 'd/7zBdnUljh1gM34TSKvbeZf7h/1DNgLbJFfSF3KiLViiqRVOumIkjwNIMZPqYtu', - 'WoEcElY50mvTETzOKemCt1GYI0GhOY2uZOVRtQLrkX0CB9r5hEQalkrnjNKlbghj', - 'LfOYu1uARF16cZUWuI0EUmEvTgEEAOkfz7QRWiWk+I6tdMqgEpOLKsFTLHOh3Inz', - 'OZUnccxMRT++J2lDDMhLChz+d0MUxdBq6rrGoEIP2bYE9AjdR1DNedsuwAjnadYI', - 'io6TMzk0ApagqHJcr1jhQfi/0sBhCCX+y0ghK8KAbiYnyXPMQFa9F19CbYaFvrj/', - 'dXk0N16bABEBAAGJAT0EGAECAAkFAlJhL04CGy4AqAkQSmNhOk1uQJSdIAQZAQIA', - 'BgUCUmEvTgAKCRDghPdEbCAsl7qiBADZpokQgEhe2Cuz7xZIniTcM3itFdxdpRl/', - 'rrumN0P2cXbcHOMUfpnvwkgZrFEcl0ztvTloTxi7Mzx/c0iVPQXQ4ur9Mjaa5hT1', - '/9TYNAG5/7ApMHrb48QtWCL0yxcLVC/+7+jUtm2abFMUU4PfnEqzFlkjY4mPalCm', - 'o5tbbszw2VwFBADDZgDd8Vzfyo8r49jitnJNF1u+PLJf7XN6oijzCftAJDBez44Z', - 'ofZ8ahPfkAhJe6opxaqgS47s4FIQVOEJcF9RgwLTU6uooSzA+b9XfNmQu7TWrXZQ', - 'zBlpyHbxDAr9hmXLiKg0Pa11rOPXu7atTZ3C2Ic97WIyoaBUyhCKt8tz6Q==', - '=MVfN', + '9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa', + 'JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag', + 'Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr', + 'woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb', + 'LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA', + 'SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP', + 'GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2', + 'bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X', + 'W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD', + 'AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY', + 'hz3tYjKhoFTKEIq3y3Pp', + '=h/aX', '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - const pgp_desktop_pub = +const pub_key_arm4 = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG 2.1.15 (GNU/Linux) + +mI0EWpoNLAEEAMoO8dfnLvvCze1hjWcr8t1fMdndFQc1fAM7dm6sbqrdlaAz+Dab +zF3F9UhIOCcABRm+QHyZlgEsoQpHF/7sWflUK1FpoxdORINtIDilukUkMZ0NnIaD ++8pRutdSczPNFvSImSzZNCyLzvDCGMO3+Xeaa6pViSPEeBwhXWJUuHYtABEBAAG0 +IkpvZSBVc2VyIDxqb2UudXNlckBwcm90b25tYWlsLmNvbT6ItwQTAQgAIQUCWpoN +LAIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBYtrN4WUnCtoUjBACi6qVb +noQJ1aOaOyoBZscDIO5XZHZK4L9V9uJJhD9v1qRF5s0PRiG969EwFlvjqIlLiRej +KSxvE/1rcym4GwBUndku1fMM+weTWHNtRn9+BPzN/4eKZbUbY3fHtlk+Lde3N+CZ +vrGKS/ICtbtuAfZL0LdzzqnNuBUXlO6EpG5C3riNBFqaDSwBBADDURzGkpTn/FTT +xHyheai+zTOUmy7N1ViCRPkErIeD606tZf/sKqAnEChfECeZJReYydN1B3O8QOyI +Ly/rH0DS2bt/6juhknPVGHPUAyNxHmiHYXTUgGPEX1QfusjzBcfIk6vHjYBiRm/I +u9iwrzCwypA4dWDZSTZuFrVsf4n+twARAQABiJ8EGAEIAAkFAlqaDSwCGwwACgkQ +WLazeFlJwrZQEAQAuUrp9Qp76CnKqUsUjcVxq7DJBi/lewyGGYSVAFt6/0Xyg/8Y +TEa/c4Dri/HMOtrfbgjp/doIVaZLOXZYfqRcpy3z0M6BierOPB3D+fdaTfd7gIrQ +nGHIp2NmbJZnYgl8Ps23qF+LKTa1eE+AmMQYzUHSGuka2lp6OglwWzg/dEw= +=/vbH +-----END PGP PUBLIC KEY BLOCK-----`; + +const priv_key_arm4 = `-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG 2.1.15 (GNU/Linux) + +lQIGBFqaDSwBBADKDvHX5y77ws3tYY1nK/LdXzHZ3RUHNXwDO3ZurG6q3ZWgM/g2 +m8xdxfVISDgnAAUZvkB8mZYBLKEKRxf+7Fn5VCtRaaMXTkSDbSA4pbpFJDGdDZyG +g/vKUbrXUnMzzRb0iJks2TQsi87wwhjDt/l3mmuqVYkjxHgcIV1iVLh2LQARAQAB +/gcDAoZ8RULY7umS4fVGPmTuETCnOOTGancXT5r7chKyfFXlyVU4ULvTdLwdFtqx +Vl9tNyED31nIiRP1CTmZLeaVScNGfVLjo8nvpMZUVopw5UdaFADeVTpwVdtp7ru+ +IgH4ynrRMgMGh7/dgBzIP8WN4w8uBPK5G4bS34NNiREkVoZ3oh4dA/6aeYfW7lVV +cYRl2F7++AGfqS+FpLsE8KjFU2z8POJjWMN1nYKwjNa+beEO0BFYdUFvMzU7eUHA +/G0xWAhYvNyuJHE4imgYmCy1OZeawc9h8YGeaQJCh2NTVzaD9HRu0xmz93bNF19q +bfUZJC7mC6WzKsRXHX0JmzH+9DShUqGnkRl5fMo2UhQMpSxsMT4dU/Ji4q+t96oy +K6g3DMJr5OtZML3XKxGmdy0CgepkG1aikrC9qLfBgxjqi+uTewcbrS9lAOfrZg4N +jwt1FLEK8gu7aOeczdW/pFOHOCrX1DnpF81JKJ1a7hz5JRP1m+ffqwm0IkpvZSBV +c2VyIDxqb2UudXNlckBwcm90b25tYWlsLmNvbT6ItwQTAQgAIQUCWpoNLAIbAwUL +CQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRBYtrN4WUnCtoUjBACi6qVbnoQJ1aOa +OyoBZscDIO5XZHZK4L9V9uJJhD9v1qRF5s0PRiG969EwFlvjqIlLiRejKSxvE/1r +cym4GwBUndku1fMM+weTWHNtRn9+BPzN/4eKZbUbY3fHtlk+Lde3N+CZvrGKS/IC +tbtuAfZL0LdzzqnNuBUXlO6EpG5C3p0CBgRamg0sAQQAw1EcxpKU5/xU08R8oXmo +vs0zlJsuzdVYgkT5BKyHg+tOrWX/7CqgJxAoXxAnmSUXmMnTdQdzvEDsiC8v6x9A +0tm7f+o7oZJz1Rhz1AMjcR5oh2F01IBjxF9UH7rI8wXHyJOrx42AYkZvyLvYsK8w +sMqQOHVg2Uk2bha1bH+J/rcAEQEAAf4HAwLwNvRIoBFS3OHTIYirkr4sHzSkWFJx +xDPozovXgCq7BoCXDMaSIQLwZqEfb+SabYtk7nLSnG2Y2mgwb9swZuBZEWuQjZk7 +lX1MvuZ0Ih2QdQSMEJk8sEsMoBGHHdHh/MZO4a27+5B9OceDfnEZZcGSOweUuu1n +IlgWcgrM40q4S3Mt39FXFgdJWnpd93hAokKDHklUGMdMLw/02dGVRkJmvUp9qdhe +c2njq9HSeYwqbY2rYgcNsF2ZcCLt9UXA2dOG4X2c2mPfjKuTRZUPxNKh6JfL3mlu +rBdd/z8gQHoKObyaarVwN3HAbtP0+6Z8a9/wDYj1K9ZCoHuEtKq1qq5J2Ec8+Yzl +K0Zlcs760LiYUr69CninMrnbDNnAhrYAcyJS42viUADPv9g+CBbyanB4KyE4UNrZ +BCB296lOEW4v1IZVNrNvqrbka3/p0qqBJiFTh7eT3zXpRNArFZDmLCUEEm53qT1a +PO/MyYUGTTMRAzTmNTiPiJ8EGAEIAAkFAlqaDSwCGwwACgkQWLazeFlJwrZQEAQA +uUrp9Qp76CnKqUsUjcVxq7DJBi/lewyGGYSVAFt6/0Xyg/8YTEa/c4Dri/HMOtrf +bgjp/doIVaZLOXZYfqRcpy3z0M6BierOPB3D+fdaTfd7gIrQnGHIp2NmbJZnYgl8 +Ps23qF+LKTa1eE+AmMQYzUHSGuka2lp6OglwWzg/dEw= +=mr3M +-----END PGP PRIVATE KEY BLOCK-----`; + +const revocation_certificate_arm4 = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG 2.1.15 (GNU/Linux) +Comment: This is a revocation certificate + +iJ8EIAEIAAkFAlqaDT0CHQAACgkQWLazeFlJwrbOaAP/V38FhBrUy4XYgt8ZX22G +ov6IFDNoyRKafSuz7Rg+8K8cf+0MAsSi52ueKfsbPxQ+I1vPeaEuEYbwTjtbvM+M +vZcX+VNYdsc1iZeNaT4ayA+2LrCN/xgFj0nrExHqcZAjgBZ9pvKghAqdK4Zb2Ghb +7chPiLLNWJCMtL4bo7a1X84= +=HcWg +-----END PGP PUBLIC KEY BLOCK-----`; + +const revoked_key_arm4 = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG 2.1.15 (GNU/Linux) + +mI0EWpoNLAEEAMoO8dfnLvvCze1hjWcr8t1fMdndFQc1fAM7dm6sbqrdlaAz+Dab +zF3F9UhIOCcABRm+QHyZlgEsoQpHF/7sWflUK1FpoxdORINtIDilukUkMZ0NnIaD ++8pRutdSczPNFvSImSzZNCyLzvDCGMO3+Xeaa6pViSPEeBwhXWJUuHYtABEBAAGI +nwQgAQgACQUCWpoNPQIdAAAKCRBYtrN4WUnCts5oA/9XfwWEGtTLhdiC3xlfbYai +/ogUM2jJEpp9K7PtGD7wrxx/7QwCxKLna54p+xs/FD4jW895oS4RhvBOO1u8z4y9 +lxf5U1h2xzWJl41pPhrID7YusI3/GAWPSesTEepxkCOAFn2m8qCECp0rhlvYaFvt +yE+Iss1YkIy0vhujtrVfzrQiSm9lIFVzZXIgPGpvZS51c2VyQHByb3Rvbm1haWwu +Y29tPoi3BBMBCAAhBQJamg0sAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJ +EFi2s3hZScK2hSMEAKLqpVuehAnVo5o7KgFmxwMg7ldkdkrgv1X24kmEP2/WpEXm +zQ9GIb3r0TAWW+OoiUuJF6MpLG8T/WtzKbgbAFSd2S7V8wz7B5NYc21Gf34E/M3/ +h4pltRtjd8e2WT4t17c34Jm+sYpL8gK1u24B9kvQt3POqc24FReU7oSkbkLeuI0E +WpoNLAEEAMNRHMaSlOf8VNPEfKF5qL7NM5SbLs3VWIJE+QSsh4PrTq1l/+wqoCcQ +KF8QJ5klF5jJ03UHc7xA7IgvL+sfQNLZu3/qO6GSc9UYc9QDI3EeaIdhdNSAY8Rf +VB+6yPMFx8iTq8eNgGJGb8i72LCvMLDKkDh1YNlJNm4WtWx/if63ABEBAAGInwQY +AQgACQUCWpoNLAIbDAAKCRBYtrN4WUnCtlAQBAC5Sun1CnvoKcqpSxSNxXGrsMkG +L+V7DIYZhJUAW3r/RfKD/xhMRr9zgOuL8cw62t9uCOn92ghVpks5dlh+pFynLfPQ +zoGJ6s48HcP591pN93uAitCcYcinY2ZslmdiCXw+zbeoX4spNrV4T4CYxBjNQdIa +6RraWno6CXBbOD90TA== +=8d2d +-----END PGP PUBLIC KEY BLOCK-----`; + +const twoKeys = + ['-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Version: GnuPG v2.0.19 (GNU/Linux)', + '', + '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', + 'PepQmgsu', + '=w6wd', + '-----END PGP PUBLIC KEY BLOCK-----'].join("\n"); + +const pub_revoked_subkeys = ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: Encryption Desktop 10.3.0 (Build 9307)', + 'Version: GnuPG v2.0.19 (GNU/Linux)', '', - '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', - '=dVeR', + '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', + 'pMiJM+NJAQ==', + '=ok+o', '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - const pgp_desktop_priv = - ['-----BEGIN PGP PRIVATE KEY BLOCK-----', - 'Version: Encryption Desktop 10.3.0 (Build 9307)', +const pub_revoked_with_cert = + ['-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Comment: GPGTools - https://gpgtools.org', '', - 'lQPGBFNjoowBCACeKvpQnv8wN3UdDVrZN//Bh/Dtq60hbZ3ObfTbNVBQ0DLD6jWA', - 'lKgwgSa3GLr0a3qrc30CRq0hRIjrFMrg4aPu5sRiZYP90B1cUGf08F2by8f+as2b', - 'BOBzRkcxH/ZmBZPU0pkRoOnkMvoT+YVt2MxzaJRBKM1dgcPXTHvZ52j7V0uEJvs8', - 's/H8DJq6MtgYqoS1zt/+eqUSDCcsVJBsEl7o7qU2d9i074hiBouM2B2mimvBKFIn', - 'W2kmG6fSryNSLaUMwvOTEC/esVNlgvSBfhu82Gic8Rwc+g0cHUnAESChxz/jE0P6', - 'INt2IpBZKeuXCY97tQmce3R4GOc/r3FNBBa3ABEBAAH+CQMCnq0oXlNfXhuothLb', - '7AD3fAc7cpnuondcU2+OdOmnkrB73Qf7iVztLXRcMdIZloSqTlAna8w2ZhmDAdId', - 'EkEO0Uj+Gf7jjC7bLPob/fOj1TMZB3EPX8xs4DhD2oBI5hPNcFrZdHY+qUh1MvMm', - 'zdKgBsnbU6nJK4MrhrJ7InPIopqbNcw3ILrJZkD7U6fhiROx0+7CQ9DSVEscTj/K', - 'u3FeGchNwY2ZmTEDrXy2ZGcQRSuw04GPUcXsBqgD3vivhJtq88K5a4SFPx28uaDO', - 'VXvbUhQ6BpfMaAvpjfJZHzelU4LyQQP+cR/lmR+E7CNuxGa4sT6+NgJ4mQjdWNTc', - 'XBaFUU8DgrOX2pAjYgszbETlATK1LRVM2eV/bXBURpEY8DL+OtwE1eAb/m4dAJXE', - 'cFx8CyaZfI64m27X6av/9GTATXVLHuQUbQHiqhxpaOJSj3ykUvfnQGQedKkT6m7/', - 'Od1B1dQuO0NwRQaM9SOfpNoM9pLU4z2cyOJJBtNydigTyqH7S9WK77BMrsWyHNCG', - 'yXo8qrCLv8oBGLM8m0WfT8twF/VyFo3iVUHIkzy7NbDu9QqiXnGzg7aBeo1L8mwk', - 'Fa5vI44Y1kI2XyjPtpOWtxHaq0YGCtSXuQtr3fSQW/AxQzqJW6lzTjdVSCXXxY/G', - '2DHWbRbbB2bdk1ehJUzSYHRMvgdsvFkZrdLy5Ibz5bTR80RRHn2Z8vYr/bSTOXdF', - 'Xo2F5CvhTME+1BJRhObgqJax8vRnArhu+JVml2cjigHnpH05WzEWv7ezqwsQlUz9', - 'EUN0dZ8Bg4UH7khdcl1Xcepb3+kzFFrGAQG02n1HhZ1Lc1pUTzHKrIQ57x4LUuP8', - 'ZOrysjcAC9TdqySvWEilEGsn/mu6/tnmZNaViDWlzah6mRgaz3Z+m2NkfcJbn/ZH', - 'VHWfOZEku5mNtB1QR1AgRGVza3RvcCAxMC4zIDxwZ3BAc3ltLmRlPp0DxgRTY6KN', - 'AQgA6tnPjznr7HHcoEFXNRC+LEkDOLAm5kTU9MY+2joJyHG7XmEAhPRt4Cp5Fq79', - 'sXPvGZ6tQnD8NVvqc3+91ThTLLKCIRdLOunIGIEJdCr7gN49kgDYisWxt7QQIsv7', - 'Q0SqbGJa7F/jPj5EDf36XJlACJy1yfP6KI6NunffLa23BUU0t0S/TWqq4185nQcz', - 'J1JnZItyyBIyIWXrNtz56B/mIDvIU56SxxpsrcYctAT68vW0njyQ7XRNIzsmvn4o', - '+H9YHnSz3VdXeJaXd7TdU+WLT2lbgzF5BvDN3AlJI8jiONfu0rW9oBmHsQdjDcOl', - 'WdExsCx5Lz7+La7EK/mX0rUVeQARAQAB/gkDAm8zCrvNFCfycCMEudU+3gQFw9Vw', - 'YP5SEAiCwegbNw/RsPXxIy6nzFbKMP9qN8SApFwhuz9qf6SeeSafNtXLDz1dZEQd', - 'yYF4BQ0GLZpeE0kF6XvdefVpTiYJaSc2Px+Ae+fw+s+jF/STvLMI8xjWBmUugs/o', - 'Xto58R6ILKC7n4Fl0YrZcB2hRyIkFu2fq9KhcdAj15rXxxL0Fpzn4wwynCGQW+EO', - 'Ix3QfDmuFweoHrU15Q7ItmpFlX+QfvTzL7uBS8WUwx2Fd/LkbA7K7yivCBDy6LxB', - 'rPnffE1EibAVdOHKIkIaSw+zBAOnkieaJou/BEH/NUerAk1uvzZZwi3tKoYy8rxU', - 'EGPcyblYyBHYRKgGwLsjN1VFvnutBDq7f1uRo5ElCSiVfMsST9VNHIft4V0l6Lsb', - 'VK/2U5+gT6GUeSXW9Rm4fSZwyslSeB2d0Cq6gbkEUAsIaI8JDtnkBPf/boHb0/S7', - 'yFeode6LIUrGqrc9ti4Zky+QFsGchJtc191pNsuvYXgeocEz2UjEBra+Tf/Z6Ysv', - 'zMU8+fVeubWvRpSDhlLc8/+z9FD0hqKJzuJUT5sLfBIvPOkpjDP9k48k5wABzW6S', - 'Mevw/X2M2vGRdHit/Pzn25Ei1H5O4dUMUkneym0qZxQmi8l/4cl8Yr1yYOKk+dsk', - '1dOOGYnyNkoPtrIjLSzctkWZPhVjM7thasBeI77eVdAP4qhf4lCTcnqvnO6eNFLw', - 'ZylzWyYPZrHGIut6Ltasvz2syeAGEDG2RBLNO+z8Mw4RM9jWmNGESiA8RjcBbSfa', - 'l5iBJgRBfVwB9v3/3Jh6V5BA1t9LY1nGbodpM6xQVQRHpzMYYO241bB+dtbW3a3y', - 'XvVs3DJafcAgdGv/TF39h1OP518mNzDG9tYYeAMbJrjby/L0OfS0lEC1gE2Nh1va', - '5g==', - '=63Nq', - '-----END PGP PRIVATE KEY BLOCK-----'].join('\n'); - - const rsa_ecc_pub = - ['pub rsa4096/C9DEDC77 2015-10-17 [expires: 2018-10-16]', - 'uid Google Security Team ', - 'sub nistp384/70C16E3C 2015-10-17 [expires: 2018-10-16]', - 'sub rsa4096/50CB43FB 2015-10-17 [expires: 2018-10-16]', - 'sub nistp384/102D9086 2015-10-17 [expires: 2018-10-16]', - 'sub rsa4096/DFC40367 2015-10-17 [expires: 2018-10-16]', - '', - '-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: GnuPG v2', - '', - 'mQINBFYiIB8BEACxs55+7GG6ONQV3UFYf36UDSVFbuvNB5V1NaEnkY0t+RVMigLR', - 'Zdl0HHsiaTKfKs4jqjLQAoR6Fcre9jlEhatotRg3AvHV1XYebxRlzdfXxyD0d6i9', - 'Quc1zbca0T8F1C5c7xfYP5g9iKWn5yFtHC3S7mLeOg7Ltx84bTo8AF7bHGA3uIQf', - 'uCtE8l6Z57HTeaf2IR/893jLOir8lvmTef83m/+e1j6ZwmKxxZO2s+aGKre6Fqsz', - 'Oo89CpWKNrdZ3IN8+Y4udZNlr7u0os7ffY0shfbLrqt+eVEu4EHfbpQTJxvalZJK', - 'tEnGtV8S7Z3dcPcimxvO7HZu7Wz8VnRzY/AZtee4fC+i2yBu1rWKgY3V1tFKdxVr', - 'KDnmS5MBgBAxv69mM3bf8QPinL4mtIQ65/Dt4ksJuysRmGwQ8LkjSLQCMMepnjBs', - '/63wJ3e4wN1LCwnJonA2f8gZQHNeGPUhVVd/dWFDtmQaLwKFcI0GS/DiUPBIJir5', - 'DWnrEedtlcSLlwwcUglFsG4Sds/tLr+z5yE88ZrDrIlX9fb9cCAsDq7c8/NCzgvw', - 'kFez14sXgGhMz6ZfFzM49o0XwlvAeuSJRWBvnKonxM7/laqv4gK0zur3a6+D6qCN', - 'vt9iWO/YG+0Fvhmyxe34/Q71nXWc9t5aLcokmYLGY1Dpzf9oB8hDRdMCAQARAQAB', - 'tCpHb29nbGUgU2VjdXJpdHkgVGVhbSA8c2VjdXJpdHlAZ29vZ2xlLmNvbT6JAjwE', - 'EwEIACYFAlYiIB8CGwEFCQWjmoAFCwkIBwIGFQgJCgsCAxYCAQIeAQIXgAAKCRC4', - '5BBcyd7cd8MzD/9YdMVZniQH4qBKxLFIoYGfLzCEI0S9IVUA37wrZ4YiRODSJRMf', - 'El6oVfTO/g8xpeQlDgHj1w2IDoSkeQrY+7rf9H41sGGOBDGXSQT+7Z7XFH2mPPvC', - 'cqYqR32BDNDkO/LL1BzzRlQvNmnGHxo098sqTgb7hoVsP+qFoem7JUMpcAV1KrUo', - 'P81haV8a/25ouWFZu5P68WFh861TyIjIYLQCns2fG+zlKFGN9Uynv6E5+Qk7dmni', - 'XnHRaiYZP9+wux6zm5a5wD/h6Iv4hyg/0Vnx5SyH8QOm3Qm6pkUciQkSmZQvf0r7', - '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', - '=Q/kB', + 'mQENBFqm7EoBCAC9MNVwQqdpz9bQK9fpKGLSPk20ckRvvTwq7oDUM1IMZGb4bd/A', + '3KDi9SoBU4oEFRbCAk3rxj8iGL9pxvsX3szyCEXuWfzilAQ/1amRe2woMst+YkTt', + 'x9rzkRiQta4T1fNlqQsJyIIpHrKAFGPp0UjBTr6Vs+Ti6JkF5su4ea+yEiuBHtY4', + 'NjFb1xuV7OyAsZToh0B5fah4/WZ5Joyt9h8gp4WGSvdhLbdsoo8Tjveh2G+Uy2qC', + 'mM8h5v9qGBBRyGM9QmAlhn9XtvEODGbSPYVijEUu8QmbUwHqONAN4fCKAM+jHPuA', + 'rFG+si6QNEk3SOhXX3nvu9ThXg/gKZmmX5ABABEBAAGJATYEIAEKACAWIQQuQVvj', + 'r/N2jaYeuSDeEOPy1UVxbwUCWqbs0wIdAQAKCRDeEOPy1UVxb8CyCACyEagyyvmg', + 'kmS8pEI+iJQU/LsfnNPHwYrDOm0NodGw8HYkil2kfWJim60vFPC3jozzFmvlfy5z', + 'VAge9sVUl3sk7HxnYdPmK767h5Skp6dQSBeeh5WfH4ZK+hhJt9vJTstzaAhVNkX1', + '5OPBfkpy9pbYblQj56g0ECF4UhUxGFVZfycy+i6jvTpk+ABHWDKdqoKj9pTOzwDV', + 'JVa6Y0UT76PMIDjkeDKUYTU6MHexN1oyC07IYh+HsZtlsPTs/zo1JsrO+D6aEkEg', + 'yoLStyg0uemr6LRQ5YuhpG7OMeGRgJstCSo22JHJEtpSUR688aHKN35KNmxjkJDi', + 'fL7cRKHLlqqKtBlTdW5ueSA8c3VubnlAc3Vubnkuc3Vubnk+iQFUBBMBCgA+FiEE', + 'LkFb46/zdo2mHrkg3hDj8tVFcW8FAlqm7EoCGwMFCQeGH4AFCwkIBwMFFQoJCAsF', + 'FgIDAQACHgECF4AACgkQ3hDj8tVFcW83pgf6Auezf0G4MR8/jfHTshYRO8uGdTVR', + 'PjSmczyk4UAk3xy2dZuVc4CathVs/ID3QhycurL33fiZntx+p3JKUrypnp2Y+ZXW', + 'q4xjL05yirDFq4WGgksovmP4q1NfNB3YIsNulHMJ/qCOHl6d+oIDIKF/udwr0+qf', + 'rhd1rMFqO5lAF5/kSBbRdCCLpvMIWKxvDkbZrsqvWcchP5nuymhVHn9cCVGdxsZ8', + 'a/1iODFsBTDF4LISX2Tk1AW5thT96erbvq9XOluDFNjZY9dc6/JWmyWBvLTNguGV', + 'rx0bydeGaddfZc+3XkpImKrpckz5gwYvkgu6bm7GroERjEeYzQDLsg2L07kBDQRa', + 'puxKAQgApxDXRk9YUQ2Ba9QVe8WW/NSmyYQEvtSuvG86nZn5aMiZkEuDpVcmePOS', + '1u6Pz0RB9k1WzAi6Az2l/fS7xSbzjDPV+VXV704t9r0M3Zr5RMzIRjbGoxaZp7Tv', + 'Da3QGN4VIZN6o4oAJM7G2FeZMstnCDxrT3wyKXaEdOn5Uc6hxl2Bhx2gTCpsTFn8', + 'AaBnSY6+kge6rCkeufndXQUhTVy8dYsaSqGwpQHVtk1X4nDoZlCC929F9d3I2/WV', + 'OGlfHqbpbO+8tprvQS0JSzsa9w7xaGJcYUA2tOWV8ZZgC8/1MHMsj5HhHKmmWPsS', + 's6k6RLg3nP+CV9zkKn4sI+l/erOEaQARAQABiQE8BBgBCgAmFiEELkFb46/zdo2m', + 'Hrkg3hDj8tVFcW8FAlqm7EoCGwwFCQeGH4AACgkQ3hDj8tVFcW/lmwgAs3o/b24U', + 't2jioTzjZNFMrqjc99PpURJ9BhKPqa9RF7HrpM4x2mJEFw0fUZGQpQmL5NP0ZazE', + 'N47YHwZH1O5i4t5HtFmjtmMkJUFPlwy0MrClW+OVu6Wl7rtYuXIBqFouUx1YBZtQ', + 'isAmwBeB6DS8Oc39raZpoHh9lGPN1Kmp6iLX3xq+6IqUEV567vSAAR6N2m18GH79', + '365Dq88eZKS/NtlzFnEzoThYlIVt/dknuQsUSdZHtuBbNXaJ816byVZQQWdqnXd5', + 'BIDZSFjrJY/gm2kgQX2Pn9hGqDdGhxiALjxhA0+OJQNw4v11y0zVGdofh0IHjkcZ', + 'onCOcv4DKguN2w==', + '=OqO3', '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - const valid_binding_sig_among_many_expired_sigs_pub = [ - '-----BEGIN PGP PUBLIC KEY BLOCK-----', - '', - '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', - '4z6aN5G1sT5159GF', - '=yzZh', - '-----END PGP PUBLIC KEY BLOCK-----' +const pub_sig_test = + ['-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Version: GnuPG v2.0.19 (GNU/Linux)', + '', + 'mQENBFKgqXUBCADC4c6sSBnBU+15Y32/a8IXqO2WxKxSHj7I5hv1OdSTmSZes7nZ', + '5V96qsk0k5/ka3C2In+GfTKfuAJ0oVkTZVi5tHP9D+PcZngrIFX56OZ2P5PtTU7U', + 'jh0C78JwCVnv6Eg57JnIMwdbL3ZLqmogLhw5q15Hie5btCIQnuuKfrwxnsox4i3q', + 'dYCHYB1HBGzpvflS07r3Y3IRFJaP8hUhx7PsvpD1s+9DU8AuMNZTXAqRI/bms5hC', + 'BpVejXLj/vlNeQil99MoI7s14L+dHogYuUOUbsXim5EyIFfF/1v+o5l0wmueWrE8', + 'mYQfj5ZvURlGVFah9ECaW9/ResCyJ1Yh975xABEBAAG0I1NpZ25hdHVyZSBUZXN0', + 'IDxzaWduYXR1cmVAdGVzdC5jb20+iQE8BBMBAgAmAhsDBwsJCAcDAgEGFQgCCQoL', + 'BBYCAwECHgECF4AFAlKgq80CGQEACgkQwHbmNNMrSY3KKQf/UGnuc6LbVyhkFQKo', + 'USTVDFg/42CVmIGOG+aZBo0VZuzNYARwDKyoZ5okKqZi5VSfdDaBXuW4VIYepvux', + 'AV8eJV6GIsLRv/wJcKPABIXDIK1tdNetiYbd+2/Fb2/YqAX5wOKIxd3Ggzyx5X4F', + 'WhA6fIBIXyShUWoadkX7S87z5hryhII9281rW2mOsLC5fy/SUQUWM1YmsZ1owvY9', + 'q6W8xRnHDmY+Ko91xex7fikDLBofsWbTUc0/O/1o9miIZfp2nXLKQus2H1WdZVOe', + 'H9zFiy54x7+zTov94SJE3xXppoQnIpeOTlFjTP2mjxm0VW1Dn9lGE3IFgWolpNPy', + 'Rv6dnLQdU2Vjb25kIFVzZXIgPHNlY29uZEB1c2VyLmNvbT6IowQwAQIADQUCUrF1', + 'hwYdIEh1cnoACgkQSmNhOk1uQJRVeQP9GQoLvan5FMYcPPY4a9dNlkvtheRXcoif', + 'oYdQoEyy9zAFCqmg2pC6RrHaMwNINw534JDh2vgWQ0MU3ktMJjSvGBBHayQc6ov8', + 'i4I6rUPBlYoSDKyFnhCCXWF56bHMGyEGJhcQLv1hrGPVv6PTKj3hyR+2n50Impwo', + 'UrlFIwYZNyWJAS8EMAECABkFAlKgqqYSHSBUZXN0aW5nIHB1cnBvc2VzAAoJEMB2', + '5jTTK0mNvKAH/Rgu+I12Fb7S8axNwzp5m/jl1iscYbjgOrdUEI7bc2yo0KhGwYOV', + 'U3Zj68Ogj6gkLkVwfhvJYZJgfYBG7nTxkC5/MTABQrAI5ZX89Hh9y0tLh2wKr5iK', + 'MH6Mi9xxJmVJ+IiAKx/02f+sKWh4tv3TFNNxnp24LPHWz7RMd/o4m8itmzQxFmaZ', + 'yEPd/CD6hYqSMP5Y7zMN4gTB+tHsawB9PWkrF/dW8bk3PtZanDlBMUSVrPH15bIZ', + 'lFO1NKEN39WagmNe5wezKxWmHBcuISQHxCIX3Hf4dYyexndX25fMphF93YgQnNE+', + 'zQeBJyNBKRpMXzGndELo5KFaA1YyC07GKKyJATkEEwECACMFAlKgqeYCGwMHCwkI', + 'BwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRDAduY00ytJjagNCACGQMQPl6foIVcz', + 'OzLf8npGihIjiIYARQz4+yg6ze9TG2hjIpWLiwGNJ0uEG22cFiN7OeFnUADFi131', + 'oEtZzIXcBd0A1S87ooH+86YjpvLj5PMlviVKGsGmdqtWpQN5fII8brydNLwSHlLV', + '+JolvyMlA2Ao/sePopR0aSKIPfD108YIIiZztE4pHgDzE5G66zAw3zWn/dzLuGln', + 'Mp4nrY8Rxb68MaZFhVq0A5QFzlOjQ/iDJWrPM6vy/U8TQxmaYGMjcEyEEil+3+OJ', + 'OFqfB4byISOIxL9LqFVRndbgOw7ICi+qE2e7+9G2koCtEkjpPg3ZCF4mfZiaLT9p', + 'QhoFS4yxiJwEEAECAAYFAlKgqhYACgkQSmNhOk1uQJSJ0gP9F5RRwGBbXD4Mg4gq', + 'wcQYrzw9ZAapLKZ2vuco6gHknQAM1YuaOpKQu1rd6eFzKE4M11CLmoS/CalDhg9f', + 'aN6fvTZG7lbUnSZKl/tgvG7qeneA919/b1RtMNDkHmRxvHysiyDYmkJYlmZlwXZB', + '5FBoRvv5b2oXfWLLEcNvUvbetuC5AQ0EUqCpdQEIAOMvycVLkIKm9EMbxFqGc019', + 'yjCB3xiK+hF0PwdfWBXF8KskJ4hfybd19LdO6EGnKfAVGaeVEt6RtUJMsgfhqAhE', + 'BwaeHLLfjXjd7PetBdzybh0u2kfaGDBQshdEuLcfqTqp4+R+ha1epdXAPDP+lb9E', + '5OXIOU2EWLSY+62fyGw3kvUSYNQKufDoKuq5vzltW1uYVq3aeA7e/yTqEoWSoRGo', + '25f/xaY6u6sYIyLpkZ6IX1n1BzLirfJSkJ8svNX+hNihCDshKJUDoMwAPcRdICkr', + 'vFbrO3k24OylQA6dpQqHUWD9kVu8sEZH/eiHZ5YBo/hgwNH7UMaFSBAYQZrSZjcA', + 'EQEAAYkBHwQoAQIACQUCUqCrcgIdAwAKCRDAduY00ytJjeO9B/9O/A6idEMy6cEG', + 'PAYv0U/SJW0RcM54/Ptryg3jiros+qkLQD+Hp2q/xxpXKFPByGWkkGZnNIIxaA1j', + 'SPvOJXrK728b/OXKB3IaMknKTB7gLGH4oA9/dmzHgbeqNWXYok5GSwPxLSUoeIrZ', + 'j+6DkUz2ebDx1FO797eibeL1Dn15iyWh/l3QMT+1fLjJyVDnEtNhZibMlDPohVuS', + 'suJfoKbQJkT6mRy4nDWsPLzFOt3VreJKXo9MMrrHV44XeOKo5nqCK3KsfCoeoqft', + 'G7e/NP4DgcfkgNrU/XnBmR9ZVn9/o3EbDENniOVlNH2JaSQskspv5fv7k6dRWn4Q', + 'NRhN5uMWiQEfBBgBAgAJBQJSoKl1AhsMAAoJEMB25jTTK0mNgaEIAKBkMGTSexox', + 'zy6EWtSR+XfA+LxXjhwOgJWrRKvLUqssGbhQNRfY3gy7dEGiSKdnIV+d/xSLgm7i', + 'zAyE4SjmDDOFRfxpyEsxhw2738OyEenEvO70A2J6RLj91Rfg9+vhT7WWyxBKdU1b', + 'zM2ZORHCBUmbqjYAiLUbz0E589YwJR3a7osjCC8Lstf2C62ttAAAcKks2+wt4kUQ', + 'Zm7WAUi1kG26VvOXVg9Tnj00mnBWmWlLPG7Qjudf2RBMJ/S8gg9OZWpBN29NEl6X', + 'SU+DbbDHw3G97gRNE7QcHZPGyRtjbKv3nV2mJ8DMKrTzLuPUUcFqd7AlpdrFeDx/', + '8YM3DBS79eW5Ay4EUqCq0hEIAMIgqJsi3uTPzJw4b4c1Oue+O98jWaacrk7M57+y', + 'Ol209yRUDyLgojs8ZmEZWdvjBG1hr15FIYI4BmusVXHCokVDGv8KNP4pvbf5wljM', + '2KG1FAxvxZ38/VXTDVH8dOERTf8JPLKlSLbF6rNqfePIL/1wto47b6oRCdawIC25', + 'ft6XX18WlE+dgIefbYcmc0BOgHTHf8YY04IIg67904/RRE6yAWS42Ibx4h1J/haP', + '95SdthKg5J4HQ2lhudC2NJS3p+QBEieavSFuYTXgJwEeLs6gobwpZ7B0IWqAFCYH', + 'rUOxA35MIg39TfZ4VAC+QZRjoDlp+NAM6tP9HfzsiTi5IecBAOEsOESNYr4ifBkw', + 'StjpU6GuGydZf8MP/Ab/EHDAgYTlB/9VLpplMKMVCJLfYIOxEPkhYCfu30kxzsAL', + 'dLmatluP33Zxv0YMnin6lY4Wii0G56ZovbuKDnGR1JcJT4Rr6ZUdd5dZzGqaP7Aj', + 'J/thLQbIJdC1cGntd2V4lyMSly03ENXxYklzWm7S7xgS+uYsE36s1nctytBqxJYl', + '8e/7y+Zg4DxgrA2RM9+5R5neciiPGJIx16tBjOq/CM+R2d2+998YN7rKLxZ3w12t', + 'RXHdGt2DZBVkH7bWxy8/2nTxwRmMiEcmeHfOsMz8BiEdgAU+E8YvuIYb2hL2Vdly', + 'ie9boAnoy0fvVMOpcexw/DQHQcPba5OlfTQJwhTxnfaVd8jaxxJmCAC3PljfH9+/', + 'MZrI2ApzC/xTP64t1ERJ7KP50eu53D+w2IpBOLJwnxMIxjtePRSdbF/0EEEL/0jF', + 'GPSGNEw95/QZAyvbhkCTHuo2Sz3f0M2hCCzReo+t+et13h/7nQhEeNEJtOFFu/t+', + 'nX9BrqNLCjH/6TCpQOkiZC3JQGzJxLU15P0LT+/20Rd8ysym0kPg2SrJCnyOrWwZ', + 'wj+1hEHR9pfNtPIZx2LodtRF//Qo9KMSv9G6Tw3a60x7+18siHxTO9wzOxJxRnqN', + 'LgguiQYq//N6LxF1MeQSxxmNr6kNalafp+pwRwNV4G2L7QWPYn3Axe5oEbjKfnoF', + 'pwhalEs4PCnNiQGFBBgBAgAPBQJSoKrSAhsCBQkAAVGAAGoJEMB25jTTK0mNXyAE', + 'GREIAAYFAlKgqtIACgkQqxSB4x5Bj2igHQD+JYra3ESBrVwurLq4n8mm4bq5Wujm', + 'Da5k6Vf7F7ytbDAA/jb47AhgcDXQRcMw0ElTap5AP/JgtuglW/fO4cJxJfa8Yf0H', + '/i95k6w/MOn5CIwgpZyHc/F4bAVyaZmZ8gAT4lhn03ZDehFNrGJ0IhQH/QfqqNSp', + 'NqG8h7GQIH6ovJlLIcolszIL3khI7LhMsIS6Yi8xpPPB9QcqNmjYkuYAtPE2KyL+', + '2yBt+f4AJ/VFnBygcUf+AC6YxBS3cYclGKUAE9j6StRGj3kPNJPF7M5dZi+1+1Tu', + 'yJ5ucX3iq+3GKLq98Lv7SPUxIqkxuZbkZIoX99Wqz8of9BUV2wTDvVXB7TEPC5Ho', + '1y9Mb82aDrqPCq3DXvw5nz3EwxYqIXoKvLW5zsScBg9N3gmMeukXr2FCREKP5oht', + 'yeSTTh8ZnzRiwuUH1t90E7w=', + '=e8xo', + '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); + +const priv_key_rsa = + ['-----BEGIN PGP PRIVATE KEY BLOCK-----', + 'Version: GnuPG v2.0.19 (GNU/Linux)', + '', + 'lQH+BFJhL04BBADclrUEDDsm0PSZbQ6pml9FpzTyXiyCyDN+rMOsy9J300Oc10kt', + '/nyBej9vZSRcaW5VpNNj0iA+c1/w2FPf84zNsTzvDmuMaNHFUzky4/vkYuZra//3', + '+Ri7CF8RawSYQ/4IRbC9zqdBlzniyfQOW7Dp/LYe8eibnDSrmkQem0G0jwARAQAB', + '/gMDAu7L//czBpE40p1ZqO8K3k7UejemjsQqc7kOqnlDYd1Z6/3NEA/UM30Siipr', + 'KjdIFY5+hp0hcs6EiiNq0PDfm/W2j+7HfrZ5kpeQVxDek4irezYZrl7JS2xezaLv', + 'k0Fv/6fxasnFtjOM6Qbstu67s5Gpl9y06ZxbP3VpT62+Xeibn/swWrfiJjuGEEhM', + 'bgnsMpHtzAz/L8y6KSzViG/05hBaqrvk3/GeEA6nE+o0+0a6r0LYLTemmq6FbaA1', + 'PHo+x7k7oFcBFUUeSzgx78GckuPwqr2mNfeF+IuSRnrlpZl3kcbHASPAOfEkyMXS', + 'sWGE7grCAjbyQyM3OEXTSyqnehvGS/1RdB6kDDxGwgE/QFbwNyEh6K4eaaAThW2j', + 'IEEI0WEnRkPi9fXyxhFsCLSI1XhqTaq7iDNqJTxE+AX2b9ZuZXAxI3Tc/7++vEyL', + '3p18N/MB2kt1Wb1azmXWL2EKlT1BZ5yDaJuBQ8BhphM3tCRUZXN0IE1jVGVzdGlu', + 'Z3RvbiA8dGVzdEBleGFtcGxlLmNvbT6IuQQTAQIAIwUCUmEvTgIbLwcLCQgHAwIB', + 'BhUIAgkKCwQWAgMBAh4BAheAAAoJEEpjYTpNbkCUMAwD+gIK08qpEZSVas9qW+Ok', + '32wzNkwxe6PQgZwcyBqMQYZUcKagC8+89pMQQ5sKUGvpIgat42Tf1KLGPcvG4cDA', + 'JZ6w2PYz9YHQqPh9LA+PAnV8m25TcGmKcKgvFUqQ3U53X/Y9sBP8HooRqfwwHcv9', + 'pMgQmojmNbI4VHydRqIBePawnQH+BFJhL04BBADpH8+0EVolpPiOrXTKoBKTiyrB', + 'UyxzodyJ8zmVJ3HMTEU/vidpQwzISwoc/ndDFMXQauq6xqBCD9m2BPQI3UdQzXnb', + 'LsAI52nWCIqOkzM5NAKWoKhyXK9Y4UH4v9LAYQgl/stIISvCgG4mJ8lzzEBWvRdf', + 'Qm2Ghb64/3V5NDdemwARAQAB/gMDAu7L//czBpE40iPcpLzL7GwBbWFhSWgSLy53', + 'Md99Kxw3cApWCok2E8R9/4VS0490xKZIa5y2I/K8thVhqk96Z8Kbt7MRMC1WLHgC', + 'qJvkeQCI6PrFM0PUIPLHAQtDJYKtaLXxYuexcAdKzZj3FHdtLNWCooK6n3vJlL1c', + 'WjZcHJ1PH7USlj1jup4XfxsbziuysRUSyXkjn92GZLm+64vCIiwhqAYoizF2NHHG', + 'hRTN4gQzxrxgkeVchl+ag7DkQUDANIIVI+A63JeLJgWJiH1fbYlwESByHW+zBFNt', + 'qStjfIOhjrfNIc3RvsggbDdWQLcbxmLZj4sB0ydPSgRKoaUdRHJY0S4vp9ouKOtl', + '2au/P1BP3bhD0fDXl91oeheYth+MSmsJFDg/vZJzCJhFaQ9dp+2EnjN5auNCNbaI', + 'beFJRHFf9cha8p3hh+AK54NRCT++B2MXYf+TPwqX88jYMBv8kk8vYUgo8128r1zQ', + 'EzjviQE9BBgBAgAJBQJSYS9OAhsuAKgJEEpjYTpNbkCUnSAEGQECAAYFAlJhL04A', + 'CgkQ4IT3RGwgLJe6ogQA2aaJEIBIXtgrs+8WSJ4k3DN4rRXcXaUZf667pjdD9nF2', + '3BzjFH6Z78JIGaxRHJdM7b05aE8YuzM8f3NIlT0F0OLq/TI2muYU9f/U2DQBuf+w', + 'KTB62+PELVgi9MsXC1Qv/u/o1LZtmmxTFFOD35xKsxZZI2OJj2pQpqObW27M8Nlc', + 'BQQAw2YA3fFc38qPK+PY4rZyTRdbvjyyX+1zeqIo8wn7QCQwXs+OGaH2fGoT35AI', + 'SXuqKcWqoEuO7OBSEFThCXBfUYMC01OrqKEswPm/V3zZkLu01q12UMwZach28QwK', + '/YZly4ioND2tdazj17u2rU2dwtiHPe1iMqGgVMoQirfLc+k=', + '=lw5e', + '-----END PGP PRIVATE KEY BLOCK-----'].join('\n'); + +const user_attr_key = + ['-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Version: GnuPG v2.0.22 (GNU/Linux)', + '', + 'mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+', + 'fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5', + 'GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0', + 'JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS', + 'YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6', + 'AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki', + 'Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf', + '9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rDRwc7BzAEQAAEBAAAAAAAA', + 'AAAAAAAA/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQN', + 'DAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/', + '2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy', + 'MjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAAFABQDASIAAhEBAxEB/8QAHwAAAQUB', + 'AQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQID', + 'AAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0', + 'NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKT', + 'lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl', + '5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL', + '/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHB', + 'CSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpj', + 'ZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3', + 'uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIR', + 'AxEAPwD3+iiigAooooA//9mIuQQTAQIAIwUCUzxDqQIbLwcLCQgHAwIBBhUIAgkK', + 'CwQWAgMBAh4BAheAAAoJEEpjYTpNbkCU9PEEAKMMaXjhGdgDISBXAAEVXL6MB3x1', + 'd/7zBdnUljh1gM34TSKvbeZf7h/1DNgLbJFfSF3KiLViiqRVOumIkjwNIMZPqYtu', + 'WoEcElY50mvTETzOKemCt1GYI0GhOY2uZOVRtQLrkX0CB9r5hEQalkrnjNKlbghj', + 'LfOYu1uARF16cZUWuI0EUmEvTgEEAOkfz7QRWiWk+I6tdMqgEpOLKsFTLHOh3Inz', + 'OZUnccxMRT++J2lDDMhLChz+d0MUxdBq6rrGoEIP2bYE9AjdR1DNedsuwAjnadYI', + 'io6TMzk0ApagqHJcr1jhQfi/0sBhCCX+y0ghK8KAbiYnyXPMQFa9F19CbYaFvrj/', + 'dXk0N16bABEBAAGJAT0EGAECAAkFAlJhL04CGy4AqAkQSmNhOk1uQJSdIAQZAQIA', + 'BgUCUmEvTgAKCRDghPdEbCAsl7qiBADZpokQgEhe2Cuz7xZIniTcM3itFdxdpRl/', + 'rrumN0P2cXbcHOMUfpnvwkgZrFEcl0ztvTloTxi7Mzx/c0iVPQXQ4ur9Mjaa5hT1', + '/9TYNAG5/7ApMHrb48QtWCL0yxcLVC/+7+jUtm2abFMUU4PfnEqzFlkjY4mPalCm', + 'o5tbbszw2VwFBADDZgDd8Vzfyo8r49jitnJNF1u+PLJf7XN6oijzCftAJDBez44Z', + 'ofZ8ahPfkAhJe6opxaqgS47s4FIQVOEJcF9RgwLTU6uooSzA+b9XfNmQu7TWrXZQ', + 'zBlpyHbxDAr9hmXLiKg0Pa11rOPXu7atTZ3C2Ic97WIyoaBUyhCKt8tz6Q==', + '=MVfN', + '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); + +const pgp_desktop_pub = + ['-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Version: Encryption Desktop 10.3.0 (Build 9307)', + '', + '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', + '=dVeR', + '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); + +const pgp_desktop_priv = + ['-----BEGIN PGP PRIVATE KEY BLOCK-----', + 'Version: Encryption Desktop 10.3.0 (Build 9307)', + '', + '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', + '5g==', + '=63Nq', + '-----END PGP PRIVATE KEY BLOCK-----'].join('\n'); + + const rsa_ecc_pub = + ['pub rsa4096/C9DEDC77 2015-10-17 [expires: 2018-10-16]', + 'uid Google Security Team ', + 'sub nistp384/70C16E3C 2015-10-17 [expires: 2018-10-16]', + 'sub rsa4096/50CB43FB 2015-10-17 [expires: 2018-10-16]', + 'sub nistp384/102D9086 2015-10-17 [expires: 2018-10-16]', + 'sub rsa4096/DFC40367 2015-10-17 [expires: 2018-10-16]', + '', + '-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Version: GnuPG v2', + '', + 'mQINBFYiIB8BEACxs55+7GG6ONQV3UFYf36UDSVFbuvNB5V1NaEnkY0t+RVMigLR', + 'Zdl0HHsiaTKfKs4jqjLQAoR6Fcre9jlEhatotRg3AvHV1XYebxRlzdfXxyD0d6i9', + 'Quc1zbca0T8F1C5c7xfYP5g9iKWn5yFtHC3S7mLeOg7Ltx84bTo8AF7bHGA3uIQf', + 'uCtE8l6Z57HTeaf2IR/893jLOir8lvmTef83m/+e1j6ZwmKxxZO2s+aGKre6Fqsz', + 'Oo89CpWKNrdZ3IN8+Y4udZNlr7u0os7ffY0shfbLrqt+eVEu4EHfbpQTJxvalZJK', + 'tEnGtV8S7Z3dcPcimxvO7HZu7Wz8VnRzY/AZtee4fC+i2yBu1rWKgY3V1tFKdxVr', + 'KDnmS5MBgBAxv69mM3bf8QPinL4mtIQ65/Dt4ksJuysRmGwQ8LkjSLQCMMepnjBs', + '/63wJ3e4wN1LCwnJonA2f8gZQHNeGPUhVVd/dWFDtmQaLwKFcI0GS/DiUPBIJir5', + 'DWnrEedtlcSLlwwcUglFsG4Sds/tLr+z5yE88ZrDrIlX9fb9cCAsDq7c8/NCzgvw', + 'kFez14sXgGhMz6ZfFzM49o0XwlvAeuSJRWBvnKonxM7/laqv4gK0zur3a6+D6qCN', + 'vt9iWO/YG+0Fvhmyxe34/Q71nXWc9t5aLcokmYLGY1Dpzf9oB8hDRdMCAQARAQAB', + 'tCpHb29nbGUgU2VjdXJpdHkgVGVhbSA8c2VjdXJpdHlAZ29vZ2xlLmNvbT6JAjwE', + 'EwEIACYFAlYiIB8CGwEFCQWjmoAFCwkIBwIGFQgJCgsCAxYCAQIeAQIXgAAKCRC4', + '5BBcyd7cd8MzD/9YdMVZniQH4qBKxLFIoYGfLzCEI0S9IVUA37wrZ4YiRODSJRMf', + 'El6oVfTO/g8xpeQlDgHj1w2IDoSkeQrY+7rf9H41sGGOBDGXSQT+7Z7XFH2mPPvC', + 'cqYqR32BDNDkO/LL1BzzRlQvNmnGHxo098sqTgb7hoVsP+qFoem7JUMpcAV1KrUo', + 'P81haV8a/25ouWFZu5P68WFh861TyIjIYLQCns2fG+zlKFGN9Uynv6E5+Qk7dmni', + 'XnHRaiYZP9+wux6zm5a5wD/h6Iv4hyg/0Vnx5SyH8QOm3Qm6pkUciQkSmZQvf0r7', + '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', + '=Q/kB', + '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); + +const valid_binding_sig_among_many_expired_sigs_pub = [ + '-----BEGIN PGP PUBLIC KEY BLOCK-----', + '', + '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', + '4z6aN5G1sT5159GF', + '=yzZh', + '-----END PGP PUBLIC KEY BLOCK-----' ].join('\n'); - const key_without_subkey = [ - '-----BEGIN PGP PRIVATE KEY BLOCK-----', - 'Version: OpenPGP.js v2.6.2', - 'Comment: https://openpgpjs.org', - '', - 'xcLYBFp9nCsBCACXTmLI9bJzaAanrD7r6j7gNDS7PsebJr0e182hgHVnGkr3', - '8XCsCdWSllUNfBRln4MI8GfWVO5Bhhx5en6ntCptJVeSsohAHfBzmdoauSGW', - 'y+M+3dlSGeVqgqmDukQSxuNgKBC/ELDhKvAb8uKWnS/MUOapk/6aF8mf9Vqm', - 'eG/1RHrIvxfeOsRCEFH0OqB2tOeCWPXohxpzv2AvFxWviwzpedwNGDhN/XjZ', - 'JzI4LyBKlorHJvwe4KLKtaLuOq0jmNkT6AcsniyhvqN8QRP4OK7084Uc/7Yd', - '6Qrcnw/6plqMB5J2PyYkB6eTptp28bwIxUGzfGQ6qfDyHHQBIbAVt3m5ABEB', - 'AAEAB/9uDdjynSvon5C/oxy9Ukvbnn2AeOCNLLdA2O07/Ijoroo7IIW4zQpo', - 'rio9PbREWqrf9KVCk9IdHORXQ88eQoDdlNzG2k8ae+xq2Ux4RZJ18eVf09P/', - '0NA7EcElDHX5RmsahOnxX72YejfdzGQd80VSEsJENF5rTMQeMkN2dIHS3pFM', - '9ar2nJe9dc/L9ND0P79X8twZvvfh287Tm23fs384nRedcUwELm43kNV7Us3t', - 'ub1ORmAzHhVCa8dWev7Zca7FqiZxa0u3X/QHvVMMpr0ewTBulr/mEjaglfYf', - 'dNp1PxduWYPWU54/XLG3G4nqLUS++qjd3O46VhMMCIigGf01BACgrkPwdrTJ', - 'EGCfgIq48IGoMU//wS1P0g7EIzplwGAzGAJQw6LhGqKrDONcyKGqHzRgn8oz', - 'dF8iezGjlVq7oiyrrB4ez1gDG4RRDC+6+PTn/TXBTZ21krUgPUrB0jcqV7SQ', - 'IIWZost7zNcbEqiPI91SPAMwYJZbJrSL4pTnDVLfewQA8RB1y3IzuK/rT+gs', - 'JfcSHqZ12G+sUIgpK6yv4pN7hQDhWC3+qe8ULnLLXYv+FQslnRW7tTkAbCRl', - 'kJvbibRqrYj+fQS2d3Hau5HYcGKcv9KPgOhB49yRkQpWCT+fqsQwJByyeZ47', - 'iiJRR8t0X92nr0zbf0f+LalmK4cQnQ6LS1sEAN2R8RiamrNcbsdmre0v6QVL', - 'WUOIwRWABRWFOm9QbSr80ji1q9pHlS5WbIw4LVeiO8V6H21QTL2fqDA9yWOK', - 'mNsOgIi+1PMkC4lwPu60VR7yBtLFWFF2SuuqPuDG8TFA2PBQFisrxcq63E38', - 'kroxpqxNCXXuB3E0uNL2fO6dqWbaRPzNF2dpYm9saW5AcHJvdG9ubWFpbC5i', - 'bHVlwsBcBBABAgAGBQJafZwrAAoJEFu1JX+Hv3FrMWEH/jE6HN5MayB6RHe7', - 'FTrfMlMEh54BqsiugmAIgtKYcxUcNsPw/hC53lJ6tDzo3/zk/2shvfItafh5', - 'ldUsERj1y5e7OMR+2GgfgMdddLddBuV8sXv2HwQgMtykeXOIPuH+7CZDwV7F', - 'lUyrykwpIjGGPkK+fG64fVt0cfWprdEsqcGZmHf/lHtoGprG8syfF+Ao3beI', - 'g6HJ61NHIBy4ewueKMBZ58/9VF2MQ7YgBQCtQNAnQKKrDFmxjZw3J4zBl83i', - '3LrYpnYepvMUitQ/Y2pBAYygUExZ0dPC2uGFdPISbDGLg3DhGcyy1MvbLuNh', - 'EyjB8RncAfSIwK4dSGVh+PD5dkc=', - '=w6Dj', - '-----END PGP PRIVATE KEY BLOCK-----' +const key_without_subkey = [ + '-----BEGIN PGP PRIVATE KEY BLOCK-----', + 'Version: OpenPGP.js v2.6.2', + 'Comment: https://openpgpjs.org', + '', + 'xcLYBFp9nCsBCACXTmLI9bJzaAanrD7r6j7gNDS7PsebJr0e182hgHVnGkr3', + '8XCsCdWSllUNfBRln4MI8GfWVO5Bhhx5en6ntCptJVeSsohAHfBzmdoauSGW', + 'y+M+3dlSGeVqgqmDukQSxuNgKBC/ELDhKvAb8uKWnS/MUOapk/6aF8mf9Vqm', + 'eG/1RHrIvxfeOsRCEFH0OqB2tOeCWPXohxpzv2AvFxWviwzpedwNGDhN/XjZ', + 'JzI4LyBKlorHJvwe4KLKtaLuOq0jmNkT6AcsniyhvqN8QRP4OK7084Uc/7Yd', + '6Qrcnw/6plqMB5J2PyYkB6eTptp28bwIxUGzfGQ6qfDyHHQBIbAVt3m5ABEB', + 'AAEAB/9uDdjynSvon5C/oxy9Ukvbnn2AeOCNLLdA2O07/Ijoroo7IIW4zQpo', + 'rio9PbREWqrf9KVCk9IdHORXQ88eQoDdlNzG2k8ae+xq2Ux4RZJ18eVf09P/', + '0NA7EcElDHX5RmsahOnxX72YejfdzGQd80VSEsJENF5rTMQeMkN2dIHS3pFM', + '9ar2nJe9dc/L9ND0P79X8twZvvfh287Tm23fs384nRedcUwELm43kNV7Us3t', + 'ub1ORmAzHhVCa8dWev7Zca7FqiZxa0u3X/QHvVMMpr0ewTBulr/mEjaglfYf', + 'dNp1PxduWYPWU54/XLG3G4nqLUS++qjd3O46VhMMCIigGf01BACgrkPwdrTJ', + 'EGCfgIq48IGoMU//wS1P0g7EIzplwGAzGAJQw6LhGqKrDONcyKGqHzRgn8oz', + 'dF8iezGjlVq7oiyrrB4ez1gDG4RRDC+6+PTn/TXBTZ21krUgPUrB0jcqV7SQ', + 'IIWZost7zNcbEqiPI91SPAMwYJZbJrSL4pTnDVLfewQA8RB1y3IzuK/rT+gs', + 'JfcSHqZ12G+sUIgpK6yv4pN7hQDhWC3+qe8ULnLLXYv+FQslnRW7tTkAbCRl', + 'kJvbibRqrYj+fQS2d3Hau5HYcGKcv9KPgOhB49yRkQpWCT+fqsQwJByyeZ47', + 'iiJRR8t0X92nr0zbf0f+LalmK4cQnQ6LS1sEAN2R8RiamrNcbsdmre0v6QVL', + 'WUOIwRWABRWFOm9QbSr80ji1q9pHlS5WbIw4LVeiO8V6H21QTL2fqDA9yWOK', + 'mNsOgIi+1PMkC4lwPu60VR7yBtLFWFF2SuuqPuDG8TFA2PBQFisrxcq63E38', + 'kroxpqxNCXXuB3E0uNL2fO6dqWbaRPzNF2dpYm9saW5AcHJvdG9ubWFpbC5i', + 'bHVlwsBcBBABAgAGBQJafZwrAAoJEFu1JX+Hv3FrMWEH/jE6HN5MayB6RHe7', + 'FTrfMlMEh54BqsiugmAIgtKYcxUcNsPw/hC53lJ6tDzo3/zk/2shvfItafh5', + 'ldUsERj1y5e7OMR+2GgfgMdddLddBuV8sXv2HwQgMtykeXOIPuH+7CZDwV7F', + 'lUyrykwpIjGGPkK+fG64fVt0cfWprdEsqcGZmHf/lHtoGprG8syfF+Ao3beI', + 'g6HJ61NHIBy4ewueKMBZ58/9VF2MQ7YgBQCtQNAnQKKrDFmxjZw3J4zBl83i', + '3LrYpnYepvMUitQ/Y2pBAYygUExZ0dPC2uGFdPISbDGLg3DhGcyy1MvbLuNh', + 'EyjB8RncAfSIwK4dSGVh+PD5dkc=', + '=w6Dj', + '-----END PGP PRIVATE KEY BLOCK-----' ].join('\n'); - it('Parsing armored text with RSA key and ECC subkey', async function() { - openpgp.config.tolerant = true; - const pubKeys = await openpgp.key.readArmored(rsa_ecc_pub); - expect(pubKeys).to.exist; - expect(pubKeys.err).to.not.exist; - expect(pubKeys.keys).to.have.length(1); - expect(pubKeys.keys[0].getKeyId().toHex()).to.equal('b8e4105cc9dedc77'); - }); +const multi_uid_key = + ['-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Version: GnuPG v1', + '', + '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', + 'ljIYQms3pCv1ja6bLlNKpPII', + '=qxBI', + '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - const multi_uid_key = - ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: GnuPG v1', - '', - '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', - 'ljIYQms3pCv1ja6bLlNKpPII', - '=qxBI', - '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); +const wrong_key = + ['-----BEGIN PGP PUBLIC KEY BLOCK-----', + 'Version: OpenPGP.js v0.9.0', + '', + 'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5', + 'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg', + 'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM', + 'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq', + 'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1', + '=6XMW', + '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); - const wrong_key = - ['-----BEGIN PGP PUBLIC KEY BLOCK-----', - 'Version: OpenPGP.js v0.9.0', - '', - 'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5', - 'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg', - 'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM', - 'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq', - 'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1', - '=6XMW', - '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); +const expiredKey = + `-----BEGIN PGP PRIVATE KEY BLOCK----- - const expiredKey = - `-----BEGIN PGP PRIVATE KEY BLOCK----- + xcA4BAAAAAEBAgCgONc0J8rfO6cJw5YTP38x1ze2tAYIO7EcmRCNYwMkXngb + 0Qdzg34Q5RW0rNiR56VB6KElPUhePRPVklLFiIvHABEBAAEAAf9qabYMzsz/ + /LeRVZSsTgTljmJTdzd2ambUbpi+vt8MXJsbaWh71vjoLMWSXajaKSPDjVU5 + waFNt9kLqwGGGLqpAQD5ZdMH2XzTq6GU9Ka69iZs6Pbnzwdz59Vc3i8hXlUj + zQEApHargCTsrtvSrm+hK/pN51/BHAy9lxCAw9f2etx+AeMA/RGrijkFZtYt + jeWdv/usXL3mgHvEcJv63N5zcEvDX5X4W1bND3Rlc3QxIDxhQGIuY29tPsJ7 + BBABCAAvBQIAAAABBQMAAAU5BgsJBwgDAgkQzcF99nGrkAkEFQgKAgMWAgEC + GQECGwMCHgEAABAlAfwPehmLZs+gOhOTTaSslqQ50bl/REjmv42Nyr1ZBlQS + DECl1Qu4QyeXin29uEXWiekMpNlZVsEuc8icCw6ABhIZ + =/7PI + -----END PGP PRIVATE KEY BLOCK-----`; - xcA4BAAAAAEBAgCgONc0J8rfO6cJw5YTP38x1ze2tAYIO7EcmRCNYwMkXngb - 0Qdzg34Q5RW0rNiR56VB6KElPUhePRPVklLFiIvHABEBAAEAAf9qabYMzsz/ - /LeRVZSsTgTljmJTdzd2ambUbpi+vt8MXJsbaWh71vjoLMWSXajaKSPDjVU5 - waFNt9kLqwGGGLqpAQD5ZdMH2XzTq6GU9Ka69iZs6Pbnzwdz59Vc3i8hXlUj - zQEApHargCTsrtvSrm+hK/pN51/BHAy9lxCAw9f2etx+AeMA/RGrijkFZtYt - jeWdv/usXL3mgHvEcJv63N5zcEvDX5X4W1bND3Rlc3QxIDxhQGIuY29tPsJ7 - BBABCAAvBQIAAAABBQMAAAU5BgsJBwgDAgkQzcF99nGrkAkEFQgKAgMWAgEC - GQECGwMCHgEAABAlAfwPehmLZs+gOhOTTaSslqQ50bl/REjmv42Nyr1ZBlQS - DECl1Qu4QyeXin29uEXWiekMpNlZVsEuc8icCw6ABhIZ - =/7PI - -----END PGP PRIVATE KEY BLOCK-----`; - - const multipleBindingSignatures = +const multipleBindingSignatures = `-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2 @@ -1264,6 +1221,462 @@ t/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU= =C0fJ -----END PGP PRIVATE KEY BLOCK-----`; +function versionSpecificTests() { + it('Preferences of generated key', function() { + const testPref = function(key) { + // key flags + const keyFlags = openpgp.enums.keyFlags; + expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.certify_keys).to.equal(keyFlags.certify_keys); + expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.sign_data).to.equal(keyFlags.sign_data); + expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_communication).to.equal(keyFlags.encrypt_communication); + expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage); + const sym = openpgp.enums.symmetric; + expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes256, sym.aes128, sym.aes192, sym.cast5, sym.tripledes]); + if (openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4) { + const aead = openpgp.enums.aead; + expect(key.users[0].selfCertifications[0].preferredAeadAlgorithms).to.eql([aead.eax, aead.ocb]); + } + const hash = openpgp.enums.hash; + expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha512, hash.sha1]); + const compr = openpgp.enums.compression; + expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]); + expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4 ? [7] : [1]); + }; + const opt = {numBits: 512, userIds: 'test ', passphrase: 'hello'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(async function(key) { + testPref(key.key); + testPref((await openpgp.key.readArmored(key.publicKeyArmored)).keys[0]); + }); + }); + + it('Generated key is not unlocked by default', function() { + const opt = {numBits: 512, userIds: 'test ', passphrase: '123'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + let key; + return openpgp.generateKey(opt).then(function(newKey) { + key = newKey.key; + return openpgp.message.fromText('hello').encrypt([key]); + }).then(function(msg) { + return msg.message.decrypt([key]); + }).catch(function(err) { + expect(err.message).to.equal('Private key is not decrypted.'); + }); + }); + + it('Generate key - single userid', function() { + const userId = { name: 'test', email: 'a@b.com', comment: 'test comment' }; + const opt = {numBits: 512, userIds: userId, passphrase: '123'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(function(key) { + key = key.key; + expect(key.users.length).to.equal(1); + expect(key.users[0].userId.userid).to.equal('test (test comment)'); + expect(key.users[0].userId.name).to.equal(userId.name); + expect(key.users[0].userId.email).to.equal(userId.email); + expect(key.users[0].userId.comment).to.equal(userId.comment); + }); + }); + + it('Generate key - setting date to the past', function() { + const past = new Date(0); + const opt = { + numBits: 512, + userIds: { name: 'Test User', email: 'text@example.com' }, + passphrase: 'secret', + date: past + }; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + + return openpgp.generateKey(opt).then(function(newKey) { + expect(newKey.key).to.exist; + expect(+newKey.key.getCreationTime()).to.equal(+past); + expect(+newKey.key.subKeys[0].getCreationTime()).to.equal(+past); + expect(+newKey.key.subKeys[0].bindingSignatures[0].created).to.equal(+past); + }); + }) + + it('Generate key - multi userid', function() { + const userId1 = 'test '; + const userId2 = 'test '; + const opt = {numBits: 512, userIds: [userId1, userId2], passphrase: '123'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(function(key) { + key = key.key; + expect(key.users.length).to.equal(2); + expect(key.users[0].userId.userid).to.equal(userId1); + expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; + expect(key.users[1].userId.userid).to.equal(userId2); + expect(key.users[1].selfCertifications[0].isPrimaryUserID).to.be.null; + }); + }); + + it('Generate key - two subkeys with default values', function() { + const userId = 'test '; + const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{},{}]}; + return openpgp.generateKey(opt).then(function(key) { + key = key.key; + expect(key.users.length).to.equal(1); + expect(key.users[0].userId.userid).to.equal(userId); + expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; + expect(key.subKeys).to.have.lengthOf(2); + expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh'); + expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('ecdh'); + }); + }); + + it('Generate key - one signing subkey', function() { + const userId = 'test '; + const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]}; + return openpgp.generateKey(opt).then(function(key) { + key = key.key; + expect(key.users.length).to.equal(1); + expect(key.users[0].userId.userid).to.equal(userId); + expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; + expect(key.subKeys).to.have.lengthOf(2); + expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh'); + expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('eddsa'); + }); + }); + + it('Generate key - override main key options for subkey', function() { + const userId = 'test '; + const opt = {numBits: 512, userIds: [userId], passphrase: '123', subkeys:[{curve: 'curve25519'}]}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(function(key) { + key = key.key; + expect(key.users.length).to.equal(1); + expect(key.users[0].userId.userid).to.equal(userId); + expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; + expect(key.getAlgorithmInfo().algorithm).to.equal('rsa_encrypt_sign'); + expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh'); + }); + }); + + it('Encrypt key with new passphrase', async function() { + const userId = 'test '; + const opt = {numBits: 512, userIds: userId, passphrase: 'passphrase'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + const key = (await openpgp.generateKey(opt)).key; + const armor1 = key.armor(); + const armor2 = key.armor(); + expect(armor1).to.equal(armor2); + expect(await key.decrypt('passphrase')).to.be.true; + expect(key.isDecrypted()).to.be.true; + await key.encrypt('new_passphrase'); + expect(key.isDecrypted()).to.be.false; + await expect(key.decrypt('passphrase')).to.eventually.be.rejectedWith('Incorrect key passphrase'); + expect(key.isDecrypted()).to.be.false; + expect(await key.decrypt('new_passphrase')).to.be.true; + expect(key.isDecrypted()).to.be.true; + const armor3 = key.armor(); + expect(armor3).to.not.equal(armor1); + }); + + it('Generate key - ensure keyExpirationTime works', function() { + const expect_delta = 365 * 24 * 60 * 60; + const userId = 'test '; + const opt = {numBits: 512, userIds: userId, passphrase: '123', keyExpirationTime: expect_delta}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(async function(key) { + key = key.key; + + const expiration = await key.getExpirationTime(); + expect(expiration).to.exist; + + const actual_delta = (new Date(expiration) - new Date()) / 1000; + expect(Math.abs(actual_delta - expect_delta)).to.be.below(60); + + const subKeyExpiration = await key.subKeys[0].getExpirationTime(); + expect(subKeyExpiration).to.exist; + + const actual_subKeyDelta = (new Date(subKeyExpiration) - new Date()) / 1000; + expect(Math.abs(actual_subKeyDelta - expect_delta)).to.be.below(60); + }); + }); + + it('Sign and verify key - primary user', async function() { + let publicKey = (await openpgp.key.readArmored(pub_sig_test)).keys[0]; + const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; + await privateKey.decrypt('hello world'); + publicKey = await publicKey.signPrimaryUser([privateKey]); + const signatures = await publicKey.verifyPrimaryUser([privateKey]); + const publicSigningKey = await publicKey.getSigningKey(); + const privateSigningKey = await privateKey.getSigningKey(); + expect(signatures.length).to.equal(2); + expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); + expect(signatures[0].valid).to.be.null; + expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); + expect(signatures[1].valid).to.be.true; + }); + + it('Sign key and verify with wrong key - primary user', async function() { + let publicKey = (await openpgp.key.readArmored(pub_sig_test)).keys[0]; + const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; + const wrongKey = (await openpgp.key.readArmored(wrong_key)).keys[0]; + await privateKey.decrypt('hello world'); + publicKey = await publicKey.signPrimaryUser([privateKey]); + const signatures = await publicKey.verifyPrimaryUser([wrongKey]); + const publicSigningKey = await publicKey.getSigningKey(); + const privateSigningKey = await privateKey.getSigningKey(); + expect(signatures.length).to.equal(2); + expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); + expect(signatures[0].valid).to.be.null; + expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); + expect(signatures[1].valid).to.be.null; + }); + + it('Sign and verify key - all users', async function() { + let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0]; + const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; + await privateKey.decrypt('hello world'); + publicKey = await publicKey.signAllUsers([privateKey]); + const signatures = await publicKey.verifyAllUsers([privateKey]); + const publicSigningKey = await publicKey.getSigningKey(); + const privateSigningKey = await privateKey.getSigningKey(); + expect(signatures.length).to.equal(4); + expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid); + expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); + expect(signatures[0].valid).to.be.null; + expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid); + expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); + expect(signatures[1].valid).to.be.true; + expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid); + expect(signatures[2].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); + expect(signatures[2].valid).to.be.null; + expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid); + expect(signatures[3].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); + expect(signatures[3].valid).to.be.true; + }); + + it('Sign key and verify with wrong key - all users', async function() { + let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0]; + const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; + const wrongKey = (await openpgp.key.readArmored(wrong_key)).keys[0]; + await privateKey.decrypt('hello world'); + publicKey = await publicKey.signAllUsers([privateKey]); + const signatures = await publicKey.verifyAllUsers([wrongKey]); + const publicSigningKey = await publicKey.getSigningKey(); + const privateSigningKey = await privateKey.getSigningKey(); + expect(signatures.length).to.equal(4); + expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid); + expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); + expect(signatures[0].valid).to.be.null; + expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid); + expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); + expect(signatures[1].valid).to.be.null; + expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid); + expect(signatures[2].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); + expect(signatures[2].valid).to.be.null; + expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid); + expect(signatures[3].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); + expect(signatures[3].valid).to.be.null; + }); + + it('Reformat key without passphrase', function() { + const userId1 = 'test1 '; + const userId2 = 'test2 '; + const opt = {numBits: 512, userIds: userId1}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(function(key) { + key = key.key; + expect(key.users.length).to.equal(1); + expect(key.users[0].userId.userid).to.equal(userId1); + expect(key.isDecrypted()).to.be.true; + opt.privateKey = key; + opt.userIds = userId2; + return openpgp.reformatKey(opt).then(function(newKey) { + newKey = newKey.key; + expect(newKey.users.length).to.equal(1); + expect(newKey.users[0].userId.userid).to.equal(userId2); + expect(newKey.isDecrypted()).to.be.true; + }); + }); + }); + + it('Reformat key with no subkey with passphrase', async function() { + const userId = 'test1 '; + const keys = (await openpgp.key.readArmored(key_without_subkey)).keys; + const opt = {privateKey: keys[0], userIds: [userId], passphrase: "test"}; + return openpgp.reformatKey(opt).then(function(newKey) { + newKey = newKey.key; + expect(newKey.users.length).to.equal(1); + expect(newKey.users[0].userId.userid).to.equal(userId); + expect(newKey.isDecrypted()).to.be.false; + }); + }); + + it('Reformat key with two subkeys with passphrase', function() { + const userId1 = 'test '; + const userId2 = 'test '; + const now = openpgp.util.normalizeDate(new Date()); + const before = openpgp.util.normalizeDate(new Date(0)); + const opt1 = {curve: 'curve25519', userIds: [userId1], date: now}; + return openpgp.generateKey(opt1).then(function(newKey) { + newKey = newKey.key; + expect(newKey.users[0].userId.userid).to.equal(userId1); + expect(+newKey.getCreationTime()).to.equal(+now); + expect(+newKey.subKeys[0].getCreationTime()).to.equal(+now); + expect(+newKey.subKeys[0].bindingSignatures[0].created).to.equal(+now); + const opt2 = {privateKey: newKey, userIds: [userId2], date: before}; + return openpgp.reformatKey(opt2).then(function(refKey) { + refKey = refKey.key; + expect(refKey.users.length).to.equal(1); + expect(refKey.users[0].userId.userid).to.equal(userId2); + expect(+refKey.subKeys[0].bindingSignatures[0].created).to.equal(+before); + }); + }); + }); + + it('Reformat key with no subkey without passphrase', async function() { + const userId = 'test1 '; + const keys = (await openpgp.key.readArmored(key_without_subkey)).keys; + const opt = {privateKey: keys[0], userIds: [userId]}; + return openpgp.reformatKey(opt).then(function(newKey) { + newKey = newKey.key; + expect(newKey.users.length).to.equal(1); + expect(newKey.users[0].userId.userid).to.equal(userId); + expect(newKey.isDecrypted()).to.be.true; + return openpgp.sign({message: openpgp.cleartext.fromText('hello'), privateKeys: newKey, armor: true}).then(async function(signed) { + return openpgp.verify( + {message: await openpgp.cleartext.readArmored(signed.data), publicKeys: newKey.toPublic()} + ).then(async function(verified) { + expect(verified.signatures[0].valid).to.be.true; + const newSigningKey = await newKey.getSigningKey(); + expect(verified.signatures[0].keyid.toHex()).to.equal(newSigningKey.getKeyId().toHex()); + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + }); + }); + + it('Reformat and encrypt key', function() { + const userId1 = 'test1 '; + const userId2 = 'test2 '; + const userId3 = 'test3 '; + const opt = {numBits: 512, userIds: userId1}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(function(key) { + key = key.key; + opt.privateKey = key; + opt.userIds = [userId2, userId3]; + opt.passphrase = '123'; + return openpgp.reformatKey(opt).then(async function(newKey) { + newKey = newKey.key; + expect(newKey.users.length).to.equal(2); + expect(newKey.users[0].userId.userid).to.equal(userId2); + expect(newKey.isDecrypted()).to.be.false; + await newKey.decrypt('123'); + expect(newKey.isDecrypted()).to.be.true; + }); + }); + }); + + it('Sign and encrypt with reformatted key', function() { + const userId1 = 'test1 '; + const userId2 = 'test2 '; + const opt = {numBits: 512, userIds: userId1}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(function(key) { + key = key.key; + opt.privateKey = key; + opt.userIds = userId2; + return openpgp.reformatKey(opt).then(function(newKey) { + newKey = newKey.key; + return openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: newKey.toPublic(), privateKeys: newKey, armor: true}).then(async function(encrypted) { + return openpgp.decrypt({message: await openpgp.message.readArmored(encrypted.data), privateKeys: newKey, publicKeys: newKey.toPublic()}).then(function(decrypted) { + expect(decrypted.data).to.equal('hello'); + expect(decrypted.signatures[0].valid).to.be.true; + }); + }); + }); + }); + }); + + it('Reject with user-friendly error when reformatting encrypted key', function() { + const opt = {numBits: 512, userIds: 'test1 ', passphrase: '1234'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(function(original) { + return openpgp.reformatKey({privateKey: original.key, userIds: 'test2 ', passphrase: '1234'}).then(function() { + throw new Error('reformatKey should result in error when key not decrypted'); + }).catch(function(error) { + expect(error.message).to.equal('Error reformatting keypair: Key not decrypted'); + }); + }); + }); + + it('Revoke generated key with revocation certificate', function() { + const opt = {numBits: 512, userIds: 'test1 ', passphrase: '1234'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(function(original) { + return openpgp.revokeKey({key: original.key.toPublic(), revocationCertificate: original.revocationCertificate}).then(function(revKey) { + revKey = revKey.publicKey; + expect(revKey.revocationSignatures[0].reasonForRevocationFlag).to.equal(openpgp.enums.reasonForRevocation.no_reason); + expect(revKey.revocationSignatures[0].reasonForRevocationString).to.equal(''); + return revKey.verifyPrimaryKey().then(function(status) { + expect(status).to.equal(openpgp.enums.keyStatus.revoked); + }); + }); + }); + }); + + it('Revoke generated key with private key', function() { + const opt = {numBits: 512, userIds: 'test1 ', passphrase: '1234'}; + if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys + return openpgp.generateKey(opt).then(async function(original) { + await original.key.decrypt('1234'); + return openpgp.revokeKey({key: original.key, reasonForRevocation: {string: 'Testing key revocation'}}).then(function(revKey) { + revKey = revKey.publicKey; + expect(revKey.revocationSignatures[0].reasonForRevocationFlag).to.equal(openpgp.enums.reasonForRevocation.no_reason); + expect(revKey.revocationSignatures[0].reasonForRevocationString).to.equal('Testing key revocation'); + return revKey.verifyPrimaryKey().then(function(status) { + expect(status).to.equal(openpgp.enums.keyStatus.revoked); + }); + }); + }); + }); +} + +describe('Key', function() { + let rsaGenStub; + let rsaGenValue = openpgp.crypto.publicKey.rsa.generate(openpgp.util.getWebCryptoAll() ? 2048 : 512, "10001"); + + beforeEach(function() { + rsaGenStub = stub(openpgp.crypto.publicKey.rsa, 'generate'); + rsaGenStub.returns(rsaGenValue); + }); + + afterEach(function() { + rsaGenStub.restore(); + }); + + describe('V4', versionSpecificTests); + + describe('V5', function() { + let aead_protectVal; + let aead_protect_versionVal; + beforeEach(function() { + aead_protectVal = openpgp.config.aead_protect; + aead_protect_versionVal = openpgp.config.aead_protect_version; + openpgp.config.aead_protect = true; + openpgp.config.aead_protect_version = 4; + }); + afterEach(function() { + openpgp.config.aead_protect = aead_protectVal; + openpgp.config.aead_protect_version = aead_protect_versionVal; + }); + + versionSpecificTests(); + }); + + it('Parsing armored text with RSA key and ECC subkey', async function() { + openpgp.config.tolerant = true; + const pubKeys = await openpgp.key.readArmored(rsa_ecc_pub); + expect(pubKeys).to.exist; + expect(pubKeys.err).to.not.exist; + expect(pubKeys.keys).to.have.length(1); + expect(pubKeys.keys[0].getKeyId().toHex()).to.equal('b8e4105cc9dedc77'); + }); it('Parsing armored text with two keys', async function() { const pubKeys = await openpgp.key.readArmored(twoKeys); @@ -1659,34 +2072,6 @@ t/ia1kMpSEiOVLlX5dfHZzhR3WNtBqU= expect(supported).to.be.false; }); - it('Preferences of generated key', function() { - const testPref = function(key) { - // key flags - const keyFlags = openpgp.enums.keyFlags; - expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.certify_keys).to.equal(keyFlags.certify_keys); - expect(key.users[0].selfCertifications[0].keyFlags[0] & keyFlags.sign_data).to.equal(keyFlags.sign_data); - expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_communication).to.equal(keyFlags.encrypt_communication); - expect(key.subKeys[0].bindingSignatures[0].keyFlags[0] & keyFlags.encrypt_storage).to.equal(keyFlags.encrypt_storage); - const sym = openpgp.enums.symmetric; - expect(key.users[0].selfCertifications[0].preferredSymmetricAlgorithms).to.eql([sym.aes256, sym.aes128, sym.aes192, sym.cast5, sym.tripledes]); - if (openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4) { - const aead = openpgp.enums.aead; - expect(key.users[0].selfCertifications[0].preferredAeadAlgorithms).to.eql([aead.eax, aead.ocb]); - } - const hash = openpgp.enums.hash; - expect(key.users[0].selfCertifications[0].preferredHashAlgorithms).to.eql([hash.sha256, hash.sha512, hash.sha1]); - const compr = openpgp.enums.compression; - expect(key.users[0].selfCertifications[0].preferredCompressionAlgorithms).to.eql([compr.zlib, compr.zip]); - expect(key.users[0].selfCertifications[0].features).to.eql(openpgp.config.aead_protect && openpgp.config.aead_protect_version === 4 ? [7] : [1]); - }; - const opt = {numBits: 512, userIds: 'test ', passphrase: 'hello'}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(async function(key) { - testPref(key.key); - testPref((await openpgp.key.readArmored(key.publicKeyArmored)).keys[0]); - }); - }); - it('User attribute packet read & write', async function() { const key = (await openpgp.key.readArmored(user_attr_key)).keys[0]; const key2 = (await openpgp.key.readArmored(key.armor())).keys[0]; @@ -1722,229 +2107,6 @@ VYGdb3eNlV8CfoEC expect(primUser).to.be.null; }); - it('Generated key is not unlocked by default', function() { - const opt = {numBits: 512, userIds: 'test ', passphrase: '123'}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - let key; - return openpgp.generateKey(opt).then(function(newKey) { - key = newKey.key; - return openpgp.message.fromText('hello').encrypt([key]); - }).then(function(msg) { - return msg.message.decrypt([key]); - }).catch(function(err) { - expect(err.message).to.equal('Private key is not decrypted.'); - }); - }); - - it('Generate key - single userid', function() { - const userId = { name: 'test', email: 'a@b.com', comment: 'test comment' }; - const opt = {numBits: 512, userIds: userId, passphrase: '123'}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(function(key) { - key = key.key; - expect(key.users.length).to.equal(1); - expect(key.users[0].userId.userid).to.equal('test (test comment)'); - expect(key.users[0].userId.name).to.equal(userId.name); - expect(key.users[0].userId.email).to.equal(userId.email); - expect(key.users[0].userId.comment).to.equal(userId.comment); - }); - }); - - it('Generate key - setting date to the past', function() { - const past = new Date(0); - const opt = { - numBits: 512, - userIds: { name: 'Test User', email: 'text@example.com' }, - passphrase: 'secret', - date: past - }; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - - return openpgp.generateKey(opt).then(function(newKey) { - expect(newKey.key).to.exist; - expect(+newKey.key.getCreationTime()).to.equal(+past); - expect(+newKey.key.subKeys[0].getCreationTime()).to.equal(+past); - expect(+newKey.key.subKeys[0].bindingSignatures[0].created).to.equal(+past); - }); - }) - - it('Generate key - multi userid', function() { - const userId1 = 'test '; - const userId2 = 'test '; - const opt = {numBits: 512, userIds: [userId1, userId2], passphrase: '123'}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(function(key) { - key = key.key; - expect(key.users.length).to.equal(2); - expect(key.users[0].userId.userid).to.equal(userId1); - expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; - expect(key.users[1].userId.userid).to.equal(userId2); - expect(key.users[1].selfCertifications[0].isPrimaryUserID).to.be.null; - }); - }); - - it('Generate key - two subkeys with default values', function() { - const userId = 'test '; - const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{},{}]}; - return openpgp.generateKey(opt).then(function(key) { - key = key.key; - expect(key.users.length).to.equal(1); - expect(key.users[0].userId.userid).to.equal(userId); - expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; - expect(key.subKeys).to.have.lengthOf(2); - expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh'); - expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('ecdh'); - }); - }); - - it('Generate key - one signing subkey', function() { - const userId = 'test '; - const opt = {curve: 'curve25519', userIds: [userId], passphrase: '123', subkeys:[{}, {sign: true}]}; - return openpgp.generateKey(opt).then(function(key) { - key = key.key; - expect(key.users.length).to.equal(1); - expect(key.users[0].userId.userid).to.equal(userId); - expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; - expect(key.subKeys).to.have.lengthOf(2); - expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh'); - expect(key.subKeys[1].getAlgorithmInfo().algorithm).to.equal('eddsa'); - }); - }); - - it('Generate key - override main key options for subkey', function() { - const userId = 'test '; - const opt = {numBits: 512, userIds: [userId], passphrase: '123', subkeys:[{curve: 'curve25519'}]}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(function(key) { - key = key.key; - expect(key.users.length).to.equal(1); - expect(key.users[0].userId.userid).to.equal(userId); - expect(key.users[0].selfCertifications[0].isPrimaryUserID).to.be.true; - expect(key.getAlgorithmInfo().algorithm).to.equal('rsa_encrypt_sign'); - expect(key.subKeys[0].getAlgorithmInfo().algorithm).to.equal('ecdh'); - }); - }); - - it('Encrypt key with new passphrase', async function() { - const userId = 'test '; - const opt = {numBits: 512, userIds: userId, passphrase: 'passphrase'}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - const key = (await openpgp.generateKey(opt)).key; - const armor1 = key.armor(); - const armor2 = key.armor(); - expect(armor1).to.equal(armor2); - expect(await key.decrypt('passphrase')).to.be.true; - expect(key.isDecrypted()).to.be.true; - await key.encrypt('new_passphrase'); - expect(key.isDecrypted()).to.be.false; - await expect(key.decrypt('passphrase')).to.eventually.be.rejectedWith('Incorrect key passphrase'); - expect(key.isDecrypted()).to.be.false; - expect(await key.decrypt('new_passphrase')).to.be.true; - expect(key.isDecrypted()).to.be.true; - const armor3 = key.armor(); - expect(armor3).to.not.equal(armor1); - }); - - it('Generate key - ensure keyExpirationTime works', function() { - const expect_delta = 365 * 24 * 60 * 60; - const userId = 'test '; - const opt = {numBits: 512, userIds: userId, passphrase: '123', keyExpirationTime: expect_delta}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(async function(key) { - key = key.key; - - const expiration = await key.getExpirationTime(); - expect(expiration).to.exist; - - const actual_delta = (new Date(expiration) - new Date()) / 1000; - expect(Math.abs(actual_delta - expect_delta)).to.be.below(60); - - const subKeyExpiration = await key.subKeys[0].getExpirationTime(); - expect(subKeyExpiration).to.exist; - - const actual_subKeyDelta = (new Date(subKeyExpiration) - new Date()) / 1000; - expect(Math.abs(actual_subKeyDelta - expect_delta)).to.be.below(60); - }); - }); - - it('Sign and verify key - primary user', async function() { - let publicKey = (await openpgp.key.readArmored(pub_sig_test)).keys[0]; - const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; - await privateKey.decrypt('hello world'); - publicKey = await publicKey.signPrimaryUser([privateKey]); - const signatures = await publicKey.verifyPrimaryUser([privateKey]); - const publicSigningKey = await publicKey.getSigningKey(); - const privateSigningKey = await privateKey.getSigningKey(); - expect(signatures.length).to.equal(2); - expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); - expect(signatures[0].valid).to.be.null; - expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); - expect(signatures[1].valid).to.be.true; - }); - - it('Sign key and verify with wrong key - primary user', async function() { - let publicKey = (await openpgp.key.readArmored(pub_sig_test)).keys[0]; - const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; - const wrongKey = (await openpgp.key.readArmored(wrong_key)).keys[0]; - await privateKey.decrypt('hello world'); - publicKey = await publicKey.signPrimaryUser([privateKey]); - const signatures = await publicKey.verifyPrimaryUser([wrongKey]); - const publicSigningKey = await publicKey.getSigningKey(); - const privateSigningKey = await privateKey.getSigningKey(); - expect(signatures.length).to.equal(2); - expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); - expect(signatures[0].valid).to.be.null; - expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); - expect(signatures[1].valid).to.be.null; - }); - - it('Sign and verify key - all users', async function() { - let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0]; - const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; - await privateKey.decrypt('hello world'); - publicKey = await publicKey.signAllUsers([privateKey]); - const signatures = await publicKey.verifyAllUsers([privateKey]); - const publicSigningKey = await publicKey.getSigningKey(); - const privateSigningKey = await privateKey.getSigningKey(); - expect(signatures.length).to.equal(4); - expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid); - expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); - expect(signatures[0].valid).to.be.null; - expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid); - expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); - expect(signatures[1].valid).to.be.true; - expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid); - expect(signatures[2].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); - expect(signatures[2].valid).to.be.null; - expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid); - expect(signatures[3].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); - expect(signatures[3].valid).to.be.true; - }); - - it('Sign key and verify with wrong key - all users', async function() { - let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0]; - const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; - const wrongKey = (await openpgp.key.readArmored(wrong_key)).keys[0]; - await privateKey.decrypt('hello world'); - publicKey = await publicKey.signAllUsers([privateKey]); - const signatures = await publicKey.verifyAllUsers([wrongKey]); - const publicSigningKey = await publicKey.getSigningKey(); - const privateSigningKey = await privateKey.getSigningKey(); - expect(signatures.length).to.equal(4); - expect(signatures[0].userid).to.equal(publicKey.users[0].userId.userid); - expect(signatures[0].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); - expect(signatures[0].valid).to.be.null; - expect(signatures[1].userid).to.equal(publicKey.users[0].userId.userid); - expect(signatures[1].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); - expect(signatures[1].valid).to.be.null; - expect(signatures[2].userid).to.equal(publicKey.users[1].userId.userid); - expect(signatures[2].keyid.toHex()).to.equal(publicSigningKey.getKeyId().toHex()); - expect(signatures[2].valid).to.be.null; - expect(signatures[3].userid).to.equal(publicKey.users[1].userId.userid); - expect(signatures[3].keyid.toHex()).to.equal(privateSigningKey.getKeyId().toHex()); - expect(signatures[3].valid).to.be.null; - }); - it('Encrypt - latest created user', async function() { let publicKey = (await openpgp.key.readArmored(multi_uid_key)).keys[0]; const privateKey = (await openpgp.key.readArmored(priv_key_rsa)).keys[0]; @@ -2000,138 +2162,6 @@ VYGdb3eNlV8CfoEC await expect(openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: publicKey, privateKeys: privateKey, fromUserId: {name: 'Not Test McTestington', email: 'test@example.com'}, detached: true, armor: false})).to.be.rejectedWith('Could not find user that matches that user ID'); }); - it('Reformat key without passphrase', function() { - const userId1 = 'test1 '; - const userId2 = 'test2 '; - const opt = {numBits: 512, userIds: userId1}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(function(key) { - key = key.key; - expect(key.users.length).to.equal(1); - expect(key.users[0].userId.userid).to.equal(userId1); - expect(key.isDecrypted()).to.be.true; - opt.privateKey = key; - opt.userIds = userId2; - return openpgp.reformatKey(opt).then(function(newKey) { - newKey = newKey.key; - expect(newKey.users.length).to.equal(1); - expect(newKey.users[0].userId.userid).to.equal(userId2); - expect(newKey.isDecrypted()).to.be.true; - }); - }); - }); - - it('Reformat key with no subkey with passphrase', async function() { - const userId = 'test1 '; - const keys = (await openpgp.key.readArmored(key_without_subkey)).keys; - const opt = {privateKey: keys[0], userIds: [userId], passphrase: "test"}; - return openpgp.reformatKey(opt).then(function(newKey) { - newKey = newKey.key; - expect(newKey.users.length).to.equal(1); - expect(newKey.users[0].userId.userid).to.equal(userId); - expect(newKey.isDecrypted()).to.be.false; - }); - }); - - it('Reformat key with two subkeys with passphrase', function() { - const userId1 = 'test '; - const userId2 = 'test '; - const now = openpgp.util.normalizeDate(new Date()); - const before = openpgp.util.normalizeDate(new Date(0)); - const opt1 = {curve: 'curve25519', userIds: [userId1], date: now}; - return openpgp.generateKey(opt1).then(function(newKey) { - newKey = newKey.key; - expect(newKey.users[0].userId.userid).to.equal(userId1); - expect(+newKey.getCreationTime()).to.equal(+now); - expect(+newKey.subKeys[0].getCreationTime()).to.equal(+now); - expect(+newKey.subKeys[0].bindingSignatures[0].created).to.equal(+now); - const opt2 = {privateKey: newKey, userIds: [userId2], date: before}; - return openpgp.reformatKey(opt2).then(function(refKey) { - refKey = refKey.key; - expect(refKey.users.length).to.equal(1); - expect(refKey.users[0].userId.userid).to.equal(userId2); - expect(+refKey.subKeys[0].bindingSignatures[0].created).to.equal(+before); - }); - }); - }); - - it('Reformat key with no subkey without passphrase', async function() { - const userId = 'test1 '; - const keys = (await openpgp.key.readArmored(key_without_subkey)).keys; - const opt = {privateKey: keys[0], userIds: [userId]}; - return openpgp.reformatKey(opt).then(function(newKey) { - newKey = newKey.key; - expect(newKey.users.length).to.equal(1); - expect(newKey.users[0].userId.userid).to.equal(userId); - expect(newKey.isDecrypted()).to.be.true; - return openpgp.sign({message: openpgp.cleartext.fromText('hello'), privateKeys: newKey, armor: true}).then(async function(signed) { - return openpgp.verify( - {message: await openpgp.cleartext.readArmored(signed.data), publicKeys: newKey.toPublic()} - ).then(async function(verified) { - expect(verified.signatures[0].valid).to.be.true; - const newSigningKey = await newKey.getSigningKey(); - expect(verified.signatures[0].keyid.toHex()).to.equal(newSigningKey.getKeyId().toHex()); - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - }); - }); - - it('Reformat and encrypt key', function() { - const userId1 = 'test1 '; - const userId2 = 'test2 '; - const userId3 = 'test3 '; - const opt = {numBits: 512, userIds: userId1}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(function(key) { - key = key.key; - opt.privateKey = key; - opt.userIds = [userId2, userId3]; - opt.passphrase = '123'; - return openpgp.reformatKey(opt).then(async function(newKey) { - newKey = newKey.key; - expect(newKey.users.length).to.equal(2); - expect(newKey.users[0].userId.userid).to.equal(userId2); - expect(newKey.isDecrypted()).to.be.false; - await newKey.decrypt('123'); - expect(newKey.isDecrypted()).to.be.true; - }); - }); - }); - - it('Sign and encrypt with reformatted key', function() { - const userId1 = 'test1 '; - const userId2 = 'test2 '; - const opt = {numBits: 512, userIds: userId1}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(function(key) { - key = key.key; - opt.privateKey = key; - opt.userIds = userId2; - return openpgp.reformatKey(opt).then(function(newKey) { - newKey = newKey.key; - return openpgp.encrypt({message: openpgp.message.fromText('hello'), publicKeys: newKey.toPublic(), privateKeys: newKey, armor: true}).then(async function(encrypted) { - return openpgp.decrypt({message: await openpgp.message.readArmored(encrypted.data), privateKeys: newKey, publicKeys: newKey.toPublic()}).then(function(decrypted) { - expect(decrypted.data).to.equal('hello'); - expect(decrypted.signatures[0].valid).to.be.true; - }); - }); - }); - }); - }); - - it('Reject with user-friendly error when reformatting encrypted key', function() { - const opt = {numBits: 512, userIds: 'test1 ', passphrase: '1234'}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(function(original) { - return openpgp.reformatKey({privateKey: original.key, userIds: 'test2 ', passphrase: '1234'}).then(function() { - throw new Error('reformatKey should result in error when key not decrypted'); - }).catch(function(error) { - expect(error.message).to.equal('Error reformatting keypair: Key not decrypted'); - }); - }); - }); - it('Find a valid subkey binding signature among many invalid ones', async function() { const key = (await openpgp.key.readArmored(valid_binding_sig_among_many_expired_sigs_pub)).keys[0]; expect(await key.getEncryptionKey()).to.not.be.null; @@ -2160,37 +2190,6 @@ VYGdb3eNlV8CfoEC }); }); - it('Revoke generated key with revocation certificate', function() { - const opt = {numBits: 512, userIds: 'test1 ', passphrase: '1234'}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(function(original) { - return openpgp.revokeKey({key: original.key.toPublic(), revocationCertificate: original.revocationCertificate}).then(function(revKey) { - revKey = revKey.publicKey; - expect(revKey.revocationSignatures[0].reasonForRevocationFlag).to.equal(openpgp.enums.reasonForRevocation.no_reason); - expect(revKey.revocationSignatures[0].reasonForRevocationString).to.equal(''); - return revKey.verifyPrimaryKey().then(function(status) { - expect(status).to.equal(openpgp.enums.keyStatus.revoked); - }); - }); - }); - }); - - it('Revoke generated key with private key', function() { - const opt = {numBits: 512, userIds: 'test1 ', passphrase: '1234'}; - if (openpgp.util.getWebCryptoAll()) { opt.numBits = 2048; } // webkit webcrypto accepts minimum 2048 bit keys - return openpgp.generateKey(opt).then(async function(original) { - await original.key.decrypt('1234'); - return openpgp.revokeKey({key: original.key, reasonForRevocation: {string: 'Testing key revocation'}}).then(function(revKey) { - revKey = revKey.publicKey; - expect(revKey.revocationSignatures[0].reasonForRevocationFlag).to.equal(openpgp.enums.reasonForRevocation.no_reason); - expect(revKey.revocationSignatures[0].reasonForRevocationString).to.equal('Testing key revocation'); - return revKey.verifyPrimaryKey().then(function(status) { - expect(status).to.equal(openpgp.enums.keyStatus.revoked); - }); - }); - }); - }); - it('Merge key with another key with non-ID user attributes', async function() { const key = (await openpgp.key.readArmored(mergeKey1)).keys[0]; const updateKey = (await openpgp.key.readArmored(mergeKey2)).keys[0]; @@ -2204,4 +2203,4 @@ VYGdb3eNlV8CfoEC expect(key.users[1].userId).to.be.null; }); }); -} +}); diff --git a/test/general/openpgp.js b/test/general/openpgp.js index eed35347..7b39c59d 100644 --- a/test/general/openpgp.js +++ b/test/general/openpgp.js @@ -654,6 +654,53 @@ describe('OpenPGP.js public api tests', function() { openpgp.config.aead_chunk_size_byte = aead_chunk_size_byteVal; }); + it('Configuration', function() { + openpgp.config.show_version = false; + openpgp.config.commentstring = 'different'; + if (openpgp.getWorker()) { // init again to trigger config event + openpgp.initWorker({ path:'../dist/openpgp.worker.js' }); + } + return openpgp.encrypt({ publicKeys:publicKey.keys, message:openpgp.message.fromText(plaintext) }).then(function(encrypted) { + expect(encrypted.data).to.exist; + expect(encrypted.data).not.to.match(/^Version:/); + expect(encrypted.data).to.match(/Comment: different/); + }); + }); + + it('Test multiple workers', async function() { + openpgp.config.show_version = false; + openpgp.config.commentstring = 'different'; + if (!openpgp.getWorker()) { + return; + } + const { workers } = openpgp.getWorker(); + try { + await privateKey.keys[0].decrypt(passphrase) + openpgp.initWorker({path: '../dist/openpgp.worker.js', workers, n: 2}); + + const workerTest = (_, index) => { + const plaintext = input.createSomeMessage() + index; + return openpgp.encrypt({ + publicKeys: publicKey.keys, + data: plaintext + }).then(function (encrypted) { + expect(encrypted.data).to.exist; + expect(encrypted.data).not.to.match(/^Version:/); + expect(encrypted.data).to.match(/Comment: different/); + return openpgp.decrypt({ + privateKeys: privateKey.keys[0], + message: openpgp.message.readArmored(encrypted.data) + }); + }).then(function (decrypted) { + expect(decrypted.data).to.equal(plaintext); + }); + }; + await Promise.all(Array(10).fill(null).map(workerTest)); + } finally { + openpgp.initWorker({path: '../dist/openpgp.worker.js', workers, n: 1 }); + } + }); + it('Decrypting key with wrong passphrase rejected', async function () { await expect(privateKey.keys[0].decrypt('wrong passphrase')).to.eventually.be.rejectedWith('Incorrect key passphrase'); }); @@ -662,6 +709,43 @@ describe('OpenPGP.js public api tests', function() { expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true; }); + describe('decryptKey', function() { + it('should work for correct passphrase', function() { + return openpgp.decryptKey({ + privateKey: privateKey.keys[0], + passphrase: passphrase + }).then(function(unlocked){ + expect(unlocked.key.getKeyId().toHex()).to.equal(privateKey.keys[0].getKeyId().toHex()); + expect(unlocked.key.isDecrypted()).to.be.true; + }); + }); + + it('should fail for incorrect passphrase', function() { + return openpgp.decryptKey({ + privateKey: privateKey.keys[0], + passphrase: 'incorrect' + }).catch(function(error){ + expect(error.message).to.match(/Incorrect key passphrase/); + }); + }); + }); + + it('Calling decrypt with not decrypted key leads to exception', function() { + const encOpt = { + message: openpgp.message.fromText(plaintext), + publicKeys: publicKey.keys + }; + const decOpt = { + privateKeys: privateKey.keys[0] + }; + return openpgp.encrypt(encOpt).then(async function(encrypted) { + decOpt.message = await openpgp.message.readArmored(encrypted.data); + return openpgp.decrypt(decOpt); + }).catch(function(error) { + expect(error.message).to.match(/not decrypted/); + }); + }); + tryTests('CFB mode (asm.js)', tests, { if: !(typeof window !== 'undefined' && window.Worker), beforeEach: function() { @@ -730,90 +814,6 @@ describe('OpenPGP.js public api tests', function() { }); function tests() { - it('Configuration', function() { - openpgp.config.show_version = false; - openpgp.config.commentstring = 'different'; - if (openpgp.getWorker()) { // init again to trigger config event - openpgp.initWorker({ path:'../dist/openpgp.worker.js' }); - } - return openpgp.encrypt({ publicKeys:publicKey.keys, message:openpgp.message.fromText(plaintext) }).then(function(encrypted) { - expect(encrypted.data).to.exist; - expect(encrypted.data).not.to.match(/^Version:/); - expect(encrypted.data).to.match(/Comment: different/); - }); - }); - - it('Test multiple workers', async function() { - openpgp.config.show_version = false; - openpgp.config.commentstring = 'different'; - if (!openpgp.getWorker()) { - return; - } - const { workers } = openpgp.getWorker(); - try { - await privateKey.keys[0].decrypt(passphrase) - openpgp.initWorker({path: '../dist/openpgp.worker.js', workers, n: 2}); - - const workerTest = (_, index) => { - const plaintext = input.createSomeMessage() + index; - return openpgp.encrypt({ - publicKeys: publicKey.keys, - data: plaintext - }).then(function (encrypted) { - expect(encrypted.data).to.exist; - expect(encrypted.data).not.to.match(/^Version:/); - expect(encrypted.data).to.match(/Comment: different/); - return openpgp.decrypt({ - privateKeys: privateKey.keys[0], - message: openpgp.message.readArmored(encrypted.data) - }); - }).then(function (decrypted) { - expect(decrypted.data).to.equal(plaintext); - }); - }; - await Promise.all(Array(10).fill(null).map(workerTest)); - } finally { - openpgp.initWorker({path: '../dist/openpgp.worker.js', workers, n: 1 }); - } - }); - - it('Calling decrypt with not decrypted key leads to exception', function() { - const encOpt = { - message: openpgp.message.fromText(plaintext), - publicKeys: publicKey.keys - }; - const decOpt = { - privateKeys: privateKey.keys[0] - }; - return openpgp.encrypt(encOpt).then(async function(encrypted) { - decOpt.message = await openpgp.message.readArmored(encrypted.data); - return openpgp.decrypt(decOpt); - }).catch(function(error) { - expect(error.message).to.match(/not decrypted/); - }); - }); - - describe('decryptKey', function() { - it('should work for correct passphrase', function() { - return openpgp.decryptKey({ - privateKey: privateKey.keys[0], - passphrase: passphrase - }).then(function(unlocked){ - expect(unlocked.key.getKeyId().toHex()).to.equal(privateKey.keys[0].getKeyId().toHex()); - expect(unlocked.key.isDecrypted()).to.be.true; - }); - }); - - it('should fail for incorrect passphrase', function() { - return openpgp.decryptKey({ - privateKey: privateKey.keys[0], - passphrase: 'incorrect' - }).catch(function(error){ - expect(error.message).to.match(/Incorrect key passphrase/); - }); - }); - }); - describe('encryptSessionKey, decryptSessionKeys', function() { const sk = new Uint8Array([0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01]); @@ -1538,456 +1538,6 @@ describe('OpenPGP.js public api tests', function() { expect(decrypted.signatures[1].signature.packets.length).to.equal(1); }); }); - - it('should sign and verify cleartext data', function () { - const message = openpgp.cleartext.fromText(plaintext); - const signOpt = { - message, - privateKeys: privateKey.keys - }; - const verifyOpt = { - publicKeys: publicKey.keys - }; - return openpgp.sign(signOpt).then(async function (signed) { - expect(signed.data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/); - verifyOpt.message = await openpgp.cleartext.readArmored(signed.data); - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(verified.signatures[0].valid).to.be.true; - const signingKey = await privateKey.keys[0].getSigningKey(); - expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - - it('should sign and verify cleartext data with multiple private keys', async function () { - const privKeyDE = (await openpgp.key.readArmored(priv_key_de)).keys[0]; - await privKeyDE.decrypt(passphrase); - - const message = openpgp.cleartext.fromText(plaintext); - const signOpt = { - message, - privateKeys: [privateKey.keys[0], privKeyDE] - }; - const verifyOpt = { - publicKeys: [publicKey.keys[0], privKeyDE.toPublic()] - }; - return openpgp.sign(signOpt).then(async function (signed) { - expect(signed.data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/); - verifyOpt.message = await openpgp.cleartext.readArmored(signed.data); - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - let signingKey; - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(verified.signatures[0].valid).to.be.true; - signingKey = await privateKey.keys[0].getSigningKey(); - expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); - expect(verified.signatures[0].signature.packets.length).to.equal(1); - expect(verified.signatures[1].valid).to.be.true; - signingKey = await privKeyDE.getSigningKey(); - expect(verified.signatures[1].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); - expect(verified.signatures[1].signature.packets.length).to.equal(1); - }); - }); - - it('should sign and verify cleartext data with detached signatures', function () { - const message = openpgp.cleartext.fromText(plaintext); - const signOpt = { - message, - privateKeys: privateKey.keys, - detached: true - }; - const verifyOpt = { - message, - publicKeys: publicKey.keys - }; - return openpgp.sign(signOpt).then(async function (signed) { - verifyOpt.signature = await openpgp.signature.readArmored(signed.signature); - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(verified.signatures[0].valid).to.be.true; - const signingKey = await privateKey.keys[0].getSigningKey(); - expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - - it('should sign and fail to verify cleartext data with wrong public pgp key', async function () { - const message = openpgp.cleartext.fromText(plaintext); - const signOpt = { - message, - privateKeys: privateKey.keys - }; - const verifyOpt = { - publicKeys: (await openpgp.key.readArmored(wrong_pubkey)).keys - }; - return openpgp.sign(signOpt).then(async function (signed) { - verifyOpt.message = await openpgp.cleartext.readArmored(signed.data); - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(verified.signatures[0].valid).to.be.null; - const signingKey = await privateKey.keys[0].getSigningKey(); - expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - - it('should sign and fail to verify cleartext data with wrong public pgp key with detached signature', async function () { - const message = openpgp.cleartext.fromText(plaintext); - const signOpt = { - message, - privateKeys: privateKey.keys, - detached: true - }; - const verifyOpt = { - message, - publicKeys: (await openpgp.key.readArmored(wrong_pubkey)).keys - }; - return openpgp.sign(signOpt).then(async function (signed) { - verifyOpt.signature = await openpgp.signature.readArmored(signed.signature); - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(verified.signatures[0].valid).to.be.null; - const signingKey = await privateKey.keys[0].getSigningKey(); - expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - - it('should sign and verify cleartext data and not armor', function () { - const message = openpgp.cleartext.fromText(plaintext); - const signOpt = { - message, - privateKeys: privateKey.keys, - armor: false - }; - const verifyOpt = { - publicKeys: publicKey.keys - }; - return openpgp.sign(signOpt).then(function (signed) { - verifyOpt.message = signed.message; - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(verified.signatures[0].valid).to.be.true; - const signingKey = await privateKey.keys[0].getSigningKey(); - expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - - it('should sign and verify cleartext data and not armor with detached signatures', function () { - const start = openpgp.util.normalizeDate(); - const message = openpgp.cleartext.fromText(plaintext); - const signOpt = { - message, - privateKeys: privateKey.keys, - detached: true, - armor: false - }; - const verifyOpt = { - message, - publicKeys: publicKey.keys - }; - return openpgp.sign(signOpt).then(function (signed) { - verifyOpt.signature = signed.signature; - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(+verified.signatures[0].signature.packets[0].created).to.be.lte(+openpgp.util.normalizeDate()); - expect(+verified.signatures[0].signature.packets[0].created).to.be.gte(+start); - expect(verified.signatures[0].valid).to.be.true; - const signingKey = await privateKey.keys[0].getSigningKey(); - expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - - it('should sign and verify cleartext data with a date in the past', function () { - const message = openpgp.cleartext.fromText(plaintext); - const past = new Date(2000); - const signOpt = { - message, - privateKeys: privateKey_1337.keys, - detached: true, - date: past, - armor: false - }; - const verifyOpt = { - message, - publicKeys: publicKey_1337.keys, - date: past - }; - return openpgp.sign(signOpt).then(function (signed) { - verifyOpt.signature = signed.signature; - return openpgp.verify(verifyOpt).then(async function (verified) { - expect(+verified.signatures[0].signature.packets[0].created).to.equal(+past); - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(verified.signatures[0].valid).to.be.true; - expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid, past)) - .to.be.not.null; - expect(verified.signatures[0].signature.packets.length).to.equal(1); - // now check with expiration checking disabled - verifyOpt.date = null; - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(+verified.signatures[0].signature.packets[0].created).to.equal(+past); - expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); - expect(verified.signatures[0].valid).to.be.true; - expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid, null)) - .to.be.not.null; - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - }); - - it('should sign and verify binary data with a date in the future', function () { - const future = new Date(2040, 5, 5, 5, 5, 5, 0); - const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); - const signOpt = { - message: openpgp.message.fromBinary(data), - privateKeys: privateKey_2038_2045.keys, - detached: true, - date: future, - armor: false - }; - const verifyOpt = { - publicKeys: publicKey_2038_2045.keys, - date: future - }; - return openpgp.sign(signOpt).then(function (signed) { - verifyOpt.message = openpgp.message.fromBinary(data); - verifyOpt.signature = signed.signature; - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(+verified.signatures[0].signature.packets[0].created).to.equal(+future); - expect([].slice.call(verified.data)).to.deep.equal([].slice.call(data)); - expect(verified.signatures[0].valid).to.be.true; - expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid, future)) - .to.be.not.null; - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - - it('should sign and verify binary data without one-pass signature', function () { - const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); - const signOpt = { - message: openpgp.message.fromBinary(data), - privateKeys: privateKey.keys, - armor: false - }; - const verifyOpt = { - publicKeys: publicKey.keys - }; - return openpgp.sign(signOpt).then(function (signed) { - const packets = new openpgp.packet.List(); - packets.push(signed.message.packets.findPacket(openpgp.enums.packet.signature)); - packets.push(signed.message.packets.findPacket(openpgp.enums.packet.literal)); - verifyOpt.message = new openpgp.message.Message(packets); - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect([].slice.call(verified.data)).to.deep.equal([].slice.call(data)); - expect(verified.signatures[0].valid).to.be.true; - expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid)) - .to.be.not.null; - expect(verified.signatures[0].signature.packets.length).to.equal(1); - }); - }); - - it('should streaming sign and verify binary data without one-pass signature', function () { - const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); - const signOpt = { - message: openpgp.message.fromBinary(data), - privateKeys: privateKey.keys, - armor: false, - streaming: 'web' - }; - const verifyOpt = { - publicKeys: publicKey.keys, - streaming: 'web' - }; - return openpgp.sign(signOpt).then(function (signed) { - const packets = new openpgp.packet.List(); - packets.push(signed.message.packets.findPacket(openpgp.enums.packet.signature)); - packets.push(signed.message.packets.findPacket(openpgp.enums.packet.literal)); - verifyOpt.message = new openpgp.message.Message(packets); - return openpgp.verify(verifyOpt); - }).then(async function (verified) { - expect(openpgp.stream.isStream(verified.data)).to.equal('web'); - expect([].slice.call(await openpgp.stream.readToEnd(verified.data))).to.deep.equal([].slice.call(data)); - expect(await verified.signatures[0].verified).to.be.true; - expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid)) - .to.be.not.null; - expect((await verified.signatures[0].signature).packets.length).to.equal(1); - }); - }); - - it('should encrypt and decrypt cleartext data with a date in the future', function () { - const future = new Date(2040, 5, 5, 5, 5, 5, 0); - const encryptOpt = { - message: openpgp.message.fromText(plaintext, undefined, future), - publicKeys: publicKey_2038_2045.keys, - date: future, - armor: false - }; - const decryptOpt = { - privateKeys: privateKey_2038_2045.keys, - date: future - }; - - return openpgp.encrypt(encryptOpt).then(function (encrypted) { - decryptOpt.message = encrypted.message; - return encrypted.message.decrypt(decryptOpt.privateKeys); - }).then(async function (packets) { - const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); - expect(literals.length).to.equal(1); - expect(+literals[0].date).to.equal(+future); - expect(await openpgp.stream.readToEnd(packets.getText())).to.equal(plaintext); - }); - }); - - it('should encrypt and decrypt binary data with a date in the past', function () { - const past = new Date(2005, 5, 5, 5, 5, 5, 0); - const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); - const encryptOpt = { - message: openpgp.message.fromBinary(data, undefined, past), - publicKeys: publicKey_2000_2008.keys, - date: past, - armor: false - }; - const decryptOpt = { - privateKeys: privateKey_2000_2008.keys, - date: past - }; - - return openpgp.encrypt(encryptOpt).then(function (encrypted) { - decryptOpt.message = encrypted.message; - return encrypted.message.decrypt(decryptOpt.privateKeys); - }).then(async function (packets) { - const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); - expect(literals.length).to.equal(1); - expect(+literals[0].date).to.equal(+past); - expect(await openpgp.stream.readToEnd(packets.getLiteralData())).to.deep.equal(data); - }); - }); - - it('should sign, encrypt and decrypt, verify cleartext data with a date in the past', function () { - const past = new Date(2005, 5, 5, 5, 5, 5, 0); - const encryptOpt = { - message: openpgp.message.fromText(plaintext, undefined, past), - publicKeys: publicKey_2000_2008.keys, - privateKeys: privateKey_2000_2008.keys, - date: past, - armor: false - }; - - return openpgp.encrypt(encryptOpt).then(function (encrypted) { - return encrypted.message.decrypt(encryptOpt.privateKeys); - }).then(async function (packets) { - const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); - expect(literals.length).to.equal(1); - expect(+literals[0].date).to.equal(+past); - const signatures = await packets.verify(encryptOpt.publicKeys, past); - expect(await openpgp.stream.readToEnd(packets.getText())).to.equal(plaintext); - expect(+(await signatures[0].signature).packets[0].created).to.equal(+past); - expect(await signatures[0].verified).to.be.true; - expect(await encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, past)) - .to.be.not.null; - expect((await signatures[0].signature).packets.length).to.equal(1); - }); - }); - - it('should sign, encrypt and decrypt, verify binary data with a date in the future', function () { - const future = new Date(2040, 5, 5, 5, 5, 5, 0); - const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); - const encryptOpt = { - message: openpgp.message.fromBinary(data, undefined, future), - publicKeys: publicKey_2038_2045.keys, - privateKeys: privateKey_2038_2045.keys, - date: future, - armor: false - }; - - return openpgp.encrypt(encryptOpt).then(function (encrypted) { - return encrypted.message.decrypt(encryptOpt.privateKeys); - }).then(async function (packets) { - const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); - expect(literals.length).to.equal(1); - expect(literals[0].format).to.equal('binary'); - expect(+literals[0].date).to.equal(+future); - const signatures = await packets.verify(encryptOpt.publicKeys, future); - expect(await openpgp.stream.readToEnd(packets.getLiteralData())).to.deep.equal(data); - expect(+(await signatures[0].signature).packets[0].created).to.equal(+future); - expect(await signatures[0].verified).to.be.true; - expect(await encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, future)) - .to.be.not.null; - expect((await signatures[0].signature).packets.length).to.equal(1); - }); - }); - - it('should sign, encrypt and decrypt, verify mime data with a date in the future', function () { - const future = new Date(2040, 5, 5, 5, 5, 5, 0); - const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); - const encryptOpt = { - message: openpgp.message.fromBinary(data, undefined, future, 'mime'), - publicKeys: publicKey_2038_2045.keys, - privateKeys: privateKey_2038_2045.keys, - date: future, - armor: false - }; - - return openpgp.encrypt(encryptOpt).then(function (encrypted) { - return encrypted.message.decrypt(encryptOpt.privateKeys); - }).then(async function (packets) { - const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); - expect(literals.length).to.equal(1); - expect(literals[0].format).to.equal('mime'); - expect(+literals[0].date).to.equal(+future); - const signatures = await packets.verify(encryptOpt.publicKeys, future); - expect(await openpgp.stream.readToEnd(packets.getLiteralData())).to.deep.equal(data); - expect(+(await signatures[0].signature).packets[0].created).to.equal(+future); - expect(await signatures[0].verified).to.be.true; - expect(await encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, future)) - .to.be.not.null; - expect((await signatures[0].signature).packets.length).to.equal(1); - }); - }); - - it('should fail to encrypt with revoked key', function() { - return openpgp.revokeKey({ - key: privateKey.keys[0] - }).then(function(revKey) { - return openpgp.encrypt({ - message: openpgp.message.fromText(plaintext), - publicKeys: revKey.publicKey - }).then(function(encrypted) { - throw new Error('Should not encrypt with revoked key'); - }).catch(function(error) { - expect(error.message).to.match(/Could not find valid key packet for encryption/); - }); - }); - }); - - it('should fail to encrypt with revoked subkey', async function() { - const pubKeyDE = (await openpgp.key.readArmored(pub_key_de)).keys[0]; - const privKeyDE = (await openpgp.key.readArmored(priv_key_de)).keys[0]; - await privKeyDE.decrypt(passphrase); - return privKeyDE.subKeys[0].revoke(privKeyDE.primaryKey).then(function(revSubKey) { - pubKeyDE.subKeys[0] = revSubKey; - return openpgp.encrypt({ - message: openpgp.message.fromText(plaintext), - publicKeys: pubKeyDE - }).then(function(encrypted) { - throw new Error('Should not encrypt with revoked subkey'); - }).catch(function(error) { - expect(error.message).to.match(/Could not find valid key packet for encryption/); - }); - }); - }); }); describe('ELG / DSA encrypt, decrypt, sign, verify', function() { @@ -2224,24 +1774,498 @@ describe('OpenPGP.js public api tests', function() { }); }); - describe('Errors', function() { + } - it('Error message should contain the original error message', function() { - return openpgp.encrypt({ - message: openpgp.message.fromBinary(new Uint8Array([0x01, 0x01, 0x01])), - passwords: null - }) - .then(function() { - throw new Error('Error expected.'); - }) - .catch(function(error) { - expect(error.message).to.match(/No keys, passwords, or session key provided/); - }); - }); + describe('AES / RSA sign, verify', function() { + const wrong_pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n' + + 'Version: OpenPGP.js v0.9.0\r\n' + + 'Comment: Hoodiecrow - https://hoodiecrow.com\r\n' + + '\r\n' + + 'xk0EUlhMvAEB/2MZtCUOAYvyLFjDp3OBMGn3Ev8FwjzyPbIF0JUw+L7y2XR5\r\n' + + 'RVGvbK88unV3cU/1tOYdNsXI6pSp/Ztjyv7vbBUAEQEAAc0pV2hpdGVvdXQg\r\n' + + 'VXNlciA8d2hpdGVvdXQudGVzdEB0LW9ubGluZS5kZT7CXAQQAQgAEAUCUlhM\r\n' + + 'vQkQ9vYOm0LN/0wAAAW4Af9C+kYW1AvNWmivdtr0M0iYCUjM9DNOQH1fcvXq\r\n' + + 'IiN602mWrkd8jcEzLsW5IUNzVPLhrFIuKyBDTpLnC07Loce1\r\n' + + '=6XMW\r\n' + + '-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n'; + let decryptedPrivateKey; + beforeEach(async function() { + if (!decryptedPrivateKey) { + expect(await privateKey.keys[0].decrypt(passphrase)).to.be.true; + decryptedPrivateKey = privateKey; + } + privateKey = decryptedPrivateKey; }); - } + it('should sign and verify cleartext data', function () { + const message = openpgp.cleartext.fromText(plaintext); + const signOpt = { + message, + privateKeys: privateKey.keys + }; + const verifyOpt = { + publicKeys: publicKey.keys + }; + return openpgp.sign(signOpt).then(async function (signed) { + expect(signed.data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/); + verifyOpt.message = await openpgp.cleartext.readArmored(signed.data); + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(verified.signatures[0].valid).to.be.true; + const signingKey = await privateKey.keys[0].getSigningKey(); + expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('should sign and verify cleartext data with multiple private keys', async function () { + const privKeyDE = (await openpgp.key.readArmored(priv_key_de)).keys[0]; + await privKeyDE.decrypt(passphrase); + + const message = openpgp.cleartext.fromText(plaintext); + const signOpt = { + message, + privateKeys: [privateKey.keys[0], privKeyDE] + }; + const verifyOpt = { + publicKeys: [publicKey.keys[0], privKeyDE.toPublic()] + }; + return openpgp.sign(signOpt).then(async function (signed) { + expect(signed.data).to.match(/-----BEGIN PGP SIGNED MESSAGE-----/); + verifyOpt.message = await openpgp.cleartext.readArmored(signed.data); + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + let signingKey; + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(verified.signatures[0].valid).to.be.true; + signingKey = await privateKey.keys[0].getSigningKey(); + expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); + expect(verified.signatures[0].signature.packets.length).to.equal(1); + expect(verified.signatures[1].valid).to.be.true; + signingKey = await privKeyDE.getSigningKey(); + expect(verified.signatures[1].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); + expect(verified.signatures[1].signature.packets.length).to.equal(1); + }); + }); + + it('should sign and verify cleartext data with detached signatures', function () { + const message = openpgp.cleartext.fromText(plaintext); + const signOpt = { + message, + privateKeys: privateKey.keys, + detached: true + }; + const verifyOpt = { + message, + publicKeys: publicKey.keys + }; + return openpgp.sign(signOpt).then(async function (signed) { + verifyOpt.signature = await openpgp.signature.readArmored(signed.signature); + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(verified.signatures[0].valid).to.be.true; + const signingKey = await privateKey.keys[0].getSigningKey(); + expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('should sign and fail to verify cleartext data with wrong public pgp key', async function () { + const message = openpgp.cleartext.fromText(plaintext); + const signOpt = { + message, + privateKeys: privateKey.keys + }; + const verifyOpt = { + publicKeys: (await openpgp.key.readArmored(wrong_pubkey)).keys + }; + return openpgp.sign(signOpt).then(async function (signed) { + verifyOpt.message = await openpgp.cleartext.readArmored(signed.data); + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(verified.signatures[0].valid).to.be.null; + const signingKey = await privateKey.keys[0].getSigningKey(); + expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('should sign and fail to verify cleartext data with wrong public pgp key with detached signature', async function () { + const message = openpgp.cleartext.fromText(plaintext); + const signOpt = { + message, + privateKeys: privateKey.keys, + detached: true + }; + const verifyOpt = { + message, + publicKeys: (await openpgp.key.readArmored(wrong_pubkey)).keys + }; + return openpgp.sign(signOpt).then(async function (signed) { + verifyOpt.signature = await openpgp.signature.readArmored(signed.signature); + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(verified.signatures[0].valid).to.be.null; + const signingKey = await privateKey.keys[0].getSigningKey(); + expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('should sign and verify cleartext data and not armor', function () { + const message = openpgp.cleartext.fromText(plaintext); + const signOpt = { + message, + privateKeys: privateKey.keys, + armor: false + }; + const verifyOpt = { + publicKeys: publicKey.keys + }; + return openpgp.sign(signOpt).then(function (signed) { + verifyOpt.message = signed.message; + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(verified.signatures[0].valid).to.be.true; + const signingKey = await privateKey.keys[0].getSigningKey(); + expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('should sign and verify cleartext data and not armor with detached signatures', function () { + const start = openpgp.util.normalizeDate(); + const message = openpgp.cleartext.fromText(plaintext); + const signOpt = { + message, + privateKeys: privateKey.keys, + detached: true, + armor: false + }; + const verifyOpt = { + message, + publicKeys: publicKey.keys + }; + return openpgp.sign(signOpt).then(function (signed) { + verifyOpt.signature = signed.signature; + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(+verified.signatures[0].signature.packets[0].created).to.be.lte(+openpgp.util.normalizeDate()); + expect(+verified.signatures[0].signature.packets[0].created).to.be.gte(+start); + expect(verified.signatures[0].valid).to.be.true; + const signingKey = await privateKey.keys[0].getSigningKey(); + expect(verified.signatures[0].keyid.toHex()).to.equal(signingKey.getKeyId().toHex()); + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('should sign and verify cleartext data with a date in the past', function () { + const message = openpgp.cleartext.fromText(plaintext); + const past = new Date(2000); + const signOpt = { + message, + privateKeys: privateKey_1337.keys, + detached: true, + date: past, + armor: false + }; + const verifyOpt = { + message, + publicKeys: publicKey_1337.keys, + date: past + }; + return openpgp.sign(signOpt).then(function (signed) { + verifyOpt.signature = signed.signature; + return openpgp.verify(verifyOpt).then(async function (verified) { + expect(+verified.signatures[0].signature.packets[0].created).to.equal(+past); + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(verified.signatures[0].valid).to.be.true; + expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid, past)) + .to.be.not.null; + expect(verified.signatures[0].signature.packets.length).to.equal(1); + // now check with expiration checking disabled + verifyOpt.date = null; + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(+verified.signatures[0].signature.packets[0].created).to.equal(+past); + expect(verified.data).to.equal(openpgp.util.removeTrailingSpaces(plaintext)); + expect(verified.signatures[0].valid).to.be.true; + expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid, null)) + .to.be.not.null; + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + }); + + it('should sign and verify binary data with a date in the future', function () { + const future = new Date(2040, 5, 5, 5, 5, 5, 0); + const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); + const signOpt = { + message: openpgp.message.fromBinary(data), + privateKeys: privateKey_2038_2045.keys, + detached: true, + date: future, + armor: false + }; + const verifyOpt = { + publicKeys: publicKey_2038_2045.keys, + date: future + }; + return openpgp.sign(signOpt).then(function (signed) { + verifyOpt.message = openpgp.message.fromBinary(data); + verifyOpt.signature = signed.signature; + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(+verified.signatures[0].signature.packets[0].created).to.equal(+future); + expect([].slice.call(verified.data)).to.deep.equal([].slice.call(data)); + expect(verified.signatures[0].valid).to.be.true; + expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid, future)) + .to.be.not.null; + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('should sign and verify binary data without one-pass signature', function () { + const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); + const signOpt = { + message: openpgp.message.fromBinary(data), + privateKeys: privateKey.keys, + armor: false + }; + const verifyOpt = { + publicKeys: publicKey.keys + }; + return openpgp.sign(signOpt).then(function (signed) { + const packets = new openpgp.packet.List(); + packets.push(signed.message.packets.findPacket(openpgp.enums.packet.signature)); + packets.push(signed.message.packets.findPacket(openpgp.enums.packet.literal)); + verifyOpt.message = new openpgp.message.Message(packets); + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect([].slice.call(verified.data)).to.deep.equal([].slice.call(data)); + expect(verified.signatures[0].valid).to.be.true; + expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid)) + .to.be.not.null; + expect(verified.signatures[0].signature.packets.length).to.equal(1); + }); + }); + + it('should streaming sign and verify binary data without one-pass signature', function () { + const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); + const signOpt = { + message: openpgp.message.fromBinary(data), + privateKeys: privateKey.keys, + armor: false, + streaming: 'web' + }; + const verifyOpt = { + publicKeys: publicKey.keys, + streaming: 'web' + }; + return openpgp.sign(signOpt).then(function (signed) { + const packets = new openpgp.packet.List(); + packets.push(signed.message.packets.findPacket(openpgp.enums.packet.signature)); + packets.push(signed.message.packets.findPacket(openpgp.enums.packet.literal)); + verifyOpt.message = new openpgp.message.Message(packets); + return openpgp.verify(verifyOpt); + }).then(async function (verified) { + expect(openpgp.stream.isStream(verified.data)).to.equal('web'); + expect([].slice.call(await openpgp.stream.readToEnd(verified.data))).to.deep.equal([].slice.call(data)); + expect(await verified.signatures[0].verified).to.be.true; + expect(await signOpt.privateKeys[0].getSigningKey(verified.signatures[0].keyid)) + .to.be.not.null; + expect((await verified.signatures[0].signature).packets.length).to.equal(1); + }); + }); + + it('should encrypt and decrypt cleartext data with a date in the future', function () { + const future = new Date(2040, 5, 5, 5, 5, 5, 0); + const encryptOpt = { + message: openpgp.message.fromText(plaintext, undefined, future), + publicKeys: publicKey_2038_2045.keys, + date: future, + armor: false + }; + const decryptOpt = { + privateKeys: privateKey_2038_2045.keys, + date: future + }; + + return openpgp.encrypt(encryptOpt).then(function (encrypted) { + decryptOpt.message = encrypted.message; + return encrypted.message.decrypt(decryptOpt.privateKeys); + }).then(async function (packets) { + const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); + expect(literals.length).to.equal(1); + expect(+literals[0].date).to.equal(+future); + expect(await openpgp.stream.readToEnd(packets.getText())).to.equal(plaintext); + }); + }); + + it('should encrypt and decrypt binary data with a date in the past', function () { + const past = new Date(2005, 5, 5, 5, 5, 5, 0); + const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); + const encryptOpt = { + message: openpgp.message.fromBinary(data, undefined, past), + publicKeys: publicKey_2000_2008.keys, + date: past, + armor: false + }; + const decryptOpt = { + privateKeys: privateKey_2000_2008.keys, + date: past + }; + + return openpgp.encrypt(encryptOpt).then(function (encrypted) { + decryptOpt.message = encrypted.message; + return encrypted.message.decrypt(decryptOpt.privateKeys); + }).then(async function (packets) { + const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); + expect(literals.length).to.equal(1); + expect(+literals[0].date).to.equal(+past); + expect(await openpgp.stream.readToEnd(packets.getLiteralData())).to.deep.equal(data); + }); + }); + + it('should sign, encrypt and decrypt, verify cleartext data with a date in the past', function () { + const past = new Date(2005, 5, 5, 5, 5, 5, 0); + const encryptOpt = { + message: openpgp.message.fromText(plaintext, undefined, past), + publicKeys: publicKey_2000_2008.keys, + privateKeys: privateKey_2000_2008.keys, + date: past, + armor: false + }; + + return openpgp.encrypt(encryptOpt).then(function (encrypted) { + return encrypted.message.decrypt(encryptOpt.privateKeys); + }).then(async function (packets) { + const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); + expect(literals.length).to.equal(1); + expect(+literals[0].date).to.equal(+past); + const signatures = await packets.verify(encryptOpt.publicKeys, past); + expect(await openpgp.stream.readToEnd(packets.getText())).to.equal(plaintext); + expect(+(await signatures[0].signature).packets[0].created).to.equal(+past); + expect(await signatures[0].verified).to.be.true; + expect(await encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, past)) + .to.be.not.null; + expect((await signatures[0].signature).packets.length).to.equal(1); + }); + }); + + it('should sign, encrypt and decrypt, verify binary data with a date in the future', function () { + const future = new Date(2040, 5, 5, 5, 5, 5, 0); + const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); + const encryptOpt = { + message: openpgp.message.fromBinary(data, undefined, future), + publicKeys: publicKey_2038_2045.keys, + privateKeys: privateKey_2038_2045.keys, + date: future, + armor: false + }; + + return openpgp.encrypt(encryptOpt).then(function (encrypted) { + return encrypted.message.decrypt(encryptOpt.privateKeys); + }).then(async function (packets) { + const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); + expect(literals.length).to.equal(1); + expect(literals[0].format).to.equal('binary'); + expect(+literals[0].date).to.equal(+future); + const signatures = await packets.verify(encryptOpt.publicKeys, future); + expect(await openpgp.stream.readToEnd(packets.getLiteralData())).to.deep.equal(data); + expect(+(await signatures[0].signature).packets[0].created).to.equal(+future); + expect(await signatures[0].verified).to.be.true; + expect(await encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, future)) + .to.be.not.null; + expect((await signatures[0].signature).packets.length).to.equal(1); + }); + }); + + it('should sign, encrypt and decrypt, verify mime data with a date in the future', function () { + const future = new Date(2040, 5, 5, 5, 5, 5, 0); + const data = new Uint8Array([3, 14, 15, 92, 65, 35, 59]); + const encryptOpt = { + message: openpgp.message.fromBinary(data, undefined, future, 'mime'), + publicKeys: publicKey_2038_2045.keys, + privateKeys: privateKey_2038_2045.keys, + date: future, + armor: false + }; + + return openpgp.encrypt(encryptOpt).then(function (encrypted) { + return encrypted.message.decrypt(encryptOpt.privateKeys); + }).then(async function (packets) { + const literals = packets.packets.filterByTag(openpgp.enums.packet.literal); + expect(literals.length).to.equal(1); + expect(literals[0].format).to.equal('mime'); + expect(+literals[0].date).to.equal(+future); + const signatures = await packets.verify(encryptOpt.publicKeys, future); + expect(await openpgp.stream.readToEnd(packets.getLiteralData())).to.deep.equal(data); + expect(+(await signatures[0].signature).packets[0].created).to.equal(+future); + expect(await signatures[0].verified).to.be.true; + expect(await encryptOpt.privateKeys[0].getSigningKey(signatures[0].keyid, future)) + .to.be.not.null; + expect((await signatures[0].signature).packets.length).to.equal(1); + }); + }); + + it('should fail to encrypt with revoked key', function() { + return openpgp.revokeKey({ + key: privateKey.keys[0] + }).then(function(revKey) { + return openpgp.encrypt({ + message: openpgp.message.fromText(plaintext), + publicKeys: revKey.publicKey + }).then(function(encrypted) { + throw new Error('Should not encrypt with revoked key'); + }).catch(function(error) { + expect(error.message).to.match(/Could not find valid key packet for encryption/); + }); + }); + }); + + it('should fail to encrypt with revoked subkey', async function() { + const pubKeyDE = (await openpgp.key.readArmored(pub_key_de)).keys[0]; + const privKeyDE = (await openpgp.key.readArmored(priv_key_de)).keys[0]; + await privKeyDE.decrypt(passphrase); + return privKeyDE.subKeys[0].revoke(privKeyDE.primaryKey).then(function(revSubKey) { + pubKeyDE.subKeys[0] = revSubKey; + return openpgp.encrypt({ + message: openpgp.message.fromText(plaintext), + publicKeys: pubKeyDE + }).then(function(encrypted) { + throw new Error('Should not encrypt with revoked subkey'); + }).catch(function(error) { + expect(error.message).to.match(/Could not find valid key packet for encryption/); + }); + }); + }); + + }); + + describe('Errors', function() { + + it('Error message should contain the original error message', function() { + return openpgp.encrypt({ + message: openpgp.message.fromBinary(new Uint8Array([0x01, 0x01, 0x01])), + passwords: null + }) + .then(function() { + throw new Error('Error expected.'); + }) + .catch(function(error) { + expect(error.message).to.match(/No keys, passwords, or session key provided/); + }); + }); + + }); });