diff --git a/.gitignore b/.gitignore index dc99ae877bb12722f60c567114629f5e6775dff8..85cddf43fab0fa2cb4c825e8fab117ea7cb7ff85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,62 @@ -.DS_Store +# Dependencies node_modules -/dist +# Logs +*.log* -# local env files -.env.local -.env.*.local +# Temp directories +.temp +.tmp +.cache -# Log files -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -package-lock.json +# Yarn +**/.yarn/cache +**/.yarn/*state* -# Editor directories and files -.idea +# Generated dirs +dist + +# Nuxt +.nuxt +.output +.vercel +.build-* +.env +.netlify + +# Env +.env + +# Testing +reports +coverage +*.lcov +.nyc_output +dev-dist/ + +# VSCode .vscode/* -!.vscode/preview.yml -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Intellij idea +*.iml +.idea + +# OSX +.DS_Store +.AppleDouble +.LSOverride +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Playwright test +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/.pnpm-store/v3/files/01/6ef54e9c511cd83c329950563bbdb4416f5cfbd7e367b4c0f6249eeb524ad0ee02357df6f59359879de23c6bfe0ae4d85b4a02ebf62af749c5c9f65b9f6aca-index.json b/.pnpm-store/v3/files/01/6ef54e9c511cd83c329950563bbdb4416f5cfbd7e367b4c0f6249eeb524ad0ee02357df6f59359879de23c6bfe0ae4d85b4a02ebf62af749c5c9f65b9f6aca-index.json deleted file mode 100644 index 5f8c3c9c786bb0e8e68a5b90a8bffe5042f54581..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/01/6ef54e9c511cd83c329950563bbdb4416f5cfbd7e367b4c0f6249eeb524ad0ee02357df6f59359879de23c6bfe0ae4d85b4a02ebf62af749c5c9f65b9f6aca-index.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"nuxi","version":"3.11.1","files":{"LICENSE":{"checkedAt":1715158492551,"integrity":"sha512-Xxi7X7FVqA9+SoKwU4qJToWGtqDgzbWlYwpMC1FwFXihO57B5xXALXavysMMh8E4uwqkGQJjCika9SXMGSzjyg==","mode":420,"size":1071},"package.json":{"checkedAt":1715158492552,"integrity":"sha512-GcWMOlpDnb8NpNRHLXT/pawieaX1+/S2B1CLlS1CbyH25apLAtBDnoCE6yVMhEhd8CYYmYE3bW3dE7gHfFBjtw==","mode":420,"size":2465},"README.md":{"checkedAt":1715158492551,"integrity":"sha512-e2BJzsmfaPvOS2PUooCkBmBowRN1FfX2b+aSn46VCrfQspBwvVqJCfm7DFZi7IMwpG5mltfAx088ANWUQ61gPw==","mode":420,"size":922},"dist/chunks/add.mjs":{"checkedAt":1715158492553,"integrity":"sha512-dFV50x8iAkGZmuItO1Zyvf0ZPiPx9Jx1tku9d0axsvEPSzOQg5sBmcGiBb5E/BXZQAdVst77uk/uw2QLv67T0A==","mode":420,"size":4964},"dist/chunks/add2.mjs":{"checkedAt":1715158492597,"integrity":"sha512-dKB/UtXdxgMkhhK97yuRLhznBZHzWoBUnZUKuD0edHWbyrmqTqJlmzQgJYbJxZCLYiVXFBA5+HQ/Xb+8qcjABw==","mode":420,"size":889260},"dist/chunks/analyze.mjs":{"checkedAt":1715158492597,"integrity":"sha512-iGo9t2j6fi2yP3bZ7tkQ8GNKa71neFCydQjFSntiOIlxsPw55wlYoz3VfDCdh9zZcdgaehPhwS8eCb485lWxUg==","mode":420,"size":4362},"dist/chunks/build-module.mjs":{"checkedAt":1715158492597,"integrity":"sha512-UVRE5UXWLqfQuolE1js6UwJiEzlD+1GqzT+d8uLTiJHdc9bueuDs9ADElWIxEOSU6eSp1g3ucuFF5EfkzkDhyA==","mode":420,"size":2106},"dist/chunks/build.mjs":{"checkedAt":1715158492597,"integrity":"sha512-Pbf719mlHW3qhuHaedp/FO4ixa8SLGsj2ZKdjW6d2vkhHSJWQN6Gq46DyWDQe5uoEnod4kgQwBu2Xvurv8AUxg==","mode":420,"size":3235},"dist/chunks/cleanup.mjs":{"checkedAt":1715158492597,"integrity":"sha512-JEFbCBSBTEZSQIGbYgKiEMqccRK1qvdEMycQ0XUbZT/dCl0rHjkWRDpj8WWu/eofxdQ2OJX4peusDIIFKktieg==","mode":420,"size":1483},"dist/chunks/dev-child.mjs":{"checkedAt":1715158492597,"integrity":"sha512-wwW+mrE5NMjvCYgy/4VpdZAJ7I4BBJrn5u3Tnhqe73clGsdE99k7VnDLOvR5TP+bkGkNdXOfDaA+BnVxUOgQdw==","mode":420,"size":2937},"dist/chunks/dev.mjs":{"checkedAt":1715158492600,"integrity":"sha512-1aWH8/JQEWPl8EjELRDcZpmC62mDQiG80obt7yuvxVE4Pd4du/8GjXTX6qOR0DsxDwJI1wzibgysR/J8LN1B6g==","mode":420,"size":10090},"dist/chunks/dev2.mjs":{"checkedAt":1715158492606,"integrity":"sha512-qdCtXbOWsT1L8ztlkQnJqaTdB5eYWNI90vqYXxiH7axGIHL5Qj1Y3CpYxxExAdipv3L2kdxO+x6T4mV0WqW0eQ==","mode":420,"size":185516},"dist/chunks/devtools.mjs":{"checkedAt":1715158492606,"integrity":"sha512-HwBRjydqn8kq8v2s9M2k8jUgF33k/jFdF8fZNlHQlT73qWO2FaGA/1GC+fhueRYxlIU/cbXuWZT3XKfwZdFScg==","mode":420,"size":1279},"dist/chunks/generate.mjs":{"checkedAt":1715158492606,"integrity":"sha512-dkOuOfVtMLrtrs0m4xkjl3N+Ug8VCwGX8WcpuODcr04gsW6/Gcerv9lR0yrLZGcffvCwIH24hu179Ws7mGfYdA==","mode":420,"size":1473},"dist/chunks/index.mjs":{"checkedAt":1715158492606,"integrity":"sha512-oP3wGmWQ0SQw9cmaGK+TsN4abdM1LvEa2cdD4eTDygSJreMbMDjXV/gS1+cXWSGdb96TjDExc7YiV4ayO6IcrQ==","mode":420,"size":473},"dist/index.mjs":{"checkedAt":1715158492607,"integrity":"sha512-pBNDCbJJCxGNKTCptfAGeQJ5ldZ1iGdI27/PpLmqZwUqrvXVXnysAUMUtDSAs08jYiFj0YSMhByLlCOppG2PLw==","mode":420,"size":188},"dist/chunks/index2.mjs":{"checkedAt":1715158492641,"integrity":"sha512-PS08FathScChFehwsJeKjNzn0im5CtDEwJM6UvML6sbO639hgx1ntxKOZRzM3PZabtacOyWkvx1/yWJygUz9Fw==","mode":420,"size":902613},"dist/chunks/index3.mjs":{"checkedAt":1715158492643,"integrity":"sha512-pqm5fHGUpr3wmIZzzqA8PE5RI1CeR+3Ps3aYoFkZcbVbsQWqDWKUXWCgQwbQpOyTcFbK6BUWHVBrPTurpqq1MQ==","mode":420,"size":70175},"dist/chunks/index4.mjs":{"checkedAt":1715158492643,"integrity":"sha512-FkihMUJMYTWPps9+30volQ6riEYZUBPzIKJa/M7DHk83BprTnO95yL6VWmjSyo0nHooB1KfljEPloSC4CUDE4w==","mode":420,"size":17660},"dist/chunks/index5.mjs":{"checkedAt":1715158492643,"integrity":"sha512-LDaX+aE9yV5TV7yPJLkA2FXx1GoCkRvteIoCVQqFiBzKBMPgOpUg9gv3x4l+lQCI93oyRZCPTAo46AimIOxQdQ==","mode":420,"size":1489},"dist/chunks/index6.mjs":{"checkedAt":1715158492643,"integrity":"sha512-cy15RybftksjsoOkONGnADxltwz9xdflgsOOT2vbfyL9J9hQcwhRbbDs7HUe9XtcX7RImEY5YLg0a7kfIa9W3g==","mode":420,"size":7304},"dist/chunks/index7.mjs":{"checkedAt":1715158492643,"integrity":"sha512-6t083A0P/ukPzBmuAE9GBXLVDjSCx2x1olLt6xO8spzLRM+tNZ2DQ5iy1VCCUwgPjlgm2+aBio94wtNnfAcNVg==","mode":420,"size":6253},"dist/chunks/info.mjs":{"checkedAt":1715158492646,"integrity":"sha512-9cnZwlV9ma8QP08R8PWjPlSe5VFchSHSLqW8UeiDld8uO3tRYUgjgn8MMXR6k+/M7rHEdJL17SAg/qUzs3Ya6A==","mode":420,"size":5481},"dist/chunks/init.mjs":{"checkedAt":1715158492650,"integrity":"sha512-vzTYDwjm0LkY0uc+3fWQhYiQmrFFSKP/HaD7FAaApsPuzz/upBI5c7c67+twhpMUWlnbg1Ai8MMZhUE5X3Iiaw==","mode":420,"size":193228},"dist/chunks/multipart-parser.mjs":{"checkedAt":1715158492650,"integrity":"sha512-GMOg4R5Jk97NW++eoZfBznwoN0GXrd/iBSWEbLMU+7r3kZ8Pm5C10DfpT6YdgDesAJjgQRoLUvSz+wWCGTyJdw==","mode":420,"size":5242},"dist/chunks/node.mjs":{"checkedAt":1715158492655,"integrity":"sha512-j44zgoHCh5ZYR8B6WYSRHwXUbcUIGHFqBmFF8vDDKq0F6B8bH2u2aWTexyNw+lzUREv3fE7nKgU4621bXDdYyw==","mode":420,"size":126062},"dist/shared/nuxi.0f575f79.mjs":{"checkedAt":1715158492655,"integrity":"sha512-0iDkjJUcWoNbyGd8/XdnLYT5PZqhclvYs20FFtdI5a3F24vCfirVMeQ+PuKh6F1ZVnNwbpy2rhm4V9zldFt4bg==","mode":420,"size":6292},"dist/shared/nuxi.17654120.mjs":{"checkedAt":1715158492657,"integrity":"sha512-o8cZagZZ0jyHbDo1diDM+a3IhHQaFV8Bx0n5/8WIHOLq8NqkDutd6vC4x/L292/xuJi2/CyaxGMK2KoKczYwCQ==","mode":420,"size":778},"dist/shared/nuxi.1902c37d.mjs":{"checkedAt":1715158492672,"integrity":"sha512-xAOPcGhlu1fNtPcHDy5OPazH66PRuBx8pIq6EzZRQd08e6PqvPm7H/wAWsMU0hgqltjKFM0PltHLEX7zmujrtQ==","mode":420,"size":273826},"dist/shared/nuxi.1e36f2d5.mjs":{"checkedAt":1715158492671,"integrity":"sha512-9e1j+ZqJz3L6rKeKkCiDx44/PiroCwg/ROVNbI4rI/yylmQ9n1pvYDVt8tJiTuO1Seyu40/V3ZAJbfhMNCI4rA==","mode":420,"size":17431},"dist/shared/nuxi.1ff5d6e2.mjs":{"checkedAt":1715158492672,"integrity":"sha512-dN+oynjTX43KpMU47ey2kZo+Ibnvvog9d+fcvLkFZHzjkJ4MkTOOLPEfCxjoDaef+QFbYtj129xeB23CvfAgbw==","mode":420,"size":1499},"dist/shared/nuxi.2155838d.mjs":{"checkedAt":1715158492672,"integrity":"sha512-EAN3JrcDYMoPPgJYj9kRfI0W3rv79I52So/z36C10kAa4OjlL7IwgucUd6e6Wz+k9EDFZSk9PTErAFJsJGTQJQ==","mode":420,"size":1035},"dist/shared/nuxi.2509f57e.mjs":{"checkedAt":1715158492672,"integrity":"sha512-S7ClWljw/yrn3Hug6b+gOlmVuXnRrDg4ng3KThe8Xvqb4UTFyYCDhbvpDgARd+PVJyCG5vCcjqeAiFEXn/9Nzw==","mode":420,"size":330},"dist/shared/nuxi.29475410.mjs":{"checkedAt":1715158492672,"integrity":"sha512-qjqJy7bt9OTn+o7wccIMnwTlMxK3GqUILBsKvsYyQjJzY8imgg8fxk0Poi82NGcRCoaq++bq4s7VTfivyBlEuA==","mode":420,"size":15276},"dist/shared/nuxi.349af404.mjs":{"checkedAt":1715158492672,"integrity":"sha512-DIKc2VPM/qrgSOmwH8UL80nh1FZxf2ml/L+uMoIcP9dSZCN3JBZKzMzqVmpATMl5Iq1BNgU1Z3bf9/Sp0cITMQ==","mode":420,"size":1580},"dist/shared/nuxi.34ba5283.mjs":{"checkedAt":1715158492693,"integrity":"sha512-Lc5qacpi4ViMW5+KThTYtkwe9PwlZrWkPa5vW3QyKLkfdpe7KCVNr9yvMUHYU34XUFNEtZ259j20ctw8CJ4V5w==","mode":420,"size":146515},"dist/shared/nuxi.4ac76f59.mjs":{"checkedAt":1715158492693,"integrity":"sha512-EBIW3pPx0TZb22ys+CqLUEhEanuAACWlc4bDRT2dmKncTrQ1xbYbtIZs5FOtIKzF+FQcSARoo/ky1bWZ4Hlf+Q==","mode":420,"size":2085},"dist/shared/nuxi.53f5921c.mjs":{"checkedAt":1715158492694,"integrity":"sha512-xrNnJyyFv1md+t1xQuWDq+oLrNPd3Fy7eD4hVGByUQufEcxAmcrYvNZu4AfTKy858vQmOzxfvZpSy0s916XGag==","mode":420,"size":7021},"dist/shared/nuxi.5aaa4630.mjs":{"checkedAt":1715158492695,"integrity":"sha512-7nT7F3Dbl8IMCj/M/R/NQ2fs4xat/puQvq7MJaHv9HkxvPjqYIqS9ugpaxHv/U352p7i54Q1tocm1vwceAoouw==","mode":420,"size":660},"dist/shared/nuxi.610c92ff.mjs":{"checkedAt":1715158492695,"integrity":"sha512-u5bFXlIervtqaRkB8WK+ZJLBYHxtmxTT0NsQncJDTtZ/WkcOASN9Pg4kHXurvF0Ij24kiuQ/cPFX3vv2dmUgNA==","mode":420,"size":6782},"dist/shared/nuxi.73800aa7.mjs":{"checkedAt":1715158492741,"integrity":"sha512-/k9ztWp6NnBFe0LIYkgpJLIdM4mmeir89Bkc5TpTwyWq0h6D/WNG0atkhBmrLkzr27jPqutloYJcD2g+5U2bTw==","mode":420,"size":1905463},"dist/shared/nuxi.9edf0930.mjs":{"checkedAt":1715158492743,"integrity":"sha512-dTTMP2+SBds4kZpNbrGXgYZjMRxCcJ0pkhQQusm87kvS354AQaCMdjRYQic8sGUT2dwBtpjWo8YE++t7ds4QIg==","mode":420,"size":75206},"dist/shared/nuxi.c282fbf5.mjs":{"checkedAt":1715158492744,"integrity":"sha512-5k2EIpdYdL/YKoHf2p1bhF71eLEoCiUAZzCdZ0yMaVitZ34QKTRM7BwyAshPU6AD+FzEz+MUEwC+ESzwg+byFw==","mode":420,"size":19969},"dist/shared/nuxi.c8477004.mjs":{"checkedAt":1715158492745,"integrity":"sha512-CspyHUXcmdcCc+1IKAwwZ+cpW402HvsO6p6yrrO/oYlcmhP8nbPJQjgjkUATlgIFbMA9rsUaCv028/bxjhrlMA==","mode":420,"size":665},"dist/shared/nuxi.cc8dd4a9.mjs":{"checkedAt":1715158492745,"integrity":"sha512-i4qiduA5Hhxiqj677fc871PKSRQCD2MNVQDzKfo1GAKOy+adtTZyz7sRcHmN/8of75FvMXMyvNhaS146OLGZWQ==","mode":420,"size":8930},"dist/shared/nuxi.d3241ca4.mjs":{"checkedAt":1715158492745,"integrity":"sha512-23rTdZCwH1GvBbYIItyTm13OHY3pZvWWPoiKkT1lQbvZbRAwyF9M0FGbks8+tJsJ9D6/L4hrrkucI7HXsQIZZA==","mode":420,"size":3460},"dist/shared/nuxi.dc1b30dc.mjs":{"checkedAt":1715158492748,"integrity":"sha512-JdzwNWaHq++d8zuZI1oNfPR6Xt8khnIyCSLOyCFst/rBjaKp2x1KU7nuZ9zYSKNmZe7bcnC1paqs2IRGZywZXA==","mode":420,"size":68932},"dist/shared/nuxi.eaa29140.mjs":{"checkedAt":1715158492748,"integrity":"sha512-6QM77w4EVBUZWKRclsMBW7f8PJpLVydgq0T8L+1b+WWe2mBubcgEKCp7SfzGAk96tTJUCSfAyRCDTg9N85qtbQ==","mode":420,"size":1600},"bin/nuxi.mjs":{"checkedAt":1715158492748,"integrity":"sha512-fZWFwXMMjDoOEG9aJaU6jgUJclrX+6e34zfVxHjLllI/I9n6cp6f+ieZrvcE5/T1lklIbBAcmbcMoPWpAWGlvQ==","mode":493,"size":210},"dist/chunks/satisfies.mjs":{"checkedAt":1715158492750,"integrity":"sha512-xnK1t9bcWb6NIYV6NPgR5DIAtQ45nPBY4HbXobOlCvw6nDHAacwxSaRv7dB2x/secI9LSRBKxdR9MAtBkk6YcQ==","mode":420,"size":48907},"dist/chunks/prepare.mjs":{"checkedAt":1715158492752,"integrity":"sha512-4kXg4CIZhwObu4eu8PVifZrBwlVUZWFkzfJgtWVVLtRSDcJrlkxHk76pvBMWPrkVnulfUFR4TO8Un9iHw2iiFA==","mode":420,"size":1875},"dist/chunks/preview.mjs":{"checkedAt":1715158492756,"integrity":"sha512-eVn7m2aetFbXiWZSqY4XBrI0cYUNdFWXij4ueSLUzU8zmM6fupfRMD+iTaCMqxchfvf39Xh/R43MRQnuq4xQ9g==","mode":420,"size":4123},"dist/chunks/prompt.mjs":{"checkedAt":1715158492756,"integrity":"sha512-O/Epnph0tKqH6cQxZEeyQufomoOU+HOh54uyntjMV9cbbc70fLUfUyifooIwroLyzVtY//Oe6ZSMNKCfOBCW3g==","mode":420,"size":44064},"dist/chunks/upgrade.mjs":{"checkedAt":1715158492756,"integrity":"sha512-2rAKD7cbZ7eMDfDmayMooAvp6DQgFEwMEkksr+WJjgNcEeP6rU1B1D4vTEs69QxA+B6xEpt26SQKCtt+1F4HDQ==","mode":420,"size":4765},"dist/chunks/typecheck.mjs":{"checkedAt":1715158492756,"integrity":"sha512-5zIyM/wRThgpGE1RTvEISZD6yvFbT3Lq3N4u0/dDWpvUSy8KweKGT1FejfaxK6KSqcJdFYT6LAAzNg+LVbvO8A==","mode":420,"size":2398},"dist/chunks/search.mjs":{"checkedAt":1715158492756,"integrity":"sha512-KD1m9fQenjfI4m3X1bfUh6eeKGjoC4KqRDKIZXVTKaqasq+EM/DiYOzv60fvE0/yK7v3LTd2SLJ4mplMcksmNw==","mode":420,"size":45221},"dist/chunks/test.mjs":{"checkedAt":1715158492759,"integrity":"sha512-evjrwZ+KiCpv97hVvwJGWAl5xt9IYf4W33WxL87wDzoCwnpX1c0CDT6Gq5giBAJkTMSUkeVH6yBvQ3JNP2CpXg==","mode":420,"size":1596},"dist/chunks/xdg-open.mjs":{"checkedAt":1715158492760,"integrity":"sha512-B8w8NzhEmKEhDmTKTJ4zQfyjjNolXJttrcEaIqc2eKlIRAge8ZH88jk5Ogdy+p+R7UET86jsGCfVxTcIbaBROw==","mode":420,"size":25951},"dist/index.d.mts":{"checkedAt":1715158492762,"integrity":"sha512-bKZ9GYaM6GOK4Kqp5MnPttibrm+SzfQPZK0DYSMJ5AHBC2v2ReDJboYiRzPTvG4F9sd+HTYXnrVVO85UQBdhdg==","mode":420,"size":253},"dist/index.d.ts":{"checkedAt":1715158492762,"integrity":"sha512-bKZ9GYaM6GOK4Kqp5MnPttibrm+SzfQPZK0DYSMJ5AHBC2v2ReDJboYiRzPTvG4F9sd+HTYXnrVVO85UQBdhdg==","mode":420,"size":253}}} \ No newline at end of file diff --git a/.pnpm-store/v3/files/07/cc3c37384498a1210e64ca4c9e3341fca38cda255c9b6dadc11a22a73678a94844081ef191fcf239393a0772fa9f91ed4113f3a8ec1827d5c537086da0513b b/.pnpm-store/v3/files/07/cc3c37384498a1210e64ca4c9e3341fca38cda255c9b6dadc11a22a73678a94844081ef191fcf239393a0772fa9f91ed4113f3a8ec1827d5c537086da0513b deleted file mode 100644 index 8fd6b007c22016ceb16aba4b95d801f0250ad78d..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/07/cc3c37384498a1210e64ca4c9e3341fca38cda255c9b6dadc11a22a73678a94844081ef191fcf239393a0772fa9f91ed4113f3a8ec1827d5c537086da0513b +++ /dev/null @@ -1,1069 +0,0 @@ -const xdgOpenScript = () => `#!/bin/sh -#--------------------------------------------- -# xdg-open -# -# Utility script to open a URL in the registered default application. -# -# Refer to the usage() function below for usage. -# -# Copyright 2009-2010, Fathi Boudra -# Copyright 2009-2010, Rex Dieter -# Copyright 2006, Kevin Krammer -# Copyright 2006, Jeremy White -# -# LICENSE: -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -#--------------------------------------------- - -manualpage() -{ -cat << _MANUALPAGE -Name - - xdg-open -- opens a file or URL in the user's preferred - application - -Synopsis - - xdg-open { file | URL } - - xdg-open { --help | --manual | --version } - -Description - - xdg-open opens a file or URL in the user's preferred - application. If a URL is provided the URL will be opened in the - user's preferred web browser. If a file is provided the file - will be opened in the preferred application for files of that - type. xdg-open supports file, ftp, http and https URLs. - - xdg-open is for use inside a desktop session only. It is not - recommended to use xdg-open as root. - -Options - - --help - Show command synopsis. - - --manual - Show this manual page. - - --version - Show the xdg-utils version information. - -Exit Codes - - An exit code of 0 indicates success while a non-zero exit code - indicates failure. The following failure codes can be returned: - - 1 - Error in command line syntax. - - 2 - One of the files passed on the command line did not - exist. - - 3 - A required tool could not be found. - - 4 - The action failed. - -See Also - - xdg-mime(1), xdg-settings(1), MIME applications associations - specification - -Examples - -xdg-open 'http://www.freedesktop.org/' - - Opens the freedesktop.org website in the user's default - browser. - -xdg-open /tmp/foobar.png - - Opens the PNG image file /tmp/foobar.png in the user's default - image viewing application. -_MANUALPAGE -} - -usage() -{ -cat << _USAGE - xdg-open -- opens a file or URL in the user's preferred - application - -Synopsis - - xdg-open { file | URL } - - xdg-open { --help | --manual | --version } - -_USAGE -} - -#@xdg-utils-common@ - -#---------------------------------------------------------------------------- -# Common utility functions included in all XDG wrapper scripts -#---------------------------------------------------------------------------- - -DEBUG() -{ - [ -z "\${XDG_UTILS_DEBUG_LEVEL}" ] && return 0; - [ \${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0; - shift - echo "$@" >&2 -} - -# This handles backslashes but not quote marks. -first_word() -{ - read first rest - echo "$first" -} - -#------------------------------------------------------------- -# map a binary to a .desktop file -binary_to_desktop_file() -{ - search="\${XDG_DATA_HOME:-$HOME/.local/share}:\${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" - binary="\`which "$1"\`" - binary="\`readlink -f "$binary"\`" - base="\`basename "$binary"\`" - IFS=: - for dir in $search; do - unset IFS - [ "$dir" ] || continue - [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue - for file in "$dir"/applications/*.desktop "$dir"/applications/*/*.desktop "$dir"/applnk/*.desktop "$dir"/applnk/*/*.desktop; do - [ -r "$file" ] || continue - # Check to make sure it's worth the processing. - grep -q "^Exec.*$base" "$file" || continue - # Make sure it's a visible desktop file (e.g. not "preferred-web-browser.desktop"). - grep -Eq "^(NoDisplay|Hidden)=true" "$file" && continue - command="\`grep -E "^Exec(\\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word\`" - command="\`which "$command"\`" - if [ x"\`readlink -f "$command"\`" = x"$binary" ]; then - # Fix any double slashes that got added path composition - echo "$file" | sed -e 's,//*,/,g' - return - fi - done - done -} - -#------------------------------------------------------------- -# map a .desktop file to a binary -desktop_file_to_binary() -{ - search="\${XDG_DATA_HOME:-$HOME/.local/share}:\${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" - desktop="\`basename "$1"\`" - IFS=: - for dir in $search; do - unset IFS - [ "$dir" ] && [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue - # Check if desktop file contains - - if [ "\${desktop#*-}" != "$desktop" ]; then - vendor=\${desktop%-*} - app=\${desktop#*-} - if [ -r $dir/applications/$vendor/$app ]; then - file_path=$dir/applications/$vendor/$app - elif [ -r $dir/applnk/$vendor/$app ]; then - file_path=$dir/applnk/$vendor/$app - fi - fi - if test -z "$file_path" ; then - for indir in "$dir"/applications/ "$dir"/applications/*/ "$dir"/applnk/ "$dir"/applnk/*/; do - file="$indir/$desktop" - if [ -r "$file" ]; then - file_path=$file - break - fi - done - fi - if [ -r "$file_path" ]; then - # Remove any arguments (%F, %f, %U, %u, etc.). - command="\`grep -E "^Exec(\\[[^]=]*])?=" "$file_path" | cut -d= -f 2- | first_word\`" - command="\`which "$command"\`" - readlink -f "$command" - return - fi - done -} - -#------------------------------------------------------------- -# Exit script on successfully completing the desired operation - -exit_success() -{ - if [ $# -gt 0 ]; then - echo "$@" - echo - fi - - exit 0 -} - - -#----------------------------------------- -# Exit script on malformed arguments, not enough arguments -# or missing required option. -# prints usage information - -exit_failure_syntax() -{ - if [ $# -gt 0 ]; then - echo "xdg-open: $@" >&2 - echo "Try 'xdg-open --help' for more information." >&2 - else - usage - echo "Use 'man xdg-open' or 'xdg-open --manual' for additional info." - fi - - exit 1 -} - -#------------------------------------------------------------- -# Exit script on missing file specified on command line - -exit_failure_file_missing() -{ - if [ $# -gt 0 ]; then - echo "xdg-open: $@" >&2 - fi - - exit 2 -} - -#------------------------------------------------------------- -# Exit script on failure to locate necessary tool applications - -exit_failure_operation_impossible() -{ - if [ $# -gt 0 ]; then - echo "xdg-open: $@" >&2 - fi - - exit 3 -} - -#------------------------------------------------------------- -# Exit script on failure returned by a tool application - -exit_failure_operation_failed() -{ - if [ $# -gt 0 ]; then - echo "xdg-open: $@" >&2 - fi - - exit 4 -} - -#------------------------------------------------------------ -# Exit script on insufficient permission to read a specified file - -exit_failure_file_permission_read() -{ - if [ $# -gt 0 ]; then - echo "xdg-open: $@" >&2 - fi - - exit 5 -} - -#------------------------------------------------------------ -# Exit script on insufficient permission to write a specified file - -exit_failure_file_permission_write() -{ - if [ $# -gt 0 ]; then - echo "xdg-open: $@" >&2 - fi - - exit 6 -} - -check_input_file() -{ - if [ ! -e "$1" ]; then - exit_failure_file_missing "file '$1' does not exist" - fi - if [ ! -r "$1" ]; then - exit_failure_file_permission_read "no permission to read file '$1'" - fi -} - -check_vendor_prefix() -{ - file_label="$2" - [ -n "$file_label" ] || file_label="filename" - file=\`basename "$1"\` - case "$file" in - [[:alpha:]]*-*) - return - ;; - esac - - echo "xdg-open: $file_label '$file' does not have a proper vendor prefix" >&2 - echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2 - echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2 - echo "Use --novendor to override or 'xdg-open --manual' for additional info." >&2 - exit 1 -} - -check_output_file() -{ - # if the file exists, check if it is writeable - # if it does not exists, check if we are allowed to write on the directory - if [ -e "$1" ]; then - if [ ! -w "$1" ]; then - exit_failure_file_permission_write "no permission to write to file '$1'" - fi - else - DIR=\`dirname "$1"\` - if [ ! -w "$DIR" ] || [ ! -x "$DIR" ]; then - exit_failure_file_permission_write "no permission to create file '$1'" - fi - fi -} - -#---------------------------------------- -# Checks for shared commands, e.g. --help - -check_common_commands() -{ - while [ $# -gt 0 ] ; do - parm="$1" - shift - - case "$parm" in - --help) - usage - echo "Use 'man xdg-open' or 'xdg-open --manual' for additional info." - exit_success - ;; - - --manual) - manualpage - exit_success - ;; - - --version) - echo "xdg-open 1.1.3" - exit_success - ;; - esac - done -} - -check_common_commands "$@" - -[ -z "\${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL; -if [ \${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then - # Be silent - xdg_redirect_output=" > /dev/null 2> /dev/null" -else - # All output to stderr - xdg_redirect_output=" >&2" -fi - -#-------------------------------------- -# Checks for known desktop environments -# set variable DE to the desktop environments name, lowercase - -detectDE() -{ - # see https://bugs.freedesktop.org/show_bug.cgi?id=34164 - unset GREP_OPTIONS - - if [ -n "\${XDG_CURRENT_DESKTOP}" ]; then - case "\${XDG_CURRENT_DESKTOP}" in - # only recently added to menu-spec, pre-spec X- still in use - Cinnamon|X-Cinnamon) - DE=cinnamon; - ;; - ENLIGHTENMENT) - DE=enlightenment; - ;; - # GNOME, GNOME-Classic:GNOME, or GNOME-Flashback:GNOME - GNOME*) - DE=gnome; - ;; - KDE) - DE=kde; - ;; - # Deepin Desktop Environments - DEEPIN|Deepin|deepin) - DE=dde; - ;; - LXDE) - DE=lxde; - ;; - LXQt) - DE=lxqt; - ;; - MATE) - DE=mate; - ;; - XFCE) - DE=xfce - ;; - X-Generic) - DE=generic - ;; - esac - fi - - if [ x"$DE" = x"" ]; then - # classic fallbacks - if [ x"$KDE_FULL_SESSION" != x"" ]; then DE=kde; - elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome; - elif [ x"$MATE_DESKTOP_SESSION_ID" != x"" ]; then DE=mate; - elif \`dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:org.gnome.SessionManager > /dev/null 2>&1\` ; then DE=gnome; - elif xprop -root _DT_SAVE_MODE 2> /dev/null | grep ' = \\"xfce4\\"$' >/dev/null 2>&1; then DE=xfce; - elif xprop -root 2> /dev/null | grep -i '^xfce_desktop_window' >/dev/null 2>&1; then DE=xfce - elif echo $DESKTOP | grep -q '^Enlightenment'; then DE=enlightenment; - elif [ x"$LXQT_SESSION_CONFIG" != x"" ]; then DE=lxqt; - fi - fi - - if [ x"$DE" = x"" ]; then - # fallback to checking $DESKTOP_SESSION - case "$DESKTOP_SESSION" in - gnome) - DE=gnome; - ;; - LXDE|Lubuntu) - DE=lxde; - ;; - MATE) - DE=mate; - ;; - xfce|xfce4|'Xfce Session') - DE=xfce; - ;; - esac - fi - - if [ x"$DE" = x"" ]; then - # fallback to uname output for other platforms - case "$(uname 2>/dev/null)" in - CYGWIN*) - DE=cygwin; - ;; - Darwin) - DE=darwin; - ;; - esac - fi - - if [ x"$DE" = x"gnome" ]; then - # gnome-default-applications-properties is only available in GNOME 2.x - # but not in GNOME 3.x - which gnome-default-applications-properties > /dev/null 2>&1 || DE="gnome3" - fi - - if [ -f "$XDG_RUNTIME_DIR/flatpak-info" ]; then - DE="flatpak" - fi -} - -#---------------------------------------------------------------------------- -# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4 -# It also always returns 1 in KDE 3.4 and earlier -# Simply return 0 in such case - -kfmclient_fix_exit_code() -{ - version=\`LC_ALL=C.UTF-8 kde-config --version 2>/dev/null | grep '^KDE'\` - major=\`echo $version | sed 's/KDE.*: \\([0-9]\\).*/\\1/'\` - minor=\`echo $version | sed 's/KDE.*: [0-9]*\\.\\([0-9]\\).*/\\1/'\` - release=\`echo $version | sed 's/KDE.*: [0-9]*\\.[0-9]*\\.\\([0-9]\\).*/\\1/'\` - test "$major" -gt 3 && return $1 - test "$minor" -gt 5 && return $1 - test "$release" -gt 4 && return $1 - return 0 -} - -#---------------------------------------------------------------------------- -# Returns true if there is a graphical display attached. - -has_display() -{ - if [ -n "$DISPLAY" ] || [ -n "$WAYLAND_DISPLAY" ]; then - return 0 - else - return 1 - fi -} - -# This handles backslashes but not quote marks. -last_word() -{ - read first rest - echo "$rest" -} - -# Get the value of a key in a desktop file's Desktop Entry group. -# Example: Use get_key foo.desktop Exec -# to get the values of the Exec= key for the Desktop Entry group. -get_key() -{ - local file="\${1}" - local key="\${2}" - local desktop_entry="" - - IFS_="\${IFS}" - IFS="" - while read line - do - case "$line" in - "[Desktop Entry]") - desktop_entry="y" - ;; - # Reset match flag for other groups - "["*) - desktop_entry="" - ;; - "\${key}="*) - # Only match Desktop Entry group - if [ -n "\${desktop_entry}" ] - then - echo "\${line}" | cut -d= -f 2- - fi - esac - done < "\${file}" - IFS="\${IFS_}" -} - -# Returns true if argument is a file:// URL or path -is_file_url_or_path() -{ - if echo "$1" | grep -q '^file://' \\ - || ! echo "$1" | egrep -q '^[[:alpha:]+\\.\\-]+:'; then - return 0 - else - return 1 - fi -} - -# If argument is a file URL, convert it to a (percent-decoded) path. -# If not, leave it as it is. -file_url_to_path() -{ - local file="$1" - if echo "$file" | grep -q '^file:///'; then - file=\${file#file://} - file=\${file%%#*} - file=$(echo "$file" | sed -r 's/\\?.*$//') - local printf=printf - if [ -x /usr/bin/printf ]; then - printf=/usr/bin/printf - fi - file=$($printf "$(echo "$file" | sed -e 's@%\\([a-f0-9A-F]\\{2\\}\\)@\\\\x\\1@g')") - fi - echo "$file" -} - -open_cygwin() -{ - cygstart "$1" - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_darwin() -{ - open "$1" - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_kde() -{ - if [ -n "\${KDE_SESSION_VERSION}" ]; then - case "\${KDE_SESSION_VERSION}" in - 4) - kde-open "$1" - ;; - 5) - kde-open\${KDE_SESSION_VERSION} "$1" - ;; - esac - else - kfmclient exec "$1" - kfmclient_fix_exit_code $? - fi - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_dde() -{ - if dde-open -version >/dev/null 2>&1; then - dde-open "$1" - else - open_generic "$1" - fi - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_gnome3() -{ - if gio help open 2>/dev/null 1>&2; then - gio open "$1" - elif gvfs-open --help 2>/dev/null 1>&2; then - gvfs-open "$1" - else - open_generic "$1" - fi - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_gnome() -{ - if gio help open 2>/dev/null 1>&2; then - gio open "$1" - elif gvfs-open --help 2>/dev/null 1>&2; then - gvfs-open "$1" - elif gnome-open --help 2>/dev/null 1>&2; then - gnome-open "$1" - else - open_generic "$1" - fi - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_mate() -{ - if gio help open 2>/dev/null 1>&2; then - gio open "$1" - elif gvfs-open --help 2>/dev/null 1>&2; then - gvfs-open "$1" - elif mate-open --help 2>/dev/null 1>&2; then - mate-open "$1" - else - open_generic "$1" - fi - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_xfce() -{ - if exo-open --help 2>/dev/null 1>&2; then - exo-open "$1" - elif gio help open 2>/dev/null 1>&2; then - gio open "$1" - elif gvfs-open --help 2>/dev/null 1>&2; then - gvfs-open "$1" - else - open_generic "$1" - fi - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_enlightenment() -{ - if enlightenment_open --help 2>/dev/null 1>&2; then - enlightenment_open "$1" - else - open_generic "$1" - fi - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_flatpak() -{ - gdbus call --session \\ - --dest org.freedesktop.portal.Desktop \\ - --object-path /org/freedesktop/portal/desktop \\ - --method org.freedesktop.portal.OpenURI.OpenURI \\ - "" "$1" {} - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -#----------------------------------------- -# Recursively search .desktop file - -search_desktop_file() -{ - local default="$1" - local dir="$2" - local target="$3" - - local file="" - # look for both vendor-app.desktop, vendor/app.desktop - if [ -r "$dir/$default" ]; then - file="$dir/$default" - elif [ -r "$dir/\`echo $default | sed -e 's|-|/|'\`" ]; then - file="$dir/\`echo $default | sed -e 's|-|/|'\`" - fi - - if [ -r "$file" ] ; then - command="$(get_key "\${file}" "Exec" | first_word)" - command_exec=\`which $command 2>/dev/null\` - icon="$(get_key "\${file}" "Icon")" - # FIXME: Actually LC_MESSAGES should be used as described in - # http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s04.html - localised_name="$(get_key "\${file}" "Name")" - set -- $(get_key "\${file}" "Exec" | last_word) - # We need to replace any occurrence of "%f", "%F" and - # the like by the target file. We examine each - # argument and append the modified argument to the - # end then shift. - local args=$# - local replaced=0 - while [ $args -gt 0 ]; do - case $1 in - %[c]) - replaced=1 - arg="\${localised_name}" - shift - set -- "$@" "$arg" - ;; - %[fFuU]) - replaced=1 - arg="$target" - shift - set -- "$@" "$arg" - ;; - %[i]) - replaced=1 - shift - set -- "$@" "--icon" "$icon" - ;; - *) - arg="$1" - shift - set -- "$@" "$arg" - ;; - esac - args=$(( $args - 1 )) - done - [ $replaced -eq 1 ] || set -- "$@" "$target" - "$command_exec" "$@" - - if [ $? -eq 0 ]; then - exit_success - fi - fi - - for d in $dir/*/; do - [ -d "$d" ] && search_desktop_file "$default" "$d" "$target" - done -} - - -open_generic_xdg_mime() -{ - filetype="$2" - default=\`xdg-mime query default "$filetype"\` - if [ -n "$default" ] ; then - xdg_user_dir="$XDG_DATA_HOME" - [ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share" - - xdg_system_dirs="$XDG_DATA_DIRS" - [ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/ - -DEBUG 3 "$xdg_user_dir:$xdg_system_dirs" - for x in \`echo "$xdg_user_dir:$xdg_system_dirs" | sed 's/:/ /g'\`; do - search_desktop_file "$default" "$x/applications/" "$1" - done - fi -} - -open_generic_xdg_file_mime() -{ - filetype=\`xdg-mime query filetype "$1" | sed "s/;.*//"\` - open_generic_xdg_mime "$1" "$filetype" -} - -open_generic_xdg_x_scheme_handler() -{ - scheme="\`echo $1 | sed -n 's/\\(^[[:alnum:]+\\.-]*\\):.*$/\\1/p'\`" - if [ -n $scheme ]; then - filetype="x-scheme-handler/$scheme" - open_generic_xdg_mime "$1" "$filetype" - fi -} - -has_single_argument() -{ - test $# = 1 -} - -open_envvar() -{ - local oldifs="$IFS" - local browser browser_with_arg - - IFS=":" - for browser in $BROWSER; do - IFS="$oldifs" - - if [ -z "$browser" ]; then - continue - fi - - if echo "$browser" | grep -q %s; then - # Avoid argument injection. - # See https://bugs.freedesktop.org/show_bug.cgi?id=103807 - # URIs don't have IFS characters spaces anyway. - has_single_argument $1 && $(printf "$browser" "$1") - else - $browser "$1" - fi - - if [ $? -eq 0 ]; then - exit_success - fi - done -} - -open_generic() -{ - if is_file_url_or_path "$1"; then - local file="$(file_url_to_path "$1")" - - check_input_file "$file" - - if has_display; then - filetype=\`xdg-mime query filetype "$file" | sed "s/;.*//"\` - open_generic_xdg_mime "$file" "$filetype" - fi - - if which run-mailcap 2>/dev/null 1>&2; then - run-mailcap --action=view "$file" - if [ $? -eq 0 ]; then - exit_success - fi - fi - - if has_display && mimeopen -v 2>/dev/null 1>&2; then - mimeopen -L -n "$file" - if [ $? -eq 0 ]; then - exit_success - fi - fi - fi - - if has_display; then - open_generic_xdg_x_scheme_handler "$1" - fi - - if [ -n "$BROWSER" ]; then - open_envvar "$1" - fi - - # if BROWSER variable is not set, check some well known browsers instead - if [ x"$BROWSER" = x"" ]; then - BROWSER=www-browser:links2:elinks:links:lynx:w3m - if has_display; then - BROWSER=x-www-browser:firefox:iceweasel:seamonkey:mozilla:epiphany:konqueror:chromium:chromium-browser:google-chrome:microsoft-edge:$BROWSER - fi - fi - - open_envvar "$1" - - exit_failure_operation_impossible "no method available for opening '$1'" -} - -open_lxde() -{ - - # pcmanfm only knows how to handle file:// urls and filepaths, it seems. - if pcmanfm --help >/dev/null 2>&1 && is_file_url_or_path "$1"; then - local file="$(file_url_to_path "$1")" - - # handle relative paths - if ! echo "$file" | grep -q ^/; then - file="$(pwd)/$file" - fi - - pcmanfm "$file" - else - open_generic "$1" - fi - - if [ $? -eq 0 ]; then - exit_success - else - exit_failure_operation_failed - fi -} - -open_lxqt() -{ - open_generic "$1" -} - -[ x"$1" != x"" ] || exit_failure_syntax - -url= -while [ $# -gt 0 ] ; do - parm="$1" - shift - - case "$parm" in - -*) - exit_failure_syntax "unexpected option '$parm'" - ;; - - *) - if [ -n "$url" ] ; then - exit_failure_syntax "unexpected argument '$parm'" - fi - url="$parm" - ;; - esac -done - -if [ -z "\${url}" ] ; then - exit_failure_syntax "file or URL argument missing" -fi - -detectDE - -if [ x"$DE" = x"" ]; then - DE=generic -fi - -DEBUG 2 "Selected DE $DE" - -# sanitize BROWSER (avoid caling ourselves in particular) -case "\${BROWSER}" in - *:"xdg-open"|"xdg-open":*) - BROWSER=$(echo $BROWSER | sed -e 's|:xdg-open||g' -e 's|xdg-open:||g') - ;; - "xdg-open") - BROWSER= - ;; -esac - -case "$DE" in - kde) - open_kde "$url" - ;; - - dde) - open_dde "$url" - ;; - - gnome3|cinnamon) - open_gnome3 "$url" - ;; - - gnome) - open_gnome "$url" - ;; - - mate) - open_mate "$url" - ;; - - xfce) - open_xfce "$url" - ;; - - lxde) - open_lxde "$url" - ;; - - lxqt) - open_lxqt "$url" - ;; - - enlightenment) - open_enlightenment "$url" - ;; - - cygwin) - open_cygwin "$url" - ;; - - darwin) - open_darwin "$url" - ;; - - flatpak) - open_flatpak "$url" - ;; - - generic) - open_generic "$url" - ;; - - *) - exit_failure_operation_impossible "no method available for opening '$url'" - ;; -esac -`; - -export { xdgOpenScript }; diff --git a/.pnpm-store/v3/files/0a/ca721d45dc99d70273ed48280c3067e7295b8d361efb0eea9eb2aeb3bfa1895c9a13fc9db3c94238239140139602056cc03daec51a0afd36f3f6f18e1ae530 b/.pnpm-store/v3/files/0a/ca721d45dc99d70273ed48280c3067e7295b8d361efb0eea9eb2aeb3bfa1895c9a13fc9db3c94238239140139602056cc03daec51a0afd36f3f6f18e1ae530 deleted file mode 100644 index 7ac92ff0b66bda08bba0d7f621961f789ed44cff..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/0a/ca721d45dc99d70273ed48280c3067e7295b8d361efb0eea9eb2aeb3bfa1895c9a13fc9db3c94238239140139602056cc03daec51a0afd36f3f6f18e1ae530 +++ /dev/null @@ -1,17 +0,0 @@ -import { g as gray, a as green, b as bold } from './nuxi.d3241ca4.mjs'; -import { t as tryRequireModule } from './nuxi.5aaa4630.mjs'; - -function showVersions(cwd) { - const getPkgVersion = (pkg) => { - return tryRequireModule(`${pkg}/package.json`, cwd)?.version || ""; - }; - const nuxtVersion = getPkgVersion("nuxt") || getPkgVersion("nuxt-nightly") || getPkgVersion("nuxt3") || getPkgVersion("nuxt-edge"); - const nitroVersion = getPkgVersion("nitropack") || getPkgVersion("nitropack-edge"); - console.log( - gray( - green(`Nuxt ${bold(nuxtVersion)}`) + (nitroVersion ? ` with Nitro ${bold(nitroVersion)}` : "") - ) - ); -} - -export { showVersions as s }; diff --git a/.pnpm-store/v3/files/0c/829cd953ccfeaae048e9b01fc50bf349e1d456717f69a5fcbfae32821c3fd75264237724164accccea566a404cc97922ad413605356776dff7f4a9d1c21331 b/.pnpm-store/v3/files/0c/829cd953ccfeaae048e9b01fc50bf349e1d456717f69a5fcbfae32821c3fd75264237724164accccea566a404cc97922ad413605356776dff7f4a9d1c21331 deleted file mode 100644 index 39257c296e67f2e252c114830471d3f8d0d0978a..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/0c/829cd953ccfeaae048e9b01fc50bf349e1d456717f69a5fcbfae32821c3fd75264237724164accccea566a404cc97922ad413605356776dff7f4a9d1c21331 +++ /dev/null @@ -1,56 +0,0 @@ -const NUMBER_CHAR_RE = /\d/; -const STR_SPLITTERS = ["-", "_", "/", "."]; -function isUppercase(char = "") { - if (NUMBER_CHAR_RE.test(char)) { - return void 0; - } - return char !== char.toLowerCase(); -} -function splitByCase(str, separators) { - const splitters = separators ?? STR_SPLITTERS; - const parts = []; - if (!str || typeof str !== "string") { - return parts; - } - let buff = ""; - let previousUpper; - let previousSplitter; - for (const char of str) { - const isSplitter = splitters.includes(char); - if (isSplitter === true) { - parts.push(buff); - buff = ""; - previousUpper = void 0; - continue; - } - const isUpper = isUppercase(char); - if (previousSplitter === false) { - if (previousUpper === false && isUpper === true) { - parts.push(buff); - buff = char; - previousUpper = isUpper; - continue; - } - if (previousUpper === true && isUpper === false && buff.length > 1) { - const lastChar = buff.at(-1); - parts.push(buff.slice(0, Math.max(0, buff.length - 1))); - buff = lastChar + char; - previousUpper = isUpper; - continue; - } - } - buff += char; - previousUpper = isUpper; - previousSplitter = isSplitter; - } - parts.push(buff); - return parts; -} -function upperFirst(str) { - return str ? str[0].toUpperCase() + str.slice(1) : ""; -} -function kebabCase(str, joiner) { - return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p) => p.toLowerCase()).join(joiner ?? "-") : ""; -} - -export { kebabCase as k, splitByCase as s, upperFirst as u }; diff --git a/.pnpm-store/v3/files/10/037726b70360ca0f3e02588fd9117c8d16debbfbf48e764a8ff3dfa0b5d2401ae0e8e52fb23082e71477a7ba5b3fa4f440c565293d3d312b00526c2464d025 b/.pnpm-store/v3/files/10/037726b70360ca0f3e02588fd9117c8d16debbfbf48e764a8ff3dfa0b5d2401ae0e8e52fb23082e71477a7ba5b3fa4f440c565293d3d312b00526c2464d025 deleted file mode 100644 index eeea0b9c947337f8afa3eba2bb23e3e754d7beef..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/10/037726b70360ca0f3e02588fd9117c8d16debbfbf48e764a8ff3dfa0b5d2401ae0e8e52fb23082e71477a7ba5b3fa4f440c565293d3d312b00526c2464d025 +++ /dev/null @@ -1,32 +0,0 @@ -var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - -function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; -} - -function getAugmentedNamespace(n) { - if (n.__esModule) return n; - var f = n.default; - if (typeof f == "function") { - var a = function a () { - if (this instanceof a) { - return Reflect.construct(f, arguments, this.constructor); - } - return f.apply(this, arguments); - }; - a.prototype = f.prototype; - } else a = {}; - Object.defineProperty(a, '__esModule', {value: true}); - Object.keys(n).forEach(function (k) { - var d = Object.getOwnPropertyDescriptor(n, k); - Object.defineProperty(a, k, d.get ? d : { - enumerable: true, - get: function () { - return n[k]; - } - }); - }); - return a; -} - -export { getAugmentedNamespace as a, commonjsGlobal as c, getDefaultExportFromCjs as g }; diff --git a/.pnpm-store/v3/files/10/1216de93f1d1365bdb6cacf82a8b5048446a7b800025a57386c3453d9d98a9dc4eb435c5b61bb4866ce453ad20acc5f8541c480468a3f932d5b599e0795ff9 b/.pnpm-store/v3/files/10/1216de93f1d1365bdb6cacf82a8b5048446a7b800025a57386c3453d9d98a9dc4eb435c5b61bb4866ce453ad20acc5f8541c480468a3f932d5b599e0795ff9 deleted file mode 100644 index bf8bee245e263f1ebb57ac2bbff755f65e191e2c..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/10/1216de93f1d1365bdb6cacf82a8b5048446a7b800025a57386c3453d9d98a9dc4eb435c5b61bb4866ce453ad20acc5f8541c480468a3f932d5b599e0795ff9 +++ /dev/null @@ -1,71 +0,0 @@ -const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/; -const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/; -const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/; -function jsonParseTransform(key, value) { - if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) { - warnKeyDropped(key); - return; - } - return value; -} -function warnKeyDropped(key) { - console.warn(`[destr] Dropping "${key}" key to prevent prototype pollution.`); -} -function destr(value, options = {}) { - if (typeof value !== "string") { - return value; - } - const _value = value.trim(); - if ( - // eslint-disable-next-line unicorn/prefer-at - value[0] === '"' && value.endsWith('"') && !value.includes("\\") - ) { - return _value.slice(1, -1); - } - if (_value.length <= 9) { - const _lval = _value.toLowerCase(); - if (_lval === "true") { - return true; - } - if (_lval === "false") { - return false; - } - if (_lval === "undefined") { - return void 0; - } - if (_lval === "null") { - return null; - } - if (_lval === "nan") { - return Number.NaN; - } - if (_lval === "infinity") { - return Number.POSITIVE_INFINITY; - } - if (_lval === "-infinity") { - return Number.NEGATIVE_INFINITY; - } - } - if (!JsonSigRx.test(value)) { - if (options.strict) { - throw new SyntaxError("[destr] Invalid JSON"); - } - return value; - } - try { - if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) { - if (options.strict) { - throw new Error("[destr] Possible prototype pollution"); - } - return JSON.parse(value, jsonParseTransform); - } - return JSON.parse(value); - } catch (error) { - if (options.strict) { - throw error; - } - return value; - } -} - -export { destr as d }; diff --git a/.pnpm-store/v3/files/16/48a131424c61358fa6cf7edf4be8950eab8846195013f320a25afccec31e4f37069ad39cef79c8be955a68d2ca8d271e8a01d4a7e58c43e5a120b80940c4e3 b/.pnpm-store/v3/files/16/48a131424c61358fa6cf7edf4be8950eab8846195013f320a25afccec31e4f37069ad39cef79c8be955a68d2ca8d271e8a01d4a7e58c43e5a120b80940c4e3 deleted file mode 100644 index 14dd1e8f99f705cfe03b4f3dcda2f583b7b6d3d5..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/16/48a131424c61358fa6cf7edf4be8950eab8846195013f320a25afccec31e4f37069ad39cef79c8be955a68d2ca8d271e8a01d4a7e58c43e5a120b80940c4e3 +++ /dev/null @@ -1,556 +0,0 @@ -import Et from 'node:http'; -import https from 'node:https'; -import { EventEmitter } from 'node:events'; - -const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i; -const isSSL = /^https|wss/; -function setupOutgoing(outgoing, options, req, forward) { - outgoing.port = options[forward || "target"].port || (isSSL.test(options[forward || "target"].protocol) ? 443 : 80); - for (const e of [ - "host", - "hostname", - "socketPath", - "pfx", - "key", - "passphrase", - "cert", - "ca", - "ciphers", - "secureProtocol" - ]) { - outgoing[e] = options[forward || "target"][e]; - } - outgoing.method = options.method || req.method; - outgoing.headers = { ...req.headers }; - if (options.headers) { - outgoing.headers = { ...outgoing.headers, ...options.headers }; - } - if (options.auth) { - outgoing.auth = options.auth; - } - if (options.ca) { - outgoing.ca = options.ca; - } - if (isSSL.test(options[forward || "target"].protocol)) { - outgoing.rejectUnauthorized = options.secure === void 0 ? true : options.secure; - } - outgoing.agent = options.agent || false; - outgoing.localAddress = options.localAddress; - if (!outgoing.agent) { - outgoing.headers = outgoing.headers || {}; - if (typeof outgoing.headers.connection !== "string" || !upgradeHeader.test(outgoing.headers.connection)) { - outgoing.headers.connection = "close"; - } - } - const target = options[forward || "target"]; - const targetPath = target && options.prependPath !== false ? target.pathname || target.path || "" : ""; - const parsed = new URL(req.url, "http://localhost"); - let outgoingPath = options.toProxy ? req.url : parsed.pathname + parsed.search || ""; - outgoingPath = options.ignorePath ? "" : outgoingPath; - outgoing.path = urlJoin(targetPath, outgoingPath); - if (options.changeOrigin) { - outgoing.headers.host = /* required(outgoing.port, options[forward || "target"].protocol) && TODO: From requires-port */ - hasPort(outgoing.host) ? outgoing.host : outgoing.host + ":" + outgoing.port; - } - return outgoing; -} -function setupSocket(socket) { - socket.setTimeout(0); - socket.setNoDelay(true); - socket.setKeepAlive(true, 0); - return socket; -} -function getPort(req) { - const res = req.headers.host ? req.headers.host.match(/:(\d+)/) : ""; - if (res) { - return res[1]; - } - return hasEncryptedConnection(req) ? "443" : "80"; -} -function hasEncryptedConnection(req) { - return Boolean(req.connection.encrypted || req.connection.pair); -} -function urlJoin(...args) { - const lastIndex = args.length - 1; - const last = args[lastIndex]; - const lastSegs = last.split("?"); - args[lastIndex] = lastSegs.shift(); - const retSegs = [ - args.filter(Boolean).join("/").replace(/\/+/g, "/").replace("http:/", "http://").replace("https:/", "https://") - ]; - retSegs.push(...lastSegs); - return retSegs.join("?"); -} -function rewriteCookieProperty(header, config, property) { - if (Array.isArray(header)) { - return header.map(function(headerElement) { - return rewriteCookieProperty(headerElement, config, property); - }); - } - return header.replace( - new RegExp("(;\\s*" + property + "=)([^;]+)", "i"), - function(match, prefix, previousValue) { - let newValue; - if (previousValue in config) { - newValue = config[previousValue]; - } else if ("*" in config) { - newValue = config["*"]; - } else { - return match; - } - return newValue ? prefix + newValue : ""; - } - ); -} -function hasPort(host) { - return !!~host.indexOf(":"); -} - -function defineProxyMiddleware(m) { - return m; -} -function defineProxyOutgoingMiddleware(m) { - return m; -} - -const redirectRegex = /^201|30([1278])$/; -const removeChunked = defineProxyOutgoingMiddleware((req, res, proxyRes) => { - if (req.httpVersion === "1.0") { - delete proxyRes.headers["transfer-encoding"]; - } -}); -const setConnection = defineProxyOutgoingMiddleware((req, res, proxyRes) => { - if (req.httpVersion === "1.0") { - proxyRes.headers.connection = req.headers.connection || "close"; - } else if (req.httpVersion !== "2.0" && !proxyRes.headers.connection) { - proxyRes.headers.connection = req.headers.connection || "keep-alive"; - } -}); -const setRedirectHostRewrite = defineProxyOutgoingMiddleware( - (req, res, proxyRes, options) => { - if ((options.hostRewrite || options.autoRewrite || options.protocolRewrite) && proxyRes.headers.location && redirectRegex.test(String(proxyRes.statusCode))) { - const target = new URL(options.target); - const u = new URL(proxyRes.headers.location); - if (target.host !== u.host) { - return; - } - if (options.hostRewrite) { - u.host = options.hostRewrite; - } else if (options.autoRewrite) { - u.host = req.headers.host; - } - if (options.protocolRewrite) { - u.protocol = options.protocolRewrite; - } - proxyRes.headers.location = u.toString(); - } - } -); -const writeHeaders = defineProxyOutgoingMiddleware( - (req, res, proxyRes, options) => { - let rewriteCookieDomainConfig = options.cookieDomainRewrite; - let rewriteCookiePathConfig = options.cookiePathRewrite; - const preserveHeaderKeyCase = options.preserveHeaderKeyCase; - let rawHeaderKeyMap; - const setHeader = function(key, header) { - if (header === void 0) { - return; - } - if (rewriteCookieDomainConfig && key.toLowerCase() === "set-cookie") { - header = rewriteCookieProperty( - header, - rewriteCookieDomainConfig, - "domain" - ); - } - if (rewriteCookiePathConfig && key.toLowerCase() === "set-cookie") { - header = rewriteCookieProperty(header, rewriteCookiePathConfig, "path"); - } - res.setHeader(String(key).trim(), header); - }; - if (typeof rewriteCookieDomainConfig === "string") { - rewriteCookieDomainConfig = { "*": rewriteCookieDomainConfig }; - } - if (typeof rewriteCookiePathConfig === "string") { - rewriteCookiePathConfig = { "*": rewriteCookiePathConfig }; - } - if (preserveHeaderKeyCase && proxyRes.rawHeaders !== void 0) { - rawHeaderKeyMap = {}; - for (let i = 0; i < proxyRes.rawHeaders.length; i += 2) { - const key = proxyRes.rawHeaders[i]; - rawHeaderKeyMap[key.toLowerCase()] = key; - } - } - for (let key of Object.keys(proxyRes.headers)) { - const header = proxyRes.headers[key]; - if (preserveHeaderKeyCase && rawHeaderKeyMap) { - key = rawHeaderKeyMap[key] || key; - } - setHeader(key, header); - } - } -); -const writeStatusCode = defineProxyOutgoingMiddleware((req, res, proxyRes) => { - if (proxyRes.statusMessage) { - res.statusCode = proxyRes.statusCode; - res.statusMessage = proxyRes.statusMessage; - } else { - res.statusCode = proxyRes.statusCode; - } -}); -const webOutgoingMiddleware = [ - removeChunked, - setConnection, - setRedirectHostRewrite, - writeHeaders, - writeStatusCode -]; - -const nativeAgents = { http: Et, https: https }; -const deleteLength = defineProxyMiddleware((req) => { - if ((req.method === "DELETE" || req.method === "OPTIONS") && !req.headers["content-length"]) { - req.headers["content-length"] = "0"; - delete req.headers["transfer-encoding"]; - } -}); -const timeout = defineProxyMiddleware((req, res, options) => { - if (options.timeout) { - req.socket.setTimeout(options.timeout); - } -}); -const XHeaders$1 = defineProxyMiddleware((req, res, options) => { - if (!options.xfwd) { - return; - } - const encrypted = req.isSpdy || hasEncryptedConnection(req); - const values = { - for: req.connection.remoteAddress || req.socket.remoteAddress, - port: getPort(req), - proto: encrypted ? "https" : "http" - }; - for (const header of ["for", "port", "proto"]) { - req.headers["x-forwarded-" + header] = (req.headers["x-forwarded-" + header] || "") + (req.headers["x-forwarded-" + header] ? "," : "") + values[header]; - } - req.headers["x-forwarded-host"] = req.headers["x-forwarded-host"] || req.headers.host || ""; -}); -const stream$1 = defineProxyMiddleware( - (req, res, options, server, head, callback) => { - server.emit("start", req, res, options.target || options.forward); - const agents = nativeAgents; - const http = agents.http; - const https = agents.https; - if (options.forward) { - const forwardReq = (options.forward.protocol === "https:" ? https : http).request(setupOutgoing(options.ssl || {}, options, req, "forward")); - const forwardError = createErrorHandler(forwardReq, options.forward); - req.on("error", forwardError); - forwardReq.on("error", forwardError); - (options.buffer || req).pipe(forwardReq); - if (!options.target) { - res.end(); - return; - } - } - const proxyReq = (options.target.protocol === "https:" ? https : http).request(setupOutgoing(options.ssl || {}, options, req)); - proxyReq.on("socket", (socket) => { - if (server && !proxyReq.getHeader("expect")) { - server.emit("proxyReq", proxyReq, req, res, options); - } - }); - if (options.proxyTimeout) { - proxyReq.setTimeout(options.proxyTimeout, function() { - proxyReq.abort(); - }); - } - req.on("aborted", function() { - proxyReq.abort(); - }); - const proxyError = createErrorHandler(proxyReq, options.target); - req.on("error", proxyError); - proxyReq.on("error", proxyError); - function createErrorHandler(proxyReq2, url) { - return function proxyError2(err) { - if (req.socket.destroyed && err.code === "ECONNRESET") { - server.emit("econnreset", err, req, res, url); - return proxyReq2.abort(); - } - if (callback) { - callback(err, req, res, url); - } else { - server.emit("error", err, req, res, url); - } - }; - } - (options.buffer || req).pipe(proxyReq); - proxyReq.on("response", function(proxyRes) { - if (server) { - server.emit("proxyRes", proxyRes, req, res); - } - if (!res.headersSent && !options.selfHandleResponse) { - for (const pass of webOutgoingMiddleware) { - if (pass(req, res, proxyRes, options)) { - break; - } - } - } - if (res.finished) { - if (server) { - server.emit("end", req, res, proxyRes); - } - } else { - res.on("close", function() { - proxyRes.destroy(); - }); - proxyRes.on("end", function() { - if (server) { - server.emit("end", req, res, proxyRes); - } - }); - if (!options.selfHandleResponse) { - proxyRes.pipe(res); - } - } - }); - } -); -const webIncomingMiddleware = [ - deleteLength, - timeout, - XHeaders$1, - stream$1 -]; - -const checkMethodAndHeader = defineProxyMiddleware((req, socket) => { - if (req.method !== "GET" || !req.headers.upgrade) { - socket.destroy(); - return true; - } - if (req.headers.upgrade.toLowerCase() !== "websocket") { - socket.destroy(); - return true; - } -}); -const XHeaders = defineProxyMiddleware((req, socket, options) => { - if (!options.xfwd) { - return; - } - const values = { - for: req.connection.remoteAddress || req.socket.remoteAddress, - port: getPort(req), - proto: hasEncryptedConnection(req) ? "wss" : "ws" - }; - for (const header of ["for", "port", "proto"]) { - req.headers["x-forwarded-" + header] = (req.headers["x-forwarded-" + header] || "") + (req.headers["x-forwarded-" + header] ? "," : "") + values[header]; - } -}); -const stream = defineProxyMiddleware( - (req, socket, options, server, head, callback) => { - const createHttpHeader = function(line, headers) { - return Object.keys(headers).reduce( - function(head2, key) { - const value = headers[key]; - if (!Array.isArray(value)) { - head2.push(key + ": " + value); - return head2; - } - for (const element of value) { - head2.push(key + ": " + element); - } - return head2; - }, - [line] - ).join("\r\n") + "\r\n\r\n"; - }; - setupSocket(socket); - if (head && head.length > 0) { - socket.unshift(head); - } - const proxyReq = (isSSL.test(options.target.protocol) ? https : Et).request(setupOutgoing(options.ssl || {}, options, req)); - if (server) { - server.emit("proxyReqWs", proxyReq, req, socket, options, head); - } - proxyReq.on("error", onOutgoingError); - proxyReq.on("response", function(res) { - if (!res.upgrade) { - socket.write( - createHttpHeader( - "HTTP/" + res.httpVersion + " " + res.statusCode + " " + res.statusMessage, - res.headers - ) - ); - res.pipe(socket); - } - }); - proxyReq.on("upgrade", function(proxyRes, proxySocket, proxyHead) { - proxySocket.on("error", onOutgoingError); - proxySocket.on("end", function() { - server.emit("close", proxyRes, proxySocket, proxyHead); - }); - socket.on("error", function() { - proxySocket.end(); - }); - setupSocket(proxySocket); - if (proxyHead && proxyHead.length > 0) { - proxySocket.unshift(proxyHead); - } - socket.write( - createHttpHeader("HTTP/1.1 101 Switching Protocols", proxyRes.headers) - ); - proxySocket.pipe(socket).pipe(proxySocket); - server.emit("open", proxySocket); - server.emit("proxySocket", proxySocket); - }); - proxyReq.end(); - function onOutgoingError(err) { - if (callback) { - callback(err, req, socket); - } else { - server.emit("error", err, req, socket); - } - socket.end(); - } - } -); -const websocketIncomingMiddleware = [ - checkMethodAndHeader, - XHeaders, - stream -]; - -var __defProp = Object.defineProperty; -var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; -var __publicField = (obj, key, value) => { - __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); - return value; -}; -class ProxyServer extends EventEmitter { - /** - * Creates the proxy server with specified options. - * @param options - Config object passed to the proxy - */ - constructor(options = {}) { - super(); - __publicField(this, "_server"); - __publicField(this, "_webPasses", [...webIncomingMiddleware]); - __publicField(this, "_wsPasses", [...websocketIncomingMiddleware]); - __publicField(this, "options"); - __publicField(this, "web"); - __publicField(this, "ws"); - this.options = options || {}; - this.options.prependPath = options.prependPath !== false; - this.web = _createProxyFn("web", this); - this.ws = _createProxyFn("ws", this); - } - /** - * A function that wraps the object in a webserver, for your convenience - * @param port - Port to listen on - * @param hostname - The hostname to listen on - */ - listen(port, hostname) { - const closure = (req, res) => { - this.web(req, res); - }; - this._server = this.options.ssl ? https.createServer(this.options.ssl, closure) : Et.createServer(closure); - if (this.options.ws) { - this._server.on("upgrade", (req, socket, head) => { - this._ws(req, socket, head); - }); - } - this._server.listen(port, hostname); - return this; - } - /** - * A function that closes the inner webserver and stops listening on given port - */ - close(callback) { - if (this._server) { - this._server.close((...args) => { - this._server = void 0; - if (callback) { - Reflect.apply(callback, void 0, args); - } - }); - } - } - before(type, passName, pass) { - if (type !== "ws" && type !== "web") { - throw new Error("type must be `web` or `ws`"); - } - const passes = type === "ws" ? this._wsPasses : this._webPasses; - let i = false; - for (const [idx, v] of passes.entries()) { - if (v.name === passName) { - i = idx; - } - } - if (i === false) { - throw new Error("No such pass"); - } - passes.splice(i, 0, pass); - } - after(type, passName, pass) { - if (type !== "ws" && type !== "web") { - throw new Error("type must be `web` or `ws`"); - } - const passes = type === "ws" ? this._wsPasses : this._webPasses; - let i = false; - for (const [idx, v] of passes.entries()) { - if (v.name === passName) { - i = idx; - } - } - if (i === false) { - throw new Error("No such pass"); - } - passes.splice(i++, 0, pass); - } -} -function createProxyServer(options = {}) { - return new ProxyServer(options); -} -function _createProxyFn(type, server) { - return function(req, res, opts, head) { - const requestOptions = { ...opts, ...server.options }; - for (const key of ["target", "forward"]) { - if (typeof requestOptions[key] === "string") { - requestOptions[key] = new URL(requestOptions[key]); - } - } - if (!requestOptions.target && !requestOptions.forward) { - return this.emit( - "error", - new Error("Must provide a proper URL as target") - ); - } - let _resolve; - let _reject; - const callbackPromise = new Promise((resolve, reject) => { - _resolve = resolve; - _reject = reject; - }); - res.on("close", () => { - _resolve(); - }); - res.on("error", (error) => { - _reject(error); - }); - for (const pass of type === "ws" ? server._wsPasses : server._webPasses) { - const stop = pass( - req, - res, - requestOptions, - server, - head, - (error) => { - _reject(error); - } - ); - if (stop) { - _resolve(); - break; - } - } - return callbackPromise; - }; -} - -export { ProxyServer, createProxyServer }; diff --git a/.pnpm-store/v3/files/18/c3a0e11e4993decd5bef9ea197c1ce7c28374197addfe20525846cb314fbbaf7919f0f9b90b5d037e94fa61d8037ac0098e0411a0b52f4b3fb0582193c8977 b/.pnpm-store/v3/files/18/c3a0e11e4993decd5bef9ea197c1ce7c28374197addfe20525846cb314fbbaf7919f0f9b90b5d037e94fa61d8037ac0098e0411a0b52f4b3fb0582193c8977 deleted file mode 100644 index 964cd44d15e89809edd12f4f94640994cc4b561c..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/18/c3a0e11e4993decd5bef9ea197c1ce7c28374197addfe20525846cb314fbbaf7919f0f9b90b5d037e94fa61d8037ac0098e0411a0b52f4b3fb0582193c8977 +++ /dev/null @@ -1,24 +0,0 @@ -import 'node:fs'; -import 'node:path'; -import { b as br, B as Bn } from '../shared/nuxi.34ba5283.mjs'; -import 'node:http'; -import 'node:https'; -import 'node:zlib'; -import 'node:stream'; -import 'node:buffer'; -import 'node:util'; -import 'node:url'; -import 'node:net'; -import '../shared/nuxi.4ac76f59.mjs'; -import '../shared/nuxi.53f5921c.mjs'; -import './satisfies.mjs'; -import '../shared/nuxi.2155838d.mjs'; -import '../shared/nuxi.cc8dd4a9.mjs'; -import '../shared/nuxi.5aaa4630.mjs'; -import 'node:module'; -import '../shared/nuxi.610c92ff.mjs'; - -var B=Object.defineProperty;var E=(u,a)=>B(u,"name",{value:a,configurable:!0});let D=0;const t={START_BOUNDARY:D++,HEADER_FIELD_START:D++,HEADER_FIELD:D++,HEADER_VALUE_START:D++,HEADER_VALUE:D++,HEADER_VALUE_ALMOST_DONE:D++,HEADERS_ALMOST_DONE:D++,PART_DATA_START:D++,PART_DATA:D++,END:D++};let w=1;const R={PART_BOUNDARY:w,LAST_BOUNDARY:w*=2},g=10,N=13,x=32,P=45,C=58,I=97,M=122,$=E(u=>u|32,"lower"),m=E(()=>{},"noop"),F=class F{constructor(a){this.index=0,this.flags=0,this.onHeaderEnd=m,this.onHeaderField=m,this.onHeadersEnd=m,this.onHeaderValue=m,this.onPartBegin=m,this.onPartData=m,this.onPartEnd=m,this.boundaryChars={},a=`\r ---`+a;const n=new Uint8Array(a.length);for(let r=0;r{this[h+"Mark"]=n;},"mark"),s=E(h=>{delete this[h+"Mark"];},"clear"),T=E((h,S,_,U)=>{(S===void 0||S!==_)&&this[h](U&&U.subarray(S,_));},"callback"),b=E((h,S)=>{const _=h+"Mark";_ in this&&(S?(T(h,this[_],n,a),delete this[_]):(T(h,this[_],a.length,a),this[_]=0));},"dataCallback");for(n=0;nM)return;break;case t.HEADER_VALUE_START:if(o===x)break;f("onHeaderValue"),i=t.HEADER_VALUE;case t.HEADER_VALUE:o===N&&(b("onHeaderValue",!0),T("onHeaderEnd"),i=t.HEADER_VALUE_ALMOST_DONE);break;case t.HEADER_VALUE_ALMOST_DONE:if(o!==g)return;i=t.HEADER_FIELD_START;break;case t.HEADERS_ALMOST_DONE:if(o!==g)return;T("onHeadersEnd"),i=t.PART_DATA_START;break;case t.PART_DATA_START:i=t.PART_DATA,f("onPartData");case t.PART_DATA:if(d=e,e===0){for(n+=O;n0)l[e-1]=o;else if(d>0){const h=new Uint8Array(l.buffer,l.byteOffset,l.byteLength);T("onPartData",0,d,h),d=0,f("onPartData"),n--;}break;case t.END:break;default:throw new Error(`Unexpected state entered: ${i}`)}b("onHeaderField"),b("onHeaderValue"),b("onPartData"),this.index=e,this.state=i,this.flags=A;}end(){if(this.state===t.HEADER_FIELD_START&&this.index===0||this.state===t.PART_DATA&&this.index===this.boundary.length)this.onPartEnd();else if(this.state!==t.END)throw new Error("MultipartParser.end(): stream ended unexpectedly")}};E(F,"MultipartParser");let k=F;function v(u){const a=u.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);if(!a)return;const n=a[2]||a[3]||"";let r=n.slice(n.lastIndexOf("\\")+1);return r=r.replace(/%22/g,'"'),r=r.replace(/&#(\d{4});/g,(d,l)=>String.fromCharCode(l)),r}E(v,"_fileName");async function Z(u,a){if(!/multipart/i.test(a))throw new TypeError("Failed to fetch");const n=a.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!n)throw new TypeError("no or bad content-type header, no multipart boundary");const r=new k(n[1]||n[2]);let d,l,c,p,e,i;const A=[],H=new br,O=E(s=>{c+=f.decode(s,{stream:!0});},"onPartData"),y=E(s=>{A.push(s);},"appendToFile"),o=E(()=>{const s=new Bn(A,i,{type:e});H.append(p,s);},"appendFileToFormData"),L=E(()=>{H.append(p,c);},"appendEntryToFormData"),f=new TextDecoder("utf-8");f.decode(),r.onPartBegin=function(){r.onPartData=O,r.onPartEnd=L,d="",l="",c="",p="",e="",i=null,A.length=0;},r.onHeaderField=function(s){d+=f.decode(s,{stream:!0});},r.onHeaderValue=function(s){l+=f.decode(s,{stream:!0});},r.onHeaderEnd=function(){if(l+=f.decode(),d=d.toLowerCase(),d==="content-disposition"){const s=l.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);s&&(p=s[2]||s[3]||""),i=v(l),i&&(r.onPartData=y,r.onPartEnd=o);}else d==="content-type"&&(e=l);l="",d="";};for await(const s of u)r.write(s);return r.end(),H}E(Z,"toFormData"); - -export { Z as toFormData }; diff --git a/.pnpm-store/v3/files/19/c58c3a5a439dbf0da4d4472d74ffa5ac2279a5f5fbf4b607508b952d426f21f6e5aa4b02d0439e8084eb254c84485df026189981376d6ddd13b8077c5063b7 b/.pnpm-store/v3/files/19/c58c3a5a439dbf0da4d4472d74ffa5ac2279a5f5fbf4b607508b952d426f21f6e5aa4b02d0439e8084eb254c84485df026189981376d6ddd13b8077c5063b7 deleted file mode 100644 index e6cc5b0562c7e54ca14a98c8baed54dc884a77c4..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/19/c58c3a5a439dbf0da4d4472d74ffa5ac2279a5f5fbf4b607508b952d426f21f6e5aa4b02d0439e8084eb254c84485df026189981376d6ddd13b8077c5063b7 +++ /dev/null @@ -1,92 +0,0 @@ -{ - "name": "nuxi", - "version": "3.11.1", - "description": "⚡️ Nuxt Generation CLI Experience", - "repository": "nuxt/cli", - "license": "MIT", - "type": "module", - "exports": { - ".": "./dist/index.mjs", - "./cli": "./bin/nuxi.mjs" - }, - "types": "./dist/index.d.ts", - "bin": { - "nuxi": "./bin/nuxi.mjs", - "nuxi-ng": "./bin/nuxi.mjs", - "nuxt": "./bin/nuxi.mjs", - "nuxt-cli": "./bin/nuxi.mjs" - }, - "files": [ - "bin", - "dist" - ], - "scripts": { - "dev:prepare": "unbuild --stub", - "build": "unbuild", - "build:stub": "unbuild --stub", - "dev": "node ./bin/nuxi.mjs dev ./playground", - "dev:bun": "bun --bun ./bin/nuxi.mjs dev ./playground", - "lint": "eslint . && prettier --check src", - "lint:fix": "eslint --fix . && prettier --write src", - "nuxi": "node ./bin/nuxi.mjs", - "nuxi-bun": "bun --bun ./bin/nuxi.mjs", - "prepack": "unbuild", - "release": "pnpm test && changelogen --release && npm publish && git push --follow-tags", - "test": "pnpm lint && pnpm test:types && pnpm build && pnpm test:dist", - "test:dist": "node ./bin/nuxi.mjs info ./playground", - "test:types": "tsc --noEmit" - }, - "devDependencies": { - "@nuxt/eslint-config": "^0.2.0", - "@nuxt/kit": "^3.11.1", - "@nuxt/schema": "^3.11.1", - "@nuxt/test-utils": "^3.12.0", - "@types/http-proxy": "^1.17.14", - "@types/node": "^20.11.30", - "@types/semver": "^7.5.8", - "@types/ws": "^8.5.10", - "c12": "^1.10.0", - "changelogen": "^0.5.5", - "chokidar": "^3.6.0", - "citty": "^0.1.6", - "clipboardy": "^4.0.0", - "colorette": "^2.0.20", - "consola": "^3.2.3", - "destr": "^2.0.3", - "eslint": "^8.57.0", - "execa": "^8.0.1", - "fuse.js": "^7.0.0", - "giget": "^1.2.1", - "h3": "^1.11.1", - "httpxy": "^0.1.5", - "jiti": "^1.21.0", - "listhen": "^1.7.2", - "magicast": "^0.3.3", - "mlly": "^1.6.1", - "nuxt": "^3.11.1", - "nypm": "^0.3.8", - "ofetch": "^1.3.3", - "pathe": "^1.1.2", - "perfect-debounce": "^1.0.0", - "pkg-types": "^1.0.3", - "prettier": "^3.2.5", - "scule": "^1.3.0", - "semver": "^7.6.0", - "unbuild": "^2.0.0", - "unws": "^0.2.4", - "vue-tsc": "^2.0.6", - "ws": "^8.16.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "resolutions": { - "nitropack": "npm:nitropack-nightly", - "nuxt": "^3.11.1", - "h3": "^1.11.1" - }, - "packageManager": "pnpm@8.15.5", - "engines": { - "node": "^16.10.0 || >=18.0.0" - } -} \ No newline at end of file diff --git a/.pnpm-store/v3/files/1f/00518f276a9fc92af2fdacf4cda4f23520177de4fe315d17c7d93651d0953ef7a963b615a180ff5182f9f86e79163194853f71b5ee5994f75ca7f065d15272 b/.pnpm-store/v3/files/1f/00518f276a9fc92af2fdacf4cda4f23520177de4fe315d17c7d93651d0953ef7a963b615a180ff5182f9f86e79163194853f71b5ee5994f75ca7f065d15272 deleted file mode 100644 index 8d1be459c81f0be0b06a1b3edd90813b264b5bb4..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/1f/00518f276a9fc92af2fdacf4cda4f23520177de4fe315d17c7d93651d0953ef7a963b615a180ff5182f9f86e79163194853f71b5ee5994f75ca7f065d15272 +++ /dev/null @@ -1,51 +0,0 @@ -import { execa } from './index3.mjs'; -import { d as defineCommand } from '../shared/nuxi.9edf0930.mjs'; -import { s as sharedArgs, l as legacyRootDirArgs, r as resolve } from '../shared/nuxi.610c92ff.mjs'; -import 'node:buffer'; -import 'node:path'; -import 'node:child_process'; -import 'node:process'; -import '../shared/nuxi.2155838d.mjs'; -import 'child_process'; -import 'path'; -import 'fs'; -import 'node:url'; -import 'node:os'; -import 'node:fs'; -import 'node:timers/promises'; -import 'stream'; -import 'node:util'; -import 'node:tty'; - -const devtools = defineCommand({ - meta: { - name: "devtools", - description: "Enable or disable devtools in a Nuxt project" - }, - args: { - ...sharedArgs, - command: { - type: "positional", - description: "Command to run", - valueHint: "enable|disable" - }, - ...legacyRootDirArgs - }, - async run(ctx) { - const cwd = resolve(ctx.args.cwd || ctx.args.rootDir || "."); - if (!["enable", "disable"].includes(ctx.args.command)) { - console.error(`Unknown command \`${ctx.args.command}\`.`); - process.exit(1); - } - await execa( - "npx", - ["@nuxt/devtools-wizard@latest", ctx.args.command, cwd], - { - stdio: "inherit", - cwd - } - ); - } -}); - -export { devtools as default }; diff --git a/.pnpm-store/v3/files/24/415b0814814c465240819b6202a210ca9c7112b5aaf744332710d1751b653fdd0a5d2b1e3916443a63f165aefdea1fc5d4363895f8a5ebac0c82052a4b627a b/.pnpm-store/v3/files/24/415b0814814c465240819b6202a210ca9c7112b5aaf744332710d1751b653fdd0a5d2b1e3916443a63f165aefdea1fc5d4363895f8a5ebac0c82052a4b627a deleted file mode 100644 index e39938a3f19f01e5db1f98d048592dd6b2e289d8..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/24/415b0814814c465240819b6202a210ca9c7112b5aaf744332710d1751b653fdd0a5d2b1e3916443a63f165aefdea1fc5d4363895f8a5ebac0c82052a4b627a +++ /dev/null @@ -1,54 +0,0 @@ -import { c as cleanupNuxtDirs } from '../shared/nuxi.1e36f2d5.mjs'; -import { d as defineCommand } from '../shared/nuxi.9edf0930.mjs'; -import { s as sharedArgs, l as legacyRootDirArgs, r as resolve } from '../shared/nuxi.610c92ff.mjs'; -import { l as loadKit } from '../shared/nuxi.dc1b30dc.mjs'; -import 'node:fs'; -import 'node:util'; -import 'node:path'; -import 'node:process'; -import 'node:tty'; -import '../shared/nuxi.1ff5d6e2.mjs'; -import 'node:url'; -import '../shared/nuxi.1902c37d.mjs'; -import 'node:module'; -import '../shared/nuxi.53f5921c.mjs'; -import 'node:assert'; -import 'node:v8'; -import 'node:perf_hooks'; -import '../shared/nuxi.eaa29140.mjs'; -import './satisfies.mjs'; -import '../shared/nuxi.2155838d.mjs'; -import '../shared/nuxi.cc8dd4a9.mjs'; -import '../shared/nuxi.73800aa7.mjs'; -import 'crypto'; -import 'fs'; -import 'module'; -import 'path'; -import 'perf_hooks'; -import 'os'; -import 'vm'; -import 'url'; -import 'assert'; -import 'process'; -import 'v8'; -import 'util'; -import 'tty'; - -const cleanup = defineCommand({ - meta: { - name: "cleanup", - description: "Clean up generated Nuxt files and caches" - }, - args: { - ...sharedArgs, - ...legacyRootDirArgs - }, - async run(ctx) { - const cwd = resolve(ctx.args.cwd || ctx.args.rootDir || "."); - const { loadNuxtConfig } = await loadKit(cwd); - const nuxtOptions = await loadNuxtConfig({ cwd }); - await cleanupNuxtDirs(nuxtOptions.rootDir, nuxtOptions.buildDir); - } -}); - -export { cleanup as default }; diff --git a/.pnpm-store/v3/files/25/dcf0356687abef9df33b99235a0d7cf47a5edf248672320922cec8216cb7fac18da2a9db1d4a53b9ee67dcd848a36665eedb7270b5a5aaacd88446672c195c b/.pnpm-store/v3/files/25/dcf0356687abef9df33b99235a0d7cf47a5edf248672320922cec8216cb7fac18da2a9db1d4a53b9ee67dcd848a36665eedb7270b5a5aaacd88446672c195c deleted file mode 100644 index 2d9184e1462875502ff000108516e99628c8796c..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/25/dcf0356687abef9df33b99235a0d7cf47a5edf248672320922cec8216cb7fac18da2a9db1d4a53b9ee67dcd848a36665eedb7270b5a5aaacd88446672c195c +++ /dev/null @@ -1,2437 +0,0 @@ -import { r as resolvePath$1, t as tryResolveModule$1, i as importModule } from './nuxi.1902c37d.mjs'; -import { promises, statSync, lstatSync, existsSync } from 'node:fs'; -import 'node:perf_hooks'; -import { d as defu } from './nuxi.eaa29140.mjs'; -import './nuxi.9edf0930.mjs'; -import 'node:util'; -import 'node:path'; -import 'node:process'; -import 'node:tty'; -import '../chunks/satisfies.mjs'; -import { fileURLToPath } from 'node:url'; -import { j as jiti } from './nuxi.73800aa7.mjs'; -import { i as isAbsolute, r as resolve, j as join, n as normalizeWindowsPath, a as relative, d as dirname, c as normalize } from './nuxi.610c92ff.mjs'; -import { w as withTrailingSlash } from './nuxi.53f5921c.mjs'; - -const defaultFindOptions = { - startingFrom: ".", - rootPattern: /^node_modules$/, - reverse: false, - test: (filePath) => { - try { - if (statSync(filePath).isFile()) { - return true; - } - } catch { - } - } -}; -async function findFile(filename, _options = {}) { - const options = { ...defaultFindOptions, ..._options }; - const basePath = resolve(options.startingFrom); - const leadingSlash = basePath[0] === "/"; - const segments = basePath.split("/").filter(Boolean); - if (leadingSlash) { - segments[0] = "/" + segments[0]; - } - let root = segments.findIndex((r) => r.match(options.rootPattern)); - if (root === -1) { - root = 0; - } - if (!options.reverse) { - for (let index = segments.length; index > root; index--) { - const filePath = join(...segments.slice(0, index), filename); - if (await options.test(filePath)) { - return filePath; - } - } - } else { - for (let index = root + 1; index <= segments.length; index++) { - const filePath = join(...segments.slice(0, index), filename); - if (await options.test(filePath)) { - return filePath; - } - } - } - throw new Error( - `Cannot find matching ${filename} in ${options.startingFrom} or parent directories` - ); -} -function findNearestFile(filename, _options = {}) { - return findFile(filename, _options); -} -const FileCache = /* @__PURE__ */ new Map(); -async function readPackageJSON(id, options = {}) { - const resolvedPath = await resolvePackageJSON(id, options); - const cache = options.cache && typeof options.cache !== "boolean" ? options.cache : FileCache; - if (options.cache && cache.has(resolvedPath)) { - return cache.get(resolvedPath); - } - const blob = await promises.readFile(resolvedPath, "utf8"); - const parsed = JSON.parse(blob); - cache.set(resolvedPath, parsed); - return parsed; -} -async function resolvePackageJSON(id = process.cwd(), options = {}) { - const resolvedPath = isAbsolute(id) ? id : await resolvePath$1(id, options); - return findNearestFile("package.json", { - startingFrom: resolvedPath, - ...options - }); -} - -function createContext(opts = {}) { - let currentInstance; - let isSingleton = false; - const checkConflict = (instance) => { - if (currentInstance && currentInstance !== instance) { - throw new Error("Context conflict"); - } - }; - let als; - if (opts.asyncContext) { - const _AsyncLocalStorage = opts.AsyncLocalStorage || globalThis.AsyncLocalStorage; - if (_AsyncLocalStorage) { - als = new _AsyncLocalStorage(); - } else { - console.warn("[unctx] `AsyncLocalStorage` is not provided."); - } - } - const _getCurrentInstance = () => { - if (als && currentInstance === void 0) { - const instance = als.getStore(); - if (instance !== void 0) { - return instance; - } - } - return currentInstance; - }; - return { - use: () => { - const _instance = _getCurrentInstance(); - if (_instance === void 0) { - throw new Error("Context is not available"); - } - return _instance; - }, - tryUse: () => { - return _getCurrentInstance(); - }, - set: (instance, replace) => { - if (!replace) { - checkConflict(instance); - } - currentInstance = instance; - isSingleton = true; - }, - unset: () => { - currentInstance = void 0; - isSingleton = false; - }, - call: (instance, callback) => { - checkConflict(instance); - currentInstance = instance; - try { - return als ? als.run(instance, callback) : callback(); - } finally { - if (!isSingleton) { - currentInstance = void 0; - } - } - }, - async callAsync(instance, callback) { - currentInstance = instance; - const onRestore = () => { - currentInstance = instance; - }; - const onLeave = () => currentInstance === instance ? onRestore : void 0; - asyncHandlers.add(onLeave); - try { - const r = als ? als.run(instance, callback) : callback(); - if (!isSingleton) { - currentInstance = void 0; - } - return await r; - } finally { - asyncHandlers.delete(onLeave); - } - } - }; -} -function createNamespace(defaultOpts = {}) { - const contexts = {}; - return { - get(key, opts = {}) { - if (!contexts[key]) { - contexts[key] = createContext({ ...defaultOpts, ...opts }); - } - contexts[key]; - return contexts[key]; - } - }; -} -const _globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {}; -const globalKey = "__unctx__"; -const defaultNamespace = _globalThis[globalKey] || (_globalThis[globalKey] = createNamespace()); -const getContext = (key, opts = {}) => defaultNamespace.get(key, opts); -const asyncHandlersKey = "__unctx_async_handlers__"; -const asyncHandlers = _globalThis[asyncHandlersKey] || (_globalThis[asyncHandlersKey] = /* @__PURE__ */ new Set()); - -// A simple implementation of make-array -function makeArray (subject) { - return Array.isArray(subject) - ? subject - : [subject] -} - -const EMPTY = ''; -const SPACE = ' '; -const ESCAPE = '\\'; -const REGEX_TEST_BLANK_LINE = /^\s+$/; -const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/; -const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/; -const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/; -const REGEX_SPLITALL_CRLF = /\r?\n/g; -// /foo, -// ./foo, -// ../foo, -// . -// .. -const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/; - -const SLASH = '/'; - -// Do not use ternary expression here, since "istanbul ignore next" is buggy -let TMP_KEY_IGNORE = 'node-ignore'; -/* istanbul ignore else */ -if (typeof Symbol !== 'undefined') { - TMP_KEY_IGNORE = Symbol.for('node-ignore'); -} -const KEY_IGNORE = TMP_KEY_IGNORE; - -const define = (object, key, value) => - Object.defineProperty(object, key, {value}); - -const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g; - -const RETURN_FALSE = () => false; - -// Sanitize the range of a regular expression -// The cases are complicated, see test cases for details -const sanitizeRange = range => range.replace( - REGEX_REGEXP_RANGE, - (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0) - ? match - // Invalid range (out of order) which is ok for gitignore rules but - // fatal for JavaScript regular expression, so eliminate it. - : EMPTY -); - -// See fixtures #59 -const cleanRangeBackSlash = slashes => { - const {length} = slashes; - return slashes.slice(0, length - length % 2) -}; - -// > If the pattern ends with a slash, -// > it is removed for the purpose of the following description, -// > but it would only find a match with a directory. -// > In other words, foo/ will match a directory foo and paths underneath it, -// > but will not match a regular file or a symbolic link foo -// > (this is consistent with the way how pathspec works in general in Git). -// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`' -// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call -// you could use option `mark: true` with `glob` - -// '`foo/`' should not continue with the '`..`' -const REPLACERS = [ - - [ - // remove BOM - // TODO: - // Other similar zero-width characters? - /^\uFEFF/, - () => EMPTY - ], - - // > Trailing spaces are ignored unless they are quoted with backslash ("\") - [ - // (a\ ) -> (a ) - // (a ) -> (a) - // (a \ ) -> (a ) - /\\?\s+$/, - match => match.indexOf('\\') === 0 - ? SPACE - : EMPTY - ], - - // replace (\ ) with ' ' - [ - /\\\s/g, - () => SPACE - ], - - // Escape metacharacters - // which is written down by users but means special for regular expressions. - - // > There are 12 characters with special meanings: - // > - the backslash \, - // > - the caret ^, - // > - the dollar sign $, - // > - the period or dot ., - // > - the vertical bar or pipe symbol |, - // > - the question mark ?, - // > - the asterisk or star *, - // > - the plus sign +, - // > - the opening parenthesis (, - // > - the closing parenthesis ), - // > - and the opening square bracket [, - // > - the opening curly brace {, - // > These special characters are often called "metacharacters". - [ - /[\\$.|*+(){^]/g, - match => `\\${match}` - ], - - [ - // > a question mark (?) matches a single character - /(?!\\)\?/g, - () => '[^/]' - ], - - // leading slash - [ - - // > A leading slash matches the beginning of the pathname. - // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". - // A leading slash matches the beginning of the pathname - /^\//, - () => '^' - ], - - // replace special metacharacter slash after the leading slash - [ - /\//g, - () => '\\/' - ], - - [ - // > A leading "**" followed by a slash means match in all directories. - // > For example, "**/foo" matches file or directory "foo" anywhere, - // > the same as pattern "foo". - // > "**/foo/bar" matches file or directory "bar" anywhere that is directly - // > under directory "foo". - // Notice that the '*'s have been replaced as '\\*' - /^\^*\\\*\\\*\\\//, - - // '**/foo' <-> 'foo' - () => '^(?:.*\\/)?' - ], - - // starting - [ - // there will be no leading '/' - // (which has been replaced by section "leading slash") - // If starts with '**', adding a '^' to the regular expression also works - /^(?=[^^])/, - function startingReplacer () { - // If has a slash `/` at the beginning or middle - return !/\/(?!$)/.test(this) - // > Prior to 2.22.1 - // > If the pattern does not contain a slash /, - // > Git treats it as a shell glob pattern - // Actually, if there is only a trailing slash, - // git also treats it as a shell glob pattern - - // After 2.22.1 (compatible but clearer) - // > If there is a separator at the beginning or middle (or both) - // > of the pattern, then the pattern is relative to the directory - // > level of the particular .gitignore file itself. - // > Otherwise the pattern may also match at any level below - // > the .gitignore level. - ? '(?:^|\\/)' - - // > Otherwise, Git treats the pattern as a shell glob suitable for - // > consumption by fnmatch(3) - : '^' - } - ], - - // two globstars - [ - // Use lookahead assertions so that we could match more than one `'/**'` - /\\\/\\\*\\\*(?=\\\/|$)/g, - - // Zero, one or several directories - // should not use '*', or it will be replaced by the next replacer - - // Check if it is not the last `'/**'` - (_, index, str) => index + 6 < str.length - - // case: /**/ - // > A slash followed by two consecutive asterisks then a slash matches - // > zero or more directories. - // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on. - // '/**/' - ? '(?:\\/[^\\/]+)*' - - // case: /** - // > A trailing `"/**"` matches everything inside. - - // #21: everything inside but it should not include the current folder - : '\\/.+' - ], - - // normal intermediate wildcards - [ - // Never replace escaped '*' - // ignore rule '\*' will match the path '*' - - // 'abc.*/' -> go - // 'abc.*' -> skip this rule, - // coz trailing single wildcard will be handed by [trailing wildcard] - /(^|[^\\]+)(\\\*)+(?=.+)/g, - - // '*.js' matches '.js' - // '*.js' doesn't match 'abc' - (_, p1, p2) => { - // 1. - // > An asterisk "*" matches anything except a slash. - // 2. - // > Other consecutive asterisks are considered regular asterisks - // > and will match according to the previous rules. - const unescaped = p2.replace(/\\\*/g, '[^\\/]*'); - return p1 + unescaped - } - ], - - [ - // unescape, revert step 3 except for back slash - // For example, if a user escape a '\\*', - // after step 3, the result will be '\\\\\\*' - /\\\\\\(?=[$.|*+(){^])/g, - () => ESCAPE - ], - - [ - // '\\\\' -> '\\' - /\\\\/g, - () => ESCAPE - ], - - [ - // > The range notation, e.g. [a-zA-Z], - // > can be used to match one of the characters in a range. - - // `\` is escaped by step 3 - /(\\)?\[([^\]/]*?)(\\*)($|\])/g, - (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE - // '\\[bar]' -> '\\\\[bar\\]' - ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}` - : close === ']' - ? endEscape.length % 2 === 0 - // A normal case, and it is a range notation - // '[bar]' - // '[bar\\\\]' - ? `[${sanitizeRange(range)}${endEscape}]` - // Invalid range notaton - // '[bar\\]' -> '[bar\\\\]' - : '[]' - : '[]' - ], - - // ending - [ - // 'js' will not match 'js.' - // 'ab' will not match 'abc' - /(?:[^*])$/, - - // WTF! - // https://git-scm.com/docs/gitignore - // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1) - // which re-fixes #24, #38 - - // > If there is a separator at the end of the pattern then the pattern - // > will only match directories, otherwise the pattern can match both - // > files and directories. - - // 'js*' will not match 'a.js' - // 'js/' will not match 'a.js' - // 'js' will match 'a.js' and 'a.js/' - match => /\/$/.test(match) - // foo/ will not match 'foo' - ? `${match}$` - // foo matches 'foo' and 'foo/' - : `${match}(?=$|\\/$)` - ], - - // trailing wildcard - [ - /(\^|\\\/)?\\\*$/, - (_, p1) => { - const prefix = p1 - // '\^': - // '/*' does not match EMPTY - // '/*' does not match everything - - // '\\\/': - // 'abc/*' does not match 'abc/' - ? `${p1}[^/]+` - - // 'a*' matches 'a' - // 'a*' matches 'aa' - : '[^/]*'; - - return `${prefix}(?=$|\\/$)` - } - ], -]; - -// A simple cache, because an ignore rule only has only one certain meaning -const regexCache = Object.create(null); - -// @param {pattern} -const makeRegex = (pattern, ignoreCase) => { - let source = regexCache[pattern]; - - if (!source) { - source = REPLACERS.reduce( - (prev, current) => prev.replace(current[0], current[1].bind(pattern)), - pattern - ); - regexCache[pattern] = source; - } - - return ignoreCase - ? new RegExp(source, 'i') - : new RegExp(source) -}; - -const isString = subject => typeof subject === 'string'; - -// > A blank line matches no files, so it can serve as a separator for readability. -const checkPattern = pattern => pattern - && isString(pattern) - && !REGEX_TEST_BLANK_LINE.test(pattern) - && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern) - - // > A line starting with # serves as a comment. - && pattern.indexOf('#') !== 0; - -const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF); - -class IgnoreRule { - constructor ( - origin, - pattern, - negative, - regex - ) { - this.origin = origin; - this.pattern = pattern; - this.negative = negative; - this.regex = regex; - } -} - -const createRule = (pattern, ignoreCase) => { - const origin = pattern; - let negative = false; - - // > An optional prefix "!" which negates the pattern; - if (pattern.indexOf('!') === 0) { - negative = true; - pattern = pattern.substr(1); - } - - pattern = pattern - // > Put a backslash ("\") in front of the first "!" for patterns that - // > begin with a literal "!", for example, `"\!important!.txt"`. - .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!') - // > Put a backslash ("\") in front of the first hash for patterns that - // > begin with a hash. - .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#'); - - const regex = makeRegex(pattern, ignoreCase); - - return new IgnoreRule( - origin, - pattern, - negative, - regex - ) -}; - -const throwError = (message, Ctor) => { - throw new Ctor(message) -}; - -const checkPath = (path, originalPath, doThrow) => { - if (!isString(path)) { - return doThrow( - `path must be a string, but got \`${originalPath}\``, - TypeError - ) - } - - // We don't know if we should ignore EMPTY, so throw - if (!path) { - return doThrow(`path must not be empty`, TypeError) - } - - // Check if it is a relative path - if (checkPath.isNotRelative(path)) { - const r = '`path.relative()`d'; - return doThrow( - `path should be a ${r} string, but got "${originalPath}"`, - RangeError - ) - } - - return true -}; - -const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path); - -checkPath.isNotRelative = isNotRelative; -checkPath.convert = p => p; - -class Ignore { - constructor ({ - ignorecase = true, - ignoreCase = ignorecase, - allowRelativePaths = false - } = {}) { - define(this, KEY_IGNORE, true); - - this._rules = []; - this._ignoreCase = ignoreCase; - this._allowRelativePaths = allowRelativePaths; - this._initCache(); - } - - _initCache () { - this._ignoreCache = Object.create(null); - this._testCache = Object.create(null); - } - - _addPattern (pattern) { - // #32 - if (pattern && pattern[KEY_IGNORE]) { - this._rules = this._rules.concat(pattern._rules); - this._added = true; - return - } - - if (checkPattern(pattern)) { - const rule = createRule(pattern, this._ignoreCase); - this._added = true; - this._rules.push(rule); - } - } - - // @param {Array | string | Ignore} pattern - add (pattern) { - this._added = false; - - makeArray( - isString(pattern) - ? splitPattern(pattern) - : pattern - ).forEach(this._addPattern, this); - - // Some rules have just added to the ignore, - // making the behavior changed. - if (this._added) { - this._initCache(); - } - - return this - } - - // legacy - addPattern (pattern) { - return this.add(pattern) - } - - // | ignored : unignored - // negative | 0:0 | 0:1 | 1:0 | 1:1 - // -------- | ------- | ------- | ------- | -------- - // 0 | TEST | TEST | SKIP | X - // 1 | TESTIF | SKIP | TEST | X - - // - SKIP: always skip - // - TEST: always test - // - TESTIF: only test if checkUnignored - // - X: that never happen - - // @param {boolean} whether should check if the path is unignored, - // setting `checkUnignored` to `false` could reduce additional - // path matching. - - // @returns {TestResult} true if a file is ignored - _testOne (path, checkUnignored) { - let ignored = false; - let unignored = false; - - this._rules.forEach(rule => { - const {negative} = rule; - if ( - unignored === negative && ignored !== unignored - || negative && !ignored && !unignored && !checkUnignored - ) { - return - } - - const matched = rule.regex.test(path); - - if (matched) { - ignored = !negative; - unignored = negative; - } - }); - - return { - ignored, - unignored - } - } - - // @returns {TestResult} - _test (originalPath, cache, checkUnignored, slices) { - const path = originalPath - // Supports nullable path - && checkPath.convert(originalPath); - - checkPath( - path, - originalPath, - this._allowRelativePaths - ? RETURN_FALSE - : throwError - ); - - return this._t(path, cache, checkUnignored, slices) - } - - _t (path, cache, checkUnignored, slices) { - if (path in cache) { - return cache[path] - } - - if (!slices) { - // path/to/a.js - // ['path', 'to', 'a.js'] - slices = path.split(SLASH); - } - - slices.pop(); - - // If the path has no parent directory, just test it - if (!slices.length) { - return cache[path] = this._testOne(path, checkUnignored) - } - - const parent = this._t( - slices.join(SLASH) + SLASH, - cache, - checkUnignored, - slices - ); - - // If the path contains a parent directory, check the parent first - return cache[path] = parent.ignored - // > It is not possible to re-include a file if a parent directory of - // > that file is excluded. - ? parent - : this._testOne(path, checkUnignored) - } - - ignores (path) { - return this._test(path, this._ignoreCache, false).ignored - } - - createFilter () { - return path => !this.ignores(path) - } - - filter (paths) { - return makeArray(paths).filter(this.createFilter()) - } - - // @returns {TestResult} - test (path) { - return this._test(path, this._testCache, true) - } -} - -const factory = options => new Ignore(options); - -const isPathValid = path => - checkPath(path && checkPath.convert(path), path, RETURN_FALSE); - -factory.isPathValid = isPathValid; - -// Fixes typescript -factory.default = factory; - -// Windows -// -------------------------------------------------------------- -/* istanbul ignore if */ -if ( - // Detect `process` so that it can run in browsers. - typeof process !== 'undefined' - && ( - process.env && process.env.IGNORE_TEST_WIN32 - || process.platform === 'win32' - ) -) { - /* eslint no-control-regex: "off" */ - const makePosix = str => /^\\\\\?\\/.test(str) - || /["<>|\u0000-\u001F]+/u.test(str) - ? str - : str.replace(/\\/g, '/'); - - checkPath.convert = makePosix; - - // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/' - // 'd:\\foo' - const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i; - checkPath.isNotRelative = path => - REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path) - || isNotRelative(path); -} - -const pathSeparators = /* @__PURE__ */ new Set(["/", "\\", void 0]); -const normalizedAliasSymbol = Symbol.for("pathe:normalizedAlias"); -function normalizeAliases(_aliases) { - if (_aliases[normalizedAliasSymbol]) { - return _aliases; - } - const aliases = Object.fromEntries( - Object.entries(_aliases).sort(([a], [b]) => _compareAliases(a, b)) - ); - for (const key in aliases) { - for (const alias in aliases) { - if (alias === key || key.startsWith(alias)) { - continue; - } - if (aliases[key].startsWith(alias) && pathSeparators.has(aliases[key][alias.length])) { - aliases[key] = aliases[alias] + aliases[key].slice(alias.length); - } - } - } - Object.defineProperty(aliases, normalizedAliasSymbol, { - value: true, - enumerable: false - }); - return aliases; -} -function resolveAlias$1(path, aliases) { - const _path = normalizeWindowsPath(path); - aliases = normalizeAliases(aliases); - for (const [alias, to] of Object.entries(aliases)) { - if (!_path.startsWith(alias)) { - continue; - } - const _alias = hasTrailingSlash(alias) ? alias.slice(0, -1) : alias; - if (hasTrailingSlash(_path[_alias.length])) { - return join(to, _path.slice(alias.length)); - } - } - return _path; -} -function _compareAliases(a, b) { - return b.split("/").length - a.split("/").length; -} -function hasTrailingSlash(path = "/") { - const lastChar = path[path.length - 1]; - return lastChar === "/" || lastChar === "\\"; -} - -const nuxtCtx = getContext("nuxt"); -function tryUseNuxt() { - return nuxtCtx.tryUse(); -} - -/** Detect free variable `global` from Node.js. */ -var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; - -/** Detect free variable `self`. */ -var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - -/** Used as a reference to the global object. */ -var root = freeGlobal || freeSelf || Function('return this')(); - -/** Built-in value references. */ -var Symbol$1 = root.Symbol; - -/** Used for built-in method references. */ -var objectProto$b = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$9 = objectProto$b.hasOwnProperty; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var nativeObjectToString$1 = objectProto$b.toString; - -/** Built-in value references. */ -var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined; - -/** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ -function getRawTag(value) { - var isOwn = hasOwnProperty$9.call(value, symToStringTag$1), - tag = value[symToStringTag$1]; - - try { - value[symToStringTag$1] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString$1.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag$1] = tag; - } else { - delete value[symToStringTag$1]; - } - } - return result; -} - -/** Used for built-in method references. */ -var objectProto$a = Object.prototype; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var nativeObjectToString = objectProto$a.toString; - -/** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ -function objectToString(value) { - return nativeObjectToString.call(value); -} - -/** `Object#toString` result references. */ -var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - -/** Built-in value references. */ -var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : undefined; - -/** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ -function baseGetTag(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); -} - -/** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ -function isObjectLike(value) { - return value != null && typeof value == 'object'; -} - -/** - * Checks if `value` is classified as an `Array` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. - * @example - * - * _.isArray([1, 2, 3]); - * // => true - * - * _.isArray(document.body.children); - * // => false - * - * _.isArray('abc'); - * // => false - * - * _.isArray(_.noop); - * // => false - */ -var isArray = Array.isArray; - -/** Used to convert symbols to primitives and strings. */ -var symbolProto = Symbol$1 ? Symbol$1.prototype : undefined; - symbolProto ? symbolProto.toString : undefined; - -/** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ -function isObject(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); -} - -/** - * This method returns the first argument it receives. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Util - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'a': 1 }; - * - * console.log(_.identity(object) === object); - * // => true - */ -function identity(value) { - return value; -} - -/** `Object#toString` result references. */ -var asyncTag = '[object AsyncFunction]', - funcTag$1 = '[object Function]', - genTag = '[object GeneratorFunction]', - proxyTag = '[object Proxy]'; - -/** - * Checks if `value` is classified as a `Function` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - * - * _.isFunction(/abc/); - * // => false - */ -function isFunction(value) { - if (!isObject(value)) { - return false; - } - // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 9 which returns 'object' for typed arrays and other constructors. - var tag = baseGetTag(value); - return tag == funcTag$1 || tag == genTag || tag == asyncTag || tag == proxyTag; -} - -/** Used to detect overreaching core-js shims. */ -var coreJsData = root['__core-js_shared__']; - -/** Used to detect methods masquerading as native. */ -var maskSrcKey = (function() { - var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); - return uid ? ('Symbol(src)_1.' + uid) : ''; -}()); - -/** - * Checks if `func` has its source masked. - * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` is masked, else `false`. - */ -function isMasked(func) { - return !!maskSrcKey && (maskSrcKey in func); -} - -/** Used for built-in method references. */ -var funcProto$2 = Function.prototype; - -/** Used to resolve the decompiled source of functions. */ -var funcToString$2 = funcProto$2.toString; - -/** - * Converts `func` to its source code. - * - * @private - * @param {Function} func The function to convert. - * @returns {string} Returns the source code. - */ -function toSource(func) { - if (func != null) { - try { - return funcToString$2.call(func); - } catch (e) {} - try { - return (func + ''); - } catch (e) {} - } - return ''; -} - -/** - * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). - */ -var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; - -/** Used to detect host constructors (Safari). */ -var reIsHostCtor = /^\[object .+?Constructor\]$/; - -/** Used for built-in method references. */ -var funcProto$1 = Function.prototype, - objectProto$9 = Object.prototype; - -/** Used to resolve the decompiled source of functions. */ -var funcToString$1 = funcProto$1.toString; - -/** Used to check objects for own properties. */ -var hasOwnProperty$8 = objectProto$9.hasOwnProperty; - -/** Used to detect if a method is native. */ -var reIsNative = RegExp('^' + - funcToString$1.call(hasOwnProperty$8).replace(reRegExpChar, '\\$&') - .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' -); - -/** - * The base implementation of `_.isNative` without bad shim checks. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, - * else `false`. - */ -function baseIsNative(value) { - if (!isObject(value) || isMasked(value)) { - return false; - } - var pattern = isFunction(value) ? reIsNative : reIsHostCtor; - return pattern.test(toSource(value)); -} - -/** - * Gets the value at `key` of `object`. - * - * @private - * @param {Object} [object] The object to query. - * @param {string} key The key of the property to get. - * @returns {*} Returns the property value. - */ -function getValue(object, key) { - return object == null ? undefined : object[key]; -} - -/** - * Gets the native function at `key` of `object`. - * - * @private - * @param {Object} object The object to query. - * @param {string} key The key of the method to get. - * @returns {*} Returns the function if it's native, else `undefined`. - */ -function getNative(object, key) { - var value = getValue(object, key); - return baseIsNative(value) ? value : undefined; -} - -/** - * A faster alternative to `Function#apply`, this function invokes `func` - * with the `this` binding of `thisArg` and the arguments of `args`. - * - * @private - * @param {Function} func The function to invoke. - * @param {*} thisArg The `this` binding of `func`. - * @param {Array} args The arguments to invoke `func` with. - * @returns {*} Returns the result of `func`. - */ -function apply(func, thisArg, args) { - switch (args.length) { - case 0: return func.call(thisArg); - case 1: return func.call(thisArg, args[0]); - case 2: return func.call(thisArg, args[0], args[1]); - case 3: return func.call(thisArg, args[0], args[1], args[2]); - } - return func.apply(thisArg, args); -} - -/** Used to detect hot functions by number of calls within a span of milliseconds. */ -var HOT_COUNT = 800, - HOT_SPAN = 16; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeNow = Date.now; - -/** - * Creates a function that'll short out and invoke `identity` instead - * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` - * milliseconds. - * - * @private - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new shortable function. - */ -function shortOut(func) { - var count = 0, - lastCalled = 0; - - return function() { - var stamp = nativeNow(), - remaining = HOT_SPAN - (stamp - lastCalled); - - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return arguments[0]; - } - } else { - count = 0; - } - return func.apply(undefined, arguments); - }; -} - -/** - * Creates a function that returns `value`. - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Util - * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new constant function. - * @example - * - * var objects = _.times(2, _.constant({ 'a': 1 })); - * - * console.log(objects); - * // => [{ 'a': 1 }, { 'a': 1 }] - * - * console.log(objects[0] === objects[1]); - * // => true - */ -function constant(value) { - return function() { - return value; - }; -} - -var defineProperty = (function() { - try { - var func = getNative(Object, 'defineProperty'); - func({}, '', {}); - return func; - } catch (e) {} -}()); - -/** - * The base implementation of `setToString` without support for hot loop shorting. - * - * @private - * @param {Function} func The function to modify. - * @param {Function} string The `toString` result. - * @returns {Function} Returns `func`. - */ -var baseSetToString = !defineProperty ? identity : function(func, string) { - return defineProperty(func, 'toString', { - 'configurable': true, - 'enumerable': false, - 'value': constant(string), - 'writable': true - }); -}; - -const baseSetToString$1 = baseSetToString; - -/** - * Sets the `toString` method of `func` to return `string`. - * - * @private - * @param {Function} func The function to modify. - * @param {Function} string The `toString` result. - * @returns {Function} Returns `func`. - */ -var setToString = shortOut(baseSetToString$1); - -/** Used as references for various `Number` constants. */ -var MAX_SAFE_INTEGER$1 = 9007199254740991; - -/** Used to detect unsigned integer values. */ -var reIsUint = /^(?:0|[1-9]\d*)$/; - -/** - * Checks if `value` is a valid array-like index. - * - * @private - * @param {*} value The value to check. - * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. - * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. - */ -function isIndex(value, length) { - var type = typeof value; - length = length == null ? MAX_SAFE_INTEGER$1 : length; - - return !!length && - (type == 'number' || - (type != 'symbol' && reIsUint.test(value))) && - (value > -1 && value % 1 == 0 && value < length); -} - -/** - * The base implementation of `assignValue` and `assignMergeValue` without - * value checks. - * - * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. - */ -function baseAssignValue(object, key, value) { - if (key == '__proto__' && defineProperty) { - defineProperty(object, key, { - 'configurable': true, - 'enumerable': true, - 'value': value, - 'writable': true - }); - } else { - object[key] = value; - } -} - -/** - * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * comparison between two values to determine if they are equivalent. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'a': 1 }; - * var other = { 'a': 1 }; - * - * _.eq(object, object); - * // => true - * - * _.eq(object, other); - * // => false - * - * _.eq('a', 'a'); - * // => true - * - * _.eq('a', Object('a')); - * // => false - * - * _.eq(NaN, NaN); - * // => true - */ -function eq(value, other) { - return value === other || (value !== value && other !== other); -} - -/** Used for built-in method references. */ -var objectProto$8 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$7 = objectProto$8.hasOwnProperty; - -/** - * Assigns `value` to `key` of `object` if the existing value is not equivalent - * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. - * - * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. - */ -function assignValue(object, key, value) { - var objValue = object[key]; - if (!(hasOwnProperty$7.call(object, key) && eq(objValue, value)) || - (value === undefined && !(key in object))) { - baseAssignValue(object, key, value); - } -} - -/** - * Copies properties of `source` to `object`. - * - * @private - * @param {Object} source The object to copy properties from. - * @param {Array} props The property identifiers to copy. - * @param {Object} [object={}] The object to copy properties to. - * @param {Function} [customizer] The function to customize copied values. - * @returns {Object} Returns `object`. - */ -function copyObject(source, props, object, customizer) { - var isNew = !object; - object || (object = {}); - - var index = -1, - length = props.length; - - while (++index < length) { - var key = props[index]; - - var newValue = customizer - ? customizer(object[key], source[key], key, object, source) - : undefined; - - if (newValue === undefined) { - newValue = source[key]; - } - if (isNew) { - baseAssignValue(object, key, newValue); - } else { - assignValue(object, key, newValue); - } - } - return object; -} - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeMax = Math.max; - -/** - * A specialized version of `baseRest` which transforms the rest array. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @param {Function} transform The rest array transform. - * @returns {Function} Returns the new function. - */ -function overRest(func, start, transform) { - start = nativeMax(start === undefined ? (func.length - 1) : start, 0); - return function() { - var args = arguments, - index = -1, - length = nativeMax(args.length - start, 0), - array = Array(length); - - while (++index < length) { - array[index] = args[start + index]; - } - index = -1; - var otherArgs = Array(start + 1); - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = transform(array); - return apply(func, this, otherArgs); - }; -} - -/** - * The base implementation of `_.rest` which doesn't validate or coerce arguments. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @returns {Function} Returns the new function. - */ -function baseRest(func, start) { - return setToString(overRest(func, start, identity), func + ''); -} - -/** Used as references for various `Number` constants. */ -var MAX_SAFE_INTEGER = 9007199254740991; - -/** - * Checks if `value` is a valid array-like length. - * - * **Note:** This method is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. - * @example - * - * _.isLength(3); - * // => true - * - * _.isLength(Number.MIN_VALUE); - * // => false - * - * _.isLength(Infinity); - * // => false - * - * _.isLength('3'); - * // => false - */ -function isLength(value) { - return typeof value == 'number' && - value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; -} - -/** - * Checks if `value` is array-like. A value is considered array-like if it's - * not a function and has a `value.length` that's an integer greater than or - * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. - * @example - * - * _.isArrayLike([1, 2, 3]); - * // => true - * - * _.isArrayLike(document.body.children); - * // => true - * - * _.isArrayLike('abc'); - * // => true - * - * _.isArrayLike(_.noop); - * // => false - */ -function isArrayLike(value) { - return value != null && isLength(value.length) && !isFunction(value); -} - -/** - * Checks if the given arguments are from an iteratee call. - * - * @private - * @param {*} value The potential iteratee value argument. - * @param {*} index The potential iteratee index or key argument. - * @param {*} object The potential iteratee object argument. - * @returns {boolean} Returns `true` if the arguments are from an iteratee call, - * else `false`. - */ -function isIterateeCall(value, index, object) { - if (!isObject(object)) { - return false; - } - var type = typeof index; - if (type == 'number' - ? (isArrayLike(object) && isIndex(index, object.length)) - : (type == 'string' && index in object) - ) { - return eq(object[index], value); - } - return false; -} - -/** - * Creates a function like `_.assign`. - * - * @private - * @param {Function} assigner The function to assign values. - * @returns {Function} Returns the new assigner function. - */ -function createAssigner(assigner) { - return baseRest(function(object, sources) { - var index = -1, - length = sources.length, - customizer = length > 1 ? sources[length - 1] : undefined, - guard = length > 2 ? sources[2] : undefined; - - customizer = (assigner.length > 3 && typeof customizer == 'function') - ? (length--, customizer) - : undefined; - - if (guard && isIterateeCall(sources[0], sources[1], guard)) { - customizer = length < 3 ? undefined : customizer; - length = 1; - } - object = Object(object); - while (++index < length) { - var source = sources[index]; - if (source) { - assigner(object, source, index, customizer); - } - } - return object; - }); -} - -/** Used for built-in method references. */ -var objectProto$7 = Object.prototype; - -/** - * Checks if `value` is likely a prototype object. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. - */ -function isPrototype(value) { - var Ctor = value && value.constructor, - proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto$7; - - return value === proto; -} - -/** - * The base implementation of `_.times` without support for iteratee shorthands - * or max array length checks. - * - * @private - * @param {number} n The number of times to invoke `iteratee`. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns the array of results. - */ -function baseTimes(n, iteratee) { - var index = -1, - result = Array(n); - - while (++index < n) { - result[index] = iteratee(index); - } - return result; -} - -/** `Object#toString` result references. */ -var argsTag$1 = '[object Arguments]'; - -/** - * The base implementation of `_.isArguments`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - */ -function baseIsArguments(value) { - return isObjectLike(value) && baseGetTag(value) == argsTag$1; -} - -/** Used for built-in method references. */ -var objectProto$6 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$6 = objectProto$6.hasOwnProperty; - -/** Built-in value references. */ -var propertyIsEnumerable = objectProto$6.propertyIsEnumerable; - -/** - * Checks if `value` is likely an `arguments` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - * else `false`. - * @example - * - * _.isArguments(function() { return arguments; }()); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false - */ -var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { - return isObjectLike(value) && hasOwnProperty$6.call(value, 'callee') && - !propertyIsEnumerable.call(value, 'callee'); -}; - -/** - * This method returns `false`. - * - * @static - * @memberOf _ - * @since 4.13.0 - * @category Util - * @returns {boolean} Returns `false`. - * @example - * - * _.times(2, _.stubFalse); - * // => [false, false] - */ -function stubFalse() { - return false; -} - -/** Detect free variable `exports`. */ -var freeExports$1 = typeof exports == 'object' && exports && !exports.nodeType && exports; - -/** Detect free variable `module`. */ -var freeModule$1 = freeExports$1 && typeof module == 'object' && module && !module.nodeType && module; - -/** Detect the popular CommonJS extension `module.exports`. */ -var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1; - -/** Built-in value references. */ -var Buffer = moduleExports$1 ? root.Buffer : undefined; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; - -/** - * Checks if `value` is a buffer. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. - * @example - * - * _.isBuffer(new Buffer(2)); - * // => true - * - * _.isBuffer(new Uint8Array(2)); - * // => false - */ -var isBuffer = nativeIsBuffer || stubFalse; - -/** `Object#toString` result references. */ -var argsTag = '[object Arguments]', - arrayTag = '[object Array]', - boolTag = '[object Boolean]', - dateTag = '[object Date]', - errorTag$1 = '[object Error]', - funcTag = '[object Function]', - mapTag = '[object Map]', - numberTag = '[object Number]', - objectTag$1 = '[object Object]', - regexpTag = '[object RegExp]', - setTag = '[object Set]', - stringTag = '[object String]', - weakMapTag = '[object WeakMap]'; - -var arrayBufferTag = '[object ArrayBuffer]', - dataViewTag = '[object DataView]', - float32Tag = '[object Float32Array]', - float64Tag = '[object Float64Array]', - int8Tag = '[object Int8Array]', - int16Tag = '[object Int16Array]', - int32Tag = '[object Int32Array]', - uint8Tag = '[object Uint8Array]', - uint8ClampedTag = '[object Uint8ClampedArray]', - uint16Tag = '[object Uint16Array]', - uint32Tag = '[object Uint32Array]'; - -/** Used to identify `toStringTag` values of typed arrays. */ -var typedArrayTags = {}; -typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = -typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = -typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = -typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = -typedArrayTags[uint32Tag] = true; -typedArrayTags[argsTag] = typedArrayTags[arrayTag] = -typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = -typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = -typedArrayTags[errorTag$1] = typedArrayTags[funcTag] = -typedArrayTags[mapTag] = typedArrayTags[numberTag] = -typedArrayTags[objectTag$1] = typedArrayTags[regexpTag] = -typedArrayTags[setTag] = typedArrayTags[stringTag] = -typedArrayTags[weakMapTag] = false; - -/** - * The base implementation of `_.isTypedArray` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. - */ -function baseIsTypedArray(value) { - return isObjectLike(value) && - isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; -} - -/** - * The base implementation of `_.unary` without support for storing metadata. - * - * @private - * @param {Function} func The function to cap arguments for. - * @returns {Function} Returns the new capped function. - */ -function baseUnary(func) { - return function(value) { - return func(value); - }; -} - -/** Detect free variable `exports`. */ -var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; - -/** Detect free variable `module`. */ -var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; - -/** Detect the popular CommonJS extension `module.exports`. */ -var moduleExports = freeModule && freeModule.exports === freeExports; - -/** Detect free variable `process` from Node.js. */ -var freeProcess = moduleExports && freeGlobal.process; - -/** Used to access faster Node.js helpers. */ -var nodeUtil = (function() { - try { - // Use `util.types` for Node.js 10+. - var types = freeModule && freeModule.require && freeModule.require('util').types; - - if (types) { - return types; - } - - // Legacy `process.binding('util')` for Node.js < 10. - return freeProcess && freeProcess.binding && freeProcess.binding('util'); - } catch (e) {} -}()); - -/* Node.js helper references. */ -var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; - -/** - * Checks if `value` is classified as a typed array. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. - * @example - * - * _.isTypedArray(new Uint8Array); - * // => true - * - * _.isTypedArray([]); - * // => false - */ -var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; - -/** Used for built-in method references. */ -var objectProto$5 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$5 = objectProto$5.hasOwnProperty; - -/** - * Creates an array of the enumerable property names of the array-like `value`. - * - * @private - * @param {*} value The value to query. - * @param {boolean} inherited Specify returning inherited property names. - * @returns {Array} Returns the array of property names. - */ -function arrayLikeKeys(value, inherited) { - var isArr = isArray(value), - isArg = !isArr && isArguments(value), - isBuff = !isArr && !isArg && isBuffer(value), - isType = !isArr && !isArg && !isBuff && isTypedArray(value), - skipIndexes = isArr || isArg || isBuff || isType, - result = skipIndexes ? baseTimes(value.length, String) : [], - length = result.length; - - for (var key in value) { - if ((inherited || hasOwnProperty$5.call(value, key)) && - !(skipIndexes && ( - // Safari 9 has enumerable `arguments.length` in strict mode. - key == 'length' || - // Node.js 0.10 has enumerable non-index properties on buffers. - (isBuff && (key == 'offset' || key == 'parent')) || - // PhantomJS 2 has enumerable non-index properties on typed arrays. - (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || - // Skip index properties. - isIndex(key, length) - ))) { - result.push(key); - } - } - return result; -} - -/** - * Creates a unary function that invokes `func` with its argument transformed. - * - * @private - * @param {Function} func The function to wrap. - * @param {Function} transform The argument transform. - * @returns {Function} Returns the new function. - */ -function overArg(func, transform) { - return function(arg) { - return func(transform(arg)); - }; -} - -/** - * This function is like - * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * except that it includes inherited enumerable properties. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ -function nativeKeysIn(object) { - var result = []; - if (object != null) { - for (var key in Object(object)) { - result.push(key); - } - } - return result; -} - -/** Used for built-in method references. */ -var objectProto$3 = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty$3 = objectProto$3.hasOwnProperty; - -/** - * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ -function baseKeysIn(object) { - if (!isObject(object)) { - return nativeKeysIn(object); - } - var isProto = isPrototype(object), - result = []; - - for (var key in object) { - if (!(key == 'constructor' && (isProto || !hasOwnProperty$3.call(object, key)))) { - result.push(key); - } - } - return result; -} - -/** - * Creates an array of the own and inherited enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.keysIn(new Foo); - * // => ['a', 'b', 'c'] (iteration order is not guaranteed) - */ -function keysIn(object) { - return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); -} - -/** - * This method is like `_.assignIn` except that it accepts `customizer` - * which is invoked to produce the assigned values. If `customizer` returns - * `undefined`, assignment is handled by the method instead. The `customizer` - * is invoked with five arguments: (objValue, srcValue, key, object, source). - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @alias extendWith - * @category Object - * @param {Object} object The destination object. - * @param {...Object} sources The source objects. - * @param {Function} [customizer] The function to customize assigned values. - * @returns {Object} Returns `object`. - * @see _.assignWith - * @example - * - * function customizer(objValue, srcValue) { - * return _.isUndefined(objValue) ? srcValue : objValue; - * } - * - * var defaults = _.partialRight(_.assignInWith, customizer); - * - * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); - * // => { 'a': 1, 'b': 2 } - */ -createAssigner(function(object, source, srcIndex, customizer) { - copyObject(source, keysIn(source), object, customizer); -}); - -/** Built-in value references. */ -var getPrototype = overArg(Object.getPrototypeOf, Object); - -/** `Object#toString` result references. */ -var objectTag = '[object Object]'; - -/** Used for built-in method references. */ -var funcProto = Function.prototype, - objectProto$2 = Object.prototype; - -/** Used to resolve the decompiled source of functions. */ -var funcToString = funcProto.toString; - -/** Used to check objects for own properties. */ -var hasOwnProperty$2 = objectProto$2.hasOwnProperty; - -/** Used to infer the `Object` constructor. */ -var objectCtorString = funcToString.call(Object); - -/** - * Checks if `value` is a plain object, that is, an object created by the - * `Object` constructor or one with a `[[Prototype]]` of `null`. - * - * @static - * @memberOf _ - * @since 0.8.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - * @example - * - * function Foo() { - * this.a = 1; - * } - * - * _.isPlainObject(new Foo); - * // => false - * - * _.isPlainObject([1, 2, 3]); - * // => false - * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true - * - * _.isPlainObject(Object.create(null)); - * // => true - */ -function isPlainObject(value) { - if (!isObjectLike(value) || baseGetTag(value) != objectTag) { - return false; - } - var proto = getPrototype(value); - if (proto === null) { - return true; - } - var Ctor = hasOwnProperty$2.call(proto, 'constructor') && proto.constructor; - return typeof Ctor == 'function' && Ctor instanceof Ctor && - funcToString.call(Ctor) == objectCtorString; -} - -/** `Object#toString` result references. */ -var domExcTag = '[object DOMException]', - errorTag = '[object Error]'; - -/** - * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, - * `SyntaxError`, `TypeError`, or `URIError` object. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an error object, else `false`. - * @example - * - * _.isError(new Error); - * // => true - * - * _.isError(Error); - * // => false - */ -function isError(value) { - if (!isObjectLike(value)) { - return false; - } - var tag = baseGetTag(value); - return tag == errorTag || tag == domExcTag || - (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); -} - -/** - * Attempts to invoke `func`, returning either the result or the caught error - * object. Any additional arguments are provided to `func` when it's invoked. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Util - * @param {Function} func The function to attempt. - * @param {...*} [args] The arguments to invoke `func` with. - * @returns {*} Returns the `func` result or error object. - * @example - * - * // Avoid throwing errors for invalid selectors. - * var elements = _.attempt(function(selector) { - * return document.querySelectorAll(selector); - * }, '>_>'); - * - * if (_.isError(elements)) { - * elements = []; - * } - */ -baseRest(function(func, args) { - try { - return apply(func, undefined, args); - } catch (e) { - return isError(e) ? e : new Error(e); - } -}); - -jiti(process.cwd(), { interopDefault: true, esmResolve: true }); -function getModulePaths(paths) { - return [].concat( - global.__NUXT_PREPATHS__, - paths || [], - process.cwd(), - global.__NUXT_PATHS__ - ).filter(Boolean); -} - -async function tryResolveModule(id, url = import.meta.url) { - try { - return await resolvePath$1(id, { url }); - } catch { - } -} - -async function resolvePath(path, opts = {}) { - const _path = path; - path = normalize(path); - if (isAbsolute(path) && existsSync(path) && !await isDirectory(path)) { - return path; - } - const nuxt = tryUseNuxt(); - const cwd = opts.cwd || (nuxt ? nuxt.options.rootDir : process.cwd()); - const extensions = opts.extensions || (nuxt ? nuxt.options.extensions : [".ts", ".mjs", ".cjs", ".json"]); - const modulesDir = nuxt ? nuxt.options.modulesDir : []; - path = resolveAlias(path); - if (!isAbsolute(path)) { - path = resolve(cwd, path); - } - let _isDir = false; - if (existsSync(path)) { - _isDir = await isDirectory(path); - if (!_isDir) { - return path; - } - } - for (const ext of extensions) { - const pathWithExt = path + ext; - if (existsSync(pathWithExt)) { - return pathWithExt; - } - const pathWithIndex = join(path, "index" + ext); - if (_isDir && existsSync(pathWithIndex)) { - return pathWithIndex; - } - } - const resolveModulePath = await resolvePath$1(_path, { url: [cwd, ...modulesDir] }).catch(() => null); - if (resolveModulePath) { - return resolveModulePath; - } - return path; -} -function resolveAlias(path, alias) { - if (!alias) { - alias = tryUseNuxt()?.options.alias || {}; - } - return resolveAlias$1(path, alias); -} -function createResolver(base) { - if (!base) { - throw new Error("`base` argument is missing for createResolver(base)!"); - } - base = base.toString(); - if (base.startsWith("file://")) { - base = dirname(fileURLToPath(base)); - } - return { - resolve: (...path) => resolve(base, ...path), - resolvePath: (path, opts) => resolvePath(path, { cwd: base, ...opts }) - }; -} -async function resolveNuxtModule(base, paths) { - const resolved = []; - const resolver = createResolver(base); - for (const path of paths) { - if (path.startsWith(base)) { - resolved.push(path.split("/index.ts")[0]); - } else { - const resolvedPath = await resolver.resolvePath(path); - resolved.push(resolvedPath.slice(0, resolvedPath.lastIndexOf(path) + path.length)); - } - } - return resolved; -} -async function isDirectory(path) { - return (await promises.lstat(path)).isDirectory(); -} -function getDirectory(p) { - try { - return isAbsolute(p) && lstatSync(p).isFile() ? dirname(p) : p; - } catch (e) { - } - return p; -} -async function _generateTypes(nuxt) { - const nodeModulePaths = getModulePaths(nuxt.options.modulesDir); - const rootDirWithSlash = withTrailingSlash(nuxt.options.rootDir); - const modulePaths = await resolveNuxtModule( - rootDirWithSlash, - nuxt.options._installedModules.filter((m) => m.entryPath).map((m) => getDirectory(m.entryPath)) - ); - const tsConfig = defu(nuxt.options.typescript?.tsConfig, { - compilerOptions: { - forceConsistentCasingInFileNames: true, - jsx: "preserve", - jsxImportSource: "vue", - target: "ESNext", - module: "ESNext", - moduleResolution: nuxt.options.future?.typescriptBundlerResolution || nuxt.options.experimental?.typescriptBundlerResolution ? "Bundler" : "Node", - skipLibCheck: true, - isolatedModules: true, - useDefineForClassFields: true, - strict: nuxt.options.typescript?.strict ?? true, - noImplicitThis: true, - esModuleInterop: true, - types: [], - verbatimModuleSyntax: true, - allowJs: true, - noEmit: true, - resolveJsonModule: true, - allowSyntheticDefaultImports: true, - paths: {} - }, - include: [ - "./nuxt.d.ts", - join(relativeWithDot(nuxt.options.buildDir, nuxt.options.rootDir), ".config/nuxt.*"), - join(relativeWithDot(nuxt.options.buildDir, nuxt.options.rootDir), "**/*"), - ...nuxt.options.srcDir !== nuxt.options.rootDir ? [join(relative(nuxt.options.buildDir, nuxt.options.srcDir), "**/*")] : [], - ...nuxt.options._layers.map((layer) => layer.config.srcDir ?? layer.cwd).filter((srcOrCwd) => !srcOrCwd.startsWith(rootDirWithSlash) || srcOrCwd.includes("node_modules")).map((srcOrCwd) => join(relative(nuxt.options.buildDir, srcOrCwd), "**/*")), - ...nuxt.options.typescript.includeWorkspace && nuxt.options.workspaceDir !== nuxt.options.rootDir ? [join(relative(nuxt.options.buildDir, nuxt.options.workspaceDir), "**/*")] : [], - ...modulePaths.map((m) => join(relativeWithDot(nuxt.options.buildDir, m), "runtime")) - ], - exclude: [ - ...nuxt.options.modulesDir.map((m) => relativeWithDot(nuxt.options.buildDir, m)), - ...modulePaths.map((m) => join(relativeWithDot(nuxt.options.buildDir, m), "runtime/server")), - // nitro generate output: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/core/nitro.ts#L186 - relativeWithDot(nuxt.options.buildDir, resolve(nuxt.options.rootDir, "dist")) - ] - }); - const aliases = { - ...nuxt.options.alias, - "#build": nuxt.options.buildDir - }; - const excludedAlias = [/^@vue\/.*$/]; - const basePath = tsConfig.compilerOptions.baseUrl ? resolve(nuxt.options.buildDir, tsConfig.compilerOptions.baseUrl) : nuxt.options.buildDir; - tsConfig.compilerOptions = tsConfig.compilerOptions || {}; - tsConfig.include = tsConfig.include || []; - for (const alias in aliases) { - if (excludedAlias.some((re) => re.test(alias))) { - continue; - } - let absolutePath = resolve(basePath, aliases[alias]); - let stats = await promises.stat(absolutePath).catch( - () => null - /* file does not exist */ - ); - if (!stats) { - const resolvedModule = await tryResolveModule(aliases[alias], nuxt.options.modulesDir); - if (resolvedModule) { - absolutePath = resolvedModule; - stats = await promises.stat(resolvedModule).catch(() => null); - } - } - const relativePath = relativeWithDot(nuxt.options.buildDir, absolutePath); - if (stats?.isDirectory()) { - tsConfig.compilerOptions.paths[alias] = [relativePath]; - tsConfig.compilerOptions.paths[`${alias}/*`] = [`${relativePath}/*`]; - if (!absolutePath.startsWith(rootDirWithSlash)) { - tsConfig.include.push(relativePath); - } - } else { - const path = stats?.isFile() ? relativePath.replace(/(?<=\w)\.\w+$/g, "") : aliases[alias]; - tsConfig.compilerOptions.paths[alias] = [path]; - if (!absolutePath.startsWith(rootDirWithSlash)) { - tsConfig.include.push(path); - } - } - } - const references = await Promise.all([ - ...nuxt.options.modules, - ...nuxt.options._modules - ].filter((f) => typeof f === "string").map(async (id) => ({ types: (await readPackageJSON(id, { url: nodeModulePaths }).catch(() => null))?.name || id }))); - const declarations = []; - await nuxt.callHook("prepare:types", { references, declarations, tsConfig }); - for (const alias in tsConfig.compilerOptions.paths) { - const paths = tsConfig.compilerOptions.paths[alias]; - tsConfig.compilerOptions.paths[alias] = await Promise.all(paths.map(async (path) => { - if (!isAbsolute(path)) { - return path; - } - const stats = await promises.stat(path).catch( - () => null - /* file does not exist */ - ); - return relativeWithDot(nuxt.options.buildDir, stats?.isFile() ? path.replace(/(?<=\w)\.\w+$/g, "") : path); - })); - } - tsConfig.include = [...new Set(tsConfig.include.map((p) => isAbsolute(p) ? relativeWithDot(nuxt.options.buildDir, p) : p))]; - tsConfig.exclude = [...new Set(tsConfig.exclude.map((p) => isAbsolute(p) ? relativeWithDot(nuxt.options.buildDir, p) : p))]; - const declaration = [ - ...references.map((ref) => { - if ("path" in ref && isAbsolute(ref.path)) { - ref.path = relative(nuxt.options.buildDir, ref.path); - } - return `/// `; - }), - ...declarations, - "", - "export {}", - "" - ].join("\n"); - return { - declaration, - tsConfig - }; -} -async function writeTypes(nuxt) { - const { tsConfig, declaration } = await _generateTypes(nuxt); - async function writeFile() { - const GeneratedBy = "// Generated by nuxi"; - const tsConfigPath = resolve(nuxt.options.buildDir, "tsconfig.json"); - await promises.mkdir(nuxt.options.buildDir, { recursive: true }); - await promises.writeFile(tsConfigPath, GeneratedBy + "\n" + JSON.stringify(tsConfig, null, 2)); - const declarationPath = resolve(nuxt.options.buildDir, "nuxt.d.ts"); - await promises.writeFile(declarationPath, GeneratedBy + "\n" + declaration); - } - nuxt.hook("builder:prepared", writeFile); - await writeFile(); -} -function renderAttrs(obj) { - return Object.entries(obj).map((e) => renderAttr(e[0], e[1])).join(" "); -} -function renderAttr(key, value) { - return value ? `${key}="${value}"` : ""; -} -function relativeWithDot(from, to) { - return relative(from, to).replace(/^([^.])/, "./$1") || "."; -} - -const loadKit = async (rootDir) => { - try { - const localKit = await tryResolveModule$1("@nuxt/kit", rootDir); - const rootURL = localKit ? rootDir : await tryResolveNuxt() || rootDir; - let kit = await importModule( - "@nuxt/kit", - rootURL - ); - if (!kit.writeTypes) { - kit = { ...kit, writeTypes: writeTypes }; - } - return kit; - } catch (e) { - if (e.toString().includes("Cannot find module '@nuxt/kit'")) { - throw new Error( - "nuxi requires `@nuxt/kit` to be installed in your project. Try installing `nuxt` v3 or `@nuxt/bridge` first." - ); - } - throw e; - } -}; -async function tryResolveNuxt() { - for (const pkg of ["nuxt-nightly", "nuxt3", "nuxt", "nuxt-edge"]) { - const path = await tryResolveModule$1(pkg); - if (path) { - return path; - } - } - return null; -} - -export { loadKit as l, readPackageJSON as r, writeTypes as w }; diff --git a/.pnpm-store/v3/files/28/3d66f5f41e9e37c8e26dd7d5b7d487a79e2868e80b82aa44328865755329aa9ab2af8433f0e260ecefeb47ef134ff22bbbf72d377648b2789a994c724b2637 b/.pnpm-store/v3/files/28/3d66f5f41e9e37c8e26dd7d5b7d487a79e2868e80b82aa44328865755329aa9ab2af8433f0e260ecefeb47ef134ff22bbbf72d377648b2789a994c724b2637 deleted file mode 100644 index 395d9548ff44826dec92d6fa5d632baebd170ee4..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/28/3d66f5f41e9e37c8e26dd7d5b7d487a79e2868e80b82aa44328865755329aa9ab2af8433f0e260ecefeb47ef134ff22bbbf72d377648b2789a994c724b2637 +++ /dev/null @@ -1,1898 +0,0 @@ -import { d as defineCommand, c as consola } from '../shared/nuxi.9edf0930.mjs'; -import { s as sharedArgs } from '../shared/nuxi.610c92ff.mjs'; -import 'node:util'; -import 'node:path'; -import 'node:process'; -import 'node:tty'; -import { a as getNuxtVersion, f as fetchModules, c as checkNuxtCompatibility } from '../shared/nuxi.34ba5283.mjs'; -import { u as upperFirst, k as kebabCase } from '../shared/nuxi.349af404.mjs'; -import { b as bold, c as cyan, g as gray, y as yellow, m as magenta, a as green } from '../shared/nuxi.d3241ca4.mjs'; -import 'node:url'; -import 'node:http'; -import 'node:https'; -import 'node:zlib'; -import 'node:stream'; -import 'node:buffer'; -import 'node:net'; -import 'node:fs'; -import '../shared/nuxi.4ac76f59.mjs'; -import '../shared/nuxi.53f5921c.mjs'; -import './satisfies.mjs'; -import '../shared/nuxi.2155838d.mjs'; -import '../shared/nuxi.cc8dd4a9.mjs'; -import '../shared/nuxi.5aaa4630.mjs'; -import 'node:module'; -import 'tty'; - -/** - * Fuse.js v7.0.0 - Lightweight fuzzy-search (http://fusejs.io) - * - * Copyright (c) 2023 Kiro Risk (http://kiro.me) - * All Rights Reserved. Apache Software License 2.0 - * - * http://www.apache.org/licenses/LICENSE-2.0 - */ - -function isArray(value) { - return !Array.isArray - ? getTag(value) === '[object Array]' - : Array.isArray(value) -} - -// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/baseToString.js -const INFINITY = 1 / 0; -function baseToString(value) { - // Exit early for strings to avoid a performance hit in some environments. - if (typeof value == 'string') { - return value - } - let result = value + ''; - return result == '0' && 1 / value == -INFINITY ? '-0' : result -} - -function toString(value) { - return value == null ? '' : baseToString(value) -} - -function isString(value) { - return typeof value === 'string' -} - -function isNumber(value) { - return typeof value === 'number' -} - -// Adapted from: https://github.com/lodash/lodash/blob/master/isBoolean.js -function isBoolean(value) { - return ( - value === true || - value === false || - (isObjectLike(value) && getTag(value) == '[object Boolean]') - ) -} - -function isObject(value) { - return typeof value === 'object' -} - -// Checks if `value` is object-like. -function isObjectLike(value) { - return isObject(value) && value !== null -} - -function isDefined(value) { - return value !== undefined && value !== null -} - -function isBlank(value) { - return !value.trim().length -} - -// Gets the `toStringTag` of `value`. -// Adapted from: https://github.com/lodash/lodash/blob/master/.internal/getTag.js -function getTag(value) { - return value == null - ? value === undefined - ? '[object Undefined]' - : '[object Null]' - : Object.prototype.toString.call(value) -} - -const EXTENDED_SEARCH_UNAVAILABLE = 'Extended search is not available'; - -const INCORRECT_INDEX_TYPE = "Incorrect 'index' type"; - -const LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = (key) => - `Invalid value for key ${key}`; - -const PATTERN_LENGTH_TOO_LARGE = (max) => - `Pattern length exceeds max of ${max}.`; - -const MISSING_KEY_PROPERTY = (name) => `Missing ${name} property in key`; - -const INVALID_KEY_WEIGHT_VALUE = (key) => - `Property 'weight' in key '${key}' must be a positive integer`; - -const hasOwn = Object.prototype.hasOwnProperty; - -class KeyStore { - constructor(keys) { - this._keys = []; - this._keyMap = {}; - - let totalWeight = 0; - - keys.forEach((key) => { - let obj = createKey(key); - - this._keys.push(obj); - this._keyMap[obj.id] = obj; - - totalWeight += obj.weight; - }); - - // Normalize weights so that their sum is equal to 1 - this._keys.forEach((key) => { - key.weight /= totalWeight; - }); - } - get(keyId) { - return this._keyMap[keyId] - } - keys() { - return this._keys - } - toJSON() { - return JSON.stringify(this._keys) - } -} - -function createKey(key) { - let path = null; - let id = null; - let src = null; - let weight = 1; - let getFn = null; - - if (isString(key) || isArray(key)) { - src = key; - path = createKeyPath(key); - id = createKeyId(key); - } else { - if (!hasOwn.call(key, 'name')) { - throw new Error(MISSING_KEY_PROPERTY('name')) - } - - const name = key.name; - src = name; - - if (hasOwn.call(key, 'weight')) { - weight = key.weight; - - if (weight <= 0) { - throw new Error(INVALID_KEY_WEIGHT_VALUE(name)) - } - } - - path = createKeyPath(name); - id = createKeyId(name); - getFn = key.getFn; - } - - return { path, id, weight, src, getFn } -} - -function createKeyPath(key) { - return isArray(key) ? key : key.split('.') -} - -function createKeyId(key) { - return isArray(key) ? key.join('.') : key -} - -function get(obj, path) { - let list = []; - let arr = false; - - const deepGet = (obj, path, index) => { - if (!isDefined(obj)) { - return - } - if (!path[index]) { - // If there's no path left, we've arrived at the object we care about. - list.push(obj); - } else { - let key = path[index]; - - const value = obj[key]; - - if (!isDefined(value)) { - return - } - - // If we're at the last value in the path, and if it's a string/number/bool, - // add it to the list - if ( - index === path.length - 1 && - (isString(value) || isNumber(value) || isBoolean(value)) - ) { - list.push(toString(value)); - } else if (isArray(value)) { - arr = true; - // Search each item in the array. - for (let i = 0, len = value.length; i < len; i += 1) { - deepGet(value[i], path, index + 1); - } - } else if (path.length) { - // An object. Recurse further. - deepGet(value, path, index + 1); - } - } - }; - - // Backwards compatibility (since path used to be a string) - deepGet(obj, isString(path) ? path.split('.') : path, 0); - - return arr ? list : list[0] -} - -const MatchOptions = { - // Whether the matches should be included in the result set. When `true`, each record in the result - // set will include the indices of the matched characters. - // These can consequently be used for highlighting purposes. - includeMatches: false, - // When `true`, the matching function will continue to the end of a search pattern even if - // a perfect match has already been located in the string. - findAllMatches: false, - // Minimum number of characters that must be matched before a result is considered a match - minMatchCharLength: 1 -}; - -const BasicOptions = { - // When `true`, the algorithm continues searching to the end of the input even if a perfect - // match is found before the end of the same input. - isCaseSensitive: false, - // When true, the matching function will continue to the end of a search pattern even if - includeScore: false, - // List of properties that will be searched. This also supports nested properties. - keys: [], - // Whether to sort the result list, by score - shouldSort: true, - // Default sort function: sort by ascending score, ascending index - sortFn: (a, b) => - a.score === b.score ? (a.idx < b.idx ? -1 : 1) : a.score < b.score ? -1 : 1 -}; - -const FuzzyOptions = { - // Approximately where in the text is the pattern expected to be found? - location: 0, - // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match - // (of both letters and location), a threshold of '1.0' would match anything. - threshold: 0.6, - // Determines how close the match must be to the fuzzy location (specified above). - // An exact letter match which is 'distance' characters away from the fuzzy location - // would score as a complete mismatch. A distance of '0' requires the match be at - // the exact location specified, a threshold of '1000' would require a perfect match - // to be within 800 characters of the fuzzy location to be found using a 0.8 threshold. - distance: 100 -}; - -const AdvancedOptions = { - // When `true`, it enables the use of unix-like search commands - useExtendedSearch: false, - // The get function to use when fetching an object's properties. - // The default will search nested paths *ie foo.bar.baz* - getFn: get, - // When `true`, search will ignore `location` and `distance`, so it won't matter - // where in the string the pattern appears. - // More info: https://fusejs.io/concepts/scoring-theory.html#fuzziness-score - ignoreLocation: false, - // When `true`, the calculation for the relevance score (used for sorting) will - // ignore the field-length norm. - // More info: https://fusejs.io/concepts/scoring-theory.html#field-length-norm - ignoreFieldNorm: false, - // The weight to determine how much field length norm effects scoring. - fieldNormWeight: 1 -}; - -var Config = { - ...BasicOptions, - ...MatchOptions, - ...FuzzyOptions, - ...AdvancedOptions -}; - -const SPACE = /[^ ]+/g; - -// Field-length norm: the shorter the field, the higher the weight. -// Set to 3 decimals to reduce index size. -function norm(weight = 1, mantissa = 3) { - const cache = new Map(); - const m = Math.pow(10, mantissa); - - return { - get(value) { - const numTokens = value.match(SPACE).length; - - if (cache.has(numTokens)) { - return cache.get(numTokens) - } - - // Default function is 1/sqrt(x), weight makes that variable - const norm = 1 / Math.pow(numTokens, 0.5 * weight); - - // In place of `toFixed(mantissa)`, for faster computation - const n = parseFloat(Math.round(norm * m) / m); - - cache.set(numTokens, n); - - return n - }, - clear() { - cache.clear(); - } - } -} - -class FuseIndex { - constructor({ - getFn = Config.getFn, - fieldNormWeight = Config.fieldNormWeight - } = {}) { - this.norm = norm(fieldNormWeight, 3); - this.getFn = getFn; - this.isCreated = false; - - this.setIndexRecords(); - } - setSources(docs = []) { - this.docs = docs; - } - setIndexRecords(records = []) { - this.records = records; - } - setKeys(keys = []) { - this.keys = keys; - this._keysMap = {}; - keys.forEach((key, idx) => { - this._keysMap[key.id] = idx; - }); - } - create() { - if (this.isCreated || !this.docs.length) { - return - } - - this.isCreated = true; - - // List is Array - if (isString(this.docs[0])) { - this.docs.forEach((doc, docIndex) => { - this._addString(doc, docIndex); - }); - } else { - // List is Array - this.docs.forEach((doc, docIndex) => { - this._addObject(doc, docIndex); - }); - } - - this.norm.clear(); - } - // Adds a doc to the end of the index - add(doc) { - const idx = this.size(); - - if (isString(doc)) { - this._addString(doc, idx); - } else { - this._addObject(doc, idx); - } - } - // Removes the doc at the specified index of the index - removeAt(idx) { - this.records.splice(idx, 1); - - // Change ref index of every subsquent doc - for (let i = idx, len = this.size(); i < len; i += 1) { - this.records[i].i -= 1; - } - } - getValueForItemAtKeyId(item, keyId) { - return item[this._keysMap[keyId]] - } - size() { - return this.records.length - } - _addString(doc, docIndex) { - if (!isDefined(doc) || isBlank(doc)) { - return - } - - let record = { - v: doc, - i: docIndex, - n: this.norm.get(doc) - }; - - this.records.push(record); - } - _addObject(doc, docIndex) { - let record = { i: docIndex, $: {} }; - - // Iterate over every key (i.e, path), and fetch the value at that key - this.keys.forEach((key, keyIndex) => { - let value = key.getFn ? key.getFn(doc) : this.getFn(doc, key.path); - - if (!isDefined(value)) { - return - } - - if (isArray(value)) { - let subRecords = []; - const stack = [{ nestedArrIndex: -1, value }]; - - while (stack.length) { - const { nestedArrIndex, value } = stack.pop(); - - if (!isDefined(value)) { - continue - } - - if (isString(value) && !isBlank(value)) { - let subRecord = { - v: value, - i: nestedArrIndex, - n: this.norm.get(value) - }; - - subRecords.push(subRecord); - } else if (isArray(value)) { - value.forEach((item, k) => { - stack.push({ - nestedArrIndex: k, - value: item - }); - }); - } else ; - } - record.$[keyIndex] = subRecords; - } else if (isString(value) && !isBlank(value)) { - let subRecord = { - v: value, - n: this.norm.get(value) - }; - - record.$[keyIndex] = subRecord; - } - }); - - this.records.push(record); - } - toJSON() { - return { - keys: this.keys, - records: this.records - } - } -} - -function createIndex( - keys, - docs, - { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {} -) { - const myIndex = new FuseIndex({ getFn, fieldNormWeight }); - myIndex.setKeys(keys.map(createKey)); - myIndex.setSources(docs); - myIndex.create(); - return myIndex -} - -function parseIndex( - data, - { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {} -) { - const { keys, records } = data; - const myIndex = new FuseIndex({ getFn, fieldNormWeight }); - myIndex.setKeys(keys); - myIndex.setIndexRecords(records); - return myIndex -} - -function computeScore$1( - pattern, - { - errors = 0, - currentLocation = 0, - expectedLocation = 0, - distance = Config.distance, - ignoreLocation = Config.ignoreLocation - } = {} -) { - const accuracy = errors / pattern.length; - - if (ignoreLocation) { - return accuracy - } - - const proximity = Math.abs(expectedLocation - currentLocation); - - if (!distance) { - // Dodge divide by zero error. - return proximity ? 1.0 : accuracy - } - - return accuracy + proximity / distance -} - -function convertMaskToIndices( - matchmask = [], - minMatchCharLength = Config.minMatchCharLength -) { - let indices = []; - let start = -1; - let end = -1; - let i = 0; - - for (let len = matchmask.length; i < len; i += 1) { - let match = matchmask[i]; - if (match && start === -1) { - start = i; - } else if (!match && start !== -1) { - end = i - 1; - if (end - start + 1 >= minMatchCharLength) { - indices.push([start, end]); - } - start = -1; - } - } - - // (i-1 - start) + 1 => i - start - if (matchmask[i - 1] && i - start >= minMatchCharLength) { - indices.push([start, i - 1]); - } - - return indices -} - -// Machine word size -const MAX_BITS = 32; - -function search$1( - text, - pattern, - patternAlphabet, - { - location = Config.location, - distance = Config.distance, - threshold = Config.threshold, - findAllMatches = Config.findAllMatches, - minMatchCharLength = Config.minMatchCharLength, - includeMatches = Config.includeMatches, - ignoreLocation = Config.ignoreLocation - } = {} -) { - if (pattern.length > MAX_BITS) { - throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS)) - } - - const patternLen = pattern.length; - // Set starting location at beginning text and initialize the alphabet. - const textLen = text.length; - // Handle the case when location > text.length - const expectedLocation = Math.max(0, Math.min(location, textLen)); - // Highest score beyond which we give up. - let currentThreshold = threshold; - // Is there a nearby exact match? (speedup) - let bestLocation = expectedLocation; - - // Performance: only computer matches when the minMatchCharLength > 1 - // OR if `includeMatches` is true. - const computeMatches = minMatchCharLength > 1 || includeMatches; - // A mask of the matches, used for building the indices - const matchMask = computeMatches ? Array(textLen) : []; - - let index; - - // Get all exact matches, here for speed up - while ((index = text.indexOf(pattern, bestLocation)) > -1) { - let score = computeScore$1(pattern, { - currentLocation: index, - expectedLocation, - distance, - ignoreLocation - }); - - currentThreshold = Math.min(score, currentThreshold); - bestLocation = index + patternLen; - - if (computeMatches) { - let i = 0; - while (i < patternLen) { - matchMask[index + i] = 1; - i += 1; - } - } - } - - // Reset the best location - bestLocation = -1; - - let lastBitArr = []; - let finalScore = 1; - let binMax = patternLen + textLen; - - const mask = 1 << (patternLen - 1); - - for (let i = 0; i < patternLen; i += 1) { - // Scan for the best match; each iteration allows for one more error. - // Run a binary search to determine how far from the match location we can stray - // at this error level. - let binMin = 0; - let binMid = binMax; - - while (binMin < binMid) { - const score = computeScore$1(pattern, { - errors: i, - currentLocation: expectedLocation + binMid, - expectedLocation, - distance, - ignoreLocation - }); - - if (score <= currentThreshold) { - binMin = binMid; - } else { - binMax = binMid; - } - - binMid = Math.floor((binMax - binMin) / 2 + binMin); - } - - // Use the result from this iteration as the maximum for the next. - binMax = binMid; - - let start = Math.max(1, expectedLocation - binMid + 1); - let finish = findAllMatches - ? textLen - : Math.min(expectedLocation + binMid, textLen) + patternLen; - - // Initialize the bit array - let bitArr = Array(finish + 2); - - bitArr[finish + 1] = (1 << i) - 1; - - for (let j = finish; j >= start; j -= 1) { - let currentLocation = j - 1; - let charMatch = patternAlphabet[text.charAt(currentLocation)]; - - if (computeMatches) { - // Speed up: quick bool to int conversion (i.e, `charMatch ? 1 : 0`) - matchMask[currentLocation] = +!!charMatch; - } - - // First pass: exact match - bitArr[j] = ((bitArr[j + 1] << 1) | 1) & charMatch; - - // Subsequent passes: fuzzy match - if (i) { - bitArr[j] |= - ((lastBitArr[j + 1] | lastBitArr[j]) << 1) | 1 | lastBitArr[j + 1]; - } - - if (bitArr[j] & mask) { - finalScore = computeScore$1(pattern, { - errors: i, - currentLocation, - expectedLocation, - distance, - ignoreLocation - }); - - // This match will almost certainly be better than any existing match. - // But check anyway. - if (finalScore <= currentThreshold) { - // Indeed it is - currentThreshold = finalScore; - bestLocation = currentLocation; - - // Already passed `loc`, downhill from here on in. - if (bestLocation <= expectedLocation) { - break - } - - // When passing `bestLocation`, don't exceed our current distance from `expectedLocation`. - start = Math.max(1, 2 * expectedLocation - bestLocation); - } - } - } - - // No hope for a (better) match at greater error levels. - const score = computeScore$1(pattern, { - errors: i + 1, - currentLocation: expectedLocation, - expectedLocation, - distance, - ignoreLocation - }); - - if (score > currentThreshold) { - break - } - - lastBitArr = bitArr; - } - - const result = { - isMatch: bestLocation >= 0, - // Count exact matches (those with a score of 0) to be "almost" exact - score: Math.max(0.001, finalScore) - }; - - if (computeMatches) { - const indices = convertMaskToIndices(matchMask, minMatchCharLength); - if (!indices.length) { - result.isMatch = false; - } else if (includeMatches) { - result.indices = indices; - } - } - - return result -} - -function createPatternAlphabet(pattern) { - let mask = {}; - - for (let i = 0, len = pattern.length; i < len; i += 1) { - const char = pattern.charAt(i); - mask[char] = (mask[char] || 0) | (1 << (len - i - 1)); - } - - return mask -} - -class BitapSearch { - constructor( - pattern, - { - location = Config.location, - threshold = Config.threshold, - distance = Config.distance, - includeMatches = Config.includeMatches, - findAllMatches = Config.findAllMatches, - minMatchCharLength = Config.minMatchCharLength, - isCaseSensitive = Config.isCaseSensitive, - ignoreLocation = Config.ignoreLocation - } = {} - ) { - this.options = { - location, - threshold, - distance, - includeMatches, - findAllMatches, - minMatchCharLength, - isCaseSensitive, - ignoreLocation - }; - - this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); - - this.chunks = []; - - if (!this.pattern.length) { - return - } - - const addChunk = (pattern, startIndex) => { - this.chunks.push({ - pattern, - alphabet: createPatternAlphabet(pattern), - startIndex - }); - }; - - const len = this.pattern.length; - - if (len > MAX_BITS) { - let i = 0; - const remainder = len % MAX_BITS; - const end = len - remainder; - - while (i < end) { - addChunk(this.pattern.substr(i, MAX_BITS), i); - i += MAX_BITS; - } - - if (remainder) { - const startIndex = len - MAX_BITS; - addChunk(this.pattern.substr(startIndex), startIndex); - } - } else { - addChunk(this.pattern, 0); - } - } - - searchIn(text) { - const { isCaseSensitive, includeMatches } = this.options; - - if (!isCaseSensitive) { - text = text.toLowerCase(); - } - - // Exact match - if (this.pattern === text) { - let result = { - isMatch: true, - score: 0 - }; - - if (includeMatches) { - result.indices = [[0, text.length - 1]]; - } - - return result - } - - // Otherwise, use Bitap algorithm - const { - location, - distance, - threshold, - findAllMatches, - minMatchCharLength, - ignoreLocation - } = this.options; - - let allIndices = []; - let totalScore = 0; - let hasMatches = false; - - this.chunks.forEach(({ pattern, alphabet, startIndex }) => { - const { isMatch, score, indices } = search$1(text, pattern, alphabet, { - location: location + startIndex, - distance, - threshold, - findAllMatches, - minMatchCharLength, - includeMatches, - ignoreLocation - }); - - if (isMatch) { - hasMatches = true; - } - - totalScore += score; - - if (isMatch && indices) { - allIndices = [...allIndices, ...indices]; - } - }); - - let result = { - isMatch: hasMatches, - score: hasMatches ? totalScore / this.chunks.length : 1 - }; - - if (hasMatches && includeMatches) { - result.indices = allIndices; - } - - return result - } -} - -class BaseMatch { - constructor(pattern) { - this.pattern = pattern; - } - static isMultiMatch(pattern) { - return getMatch(pattern, this.multiRegex) - } - static isSingleMatch(pattern) { - return getMatch(pattern, this.singleRegex) - } - search(/*text*/) {} -} - -function getMatch(pattern, exp) { - const matches = pattern.match(exp); - return matches ? matches[1] : null -} - -// Token: 'file - -class ExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'exact' - } - static get multiRegex() { - return /^="(.*)"$/ - } - static get singleRegex() { - return /^=(.*)$/ - } - search(text) { - const isMatch = text === this.pattern; - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, this.pattern.length - 1] - } - } -} - -// Token: !fire - -class InverseExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'inverse-exact' - } - static get multiRegex() { - return /^!"(.*)"$/ - } - static get singleRegex() { - return /^!(.*)$/ - } - search(text) { - const index = text.indexOf(this.pattern); - const isMatch = index === -1; - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, text.length - 1] - } - } -} - -// Token: ^file - -class PrefixExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'prefix-exact' - } - static get multiRegex() { - return /^\^"(.*)"$/ - } - static get singleRegex() { - return /^\^(.*)$/ - } - search(text) { - const isMatch = text.startsWith(this.pattern); - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, this.pattern.length - 1] - } - } -} - -// Token: !^fire - -class InversePrefixExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'inverse-prefix-exact' - } - static get multiRegex() { - return /^!\^"(.*)"$/ - } - static get singleRegex() { - return /^!\^(.*)$/ - } - search(text) { - const isMatch = !text.startsWith(this.pattern); - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, text.length - 1] - } - } -} - -// Token: .file$ - -class SuffixExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'suffix-exact' - } - static get multiRegex() { - return /^"(.*)"\$$/ - } - static get singleRegex() { - return /^(.*)\$$/ - } - search(text) { - const isMatch = text.endsWith(this.pattern); - - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [text.length - this.pattern.length, text.length - 1] - } - } -} - -// Token: !.file$ - -class InverseSuffixExactMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'inverse-suffix-exact' - } - static get multiRegex() { - return /^!"(.*)"\$$/ - } - static get singleRegex() { - return /^!(.*)\$$/ - } - search(text) { - const isMatch = !text.endsWith(this.pattern); - return { - isMatch, - score: isMatch ? 0 : 1, - indices: [0, text.length - 1] - } - } -} - -class FuzzyMatch extends BaseMatch { - constructor( - pattern, - { - location = Config.location, - threshold = Config.threshold, - distance = Config.distance, - includeMatches = Config.includeMatches, - findAllMatches = Config.findAllMatches, - minMatchCharLength = Config.minMatchCharLength, - isCaseSensitive = Config.isCaseSensitive, - ignoreLocation = Config.ignoreLocation - } = {} - ) { - super(pattern); - this._bitapSearch = new BitapSearch(pattern, { - location, - threshold, - distance, - includeMatches, - findAllMatches, - minMatchCharLength, - isCaseSensitive, - ignoreLocation - }); - } - static get type() { - return 'fuzzy' - } - static get multiRegex() { - return /^"(.*)"$/ - } - static get singleRegex() { - return /^(.*)$/ - } - search(text) { - return this._bitapSearch.searchIn(text) - } -} - -// Token: 'file - -class IncludeMatch extends BaseMatch { - constructor(pattern) { - super(pattern); - } - static get type() { - return 'include' - } - static get multiRegex() { - return /^'"(.*)"$/ - } - static get singleRegex() { - return /^'(.*)$/ - } - search(text) { - let location = 0; - let index; - - const indices = []; - const patternLen = this.pattern.length; - - // Get all exact matches - while ((index = text.indexOf(this.pattern, location)) > -1) { - location = index + patternLen; - indices.push([index, location - 1]); - } - - const isMatch = !!indices.length; - - return { - isMatch, - score: isMatch ? 0 : 1, - indices - } - } -} - -// ❗Order is important. DO NOT CHANGE. -const searchers = [ - ExactMatch, - IncludeMatch, - PrefixExactMatch, - InversePrefixExactMatch, - InverseSuffixExactMatch, - SuffixExactMatch, - InverseExactMatch, - FuzzyMatch -]; - -const searchersLen = searchers.length; - -// Regex to split by spaces, but keep anything in quotes together -const SPACE_RE = / +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/; -const OR_TOKEN = '|'; - -// Return a 2D array representation of the query, for simpler parsing. -// Example: -// "^core go$ | rb$ | py$ xy$" => [["^core", "go$"], ["rb$"], ["py$", "xy$"]] -function parseQuery(pattern, options = {}) { - return pattern.split(OR_TOKEN).map((item) => { - let query = item - .trim() - .split(SPACE_RE) - .filter((item) => item && !!item.trim()); - - let results = []; - for (let i = 0, len = query.length; i < len; i += 1) { - const queryItem = query[i]; - - // 1. Handle multiple query match (i.e, once that are quoted, like `"hello world"`) - let found = false; - let idx = -1; - while (!found && ++idx < searchersLen) { - const searcher = searchers[idx]; - let token = searcher.isMultiMatch(queryItem); - if (token) { - results.push(new searcher(token, options)); - found = true; - } - } - - if (found) { - continue - } - - // 2. Handle single query matches (i.e, once that are *not* quoted) - idx = -1; - while (++idx < searchersLen) { - const searcher = searchers[idx]; - let token = searcher.isSingleMatch(queryItem); - if (token) { - results.push(new searcher(token, options)); - break - } - } - } - - return results - }) -} - -// These extended matchers can return an array of matches, as opposed -// to a singl match -const MultiMatchSet = new Set([FuzzyMatch.type, IncludeMatch.type]); - -/** - * Command-like searching - * ====================== - * - * Given multiple search terms delimited by spaces.e.g. `^jscript .python$ ruby !java`, - * search in a given text. - * - * Search syntax: - * - * | Token | Match type | Description | - * | ----------- | -------------------------- | -------------------------------------- | - * | `jscript` | fuzzy-match | Items that fuzzy match `jscript` | - * | `=scheme` | exact-match | Items that are `scheme` | - * | `'python` | include-match | Items that include `python` | - * | `!ruby` | inverse-exact-match | Items that do not include `ruby` | - * | `^java` | prefix-exact-match | Items that start with `java` | - * | `!^earlang` | inverse-prefix-exact-match | Items that do not start with `earlang` | - * | `.js$` | suffix-exact-match | Items that end with `.js` | - * | `!.go$` | inverse-suffix-exact-match | Items that do not end with `.go` | - * - * A single pipe character acts as an OR operator. For example, the following - * query matches entries that start with `core` and end with either`go`, `rb`, - * or`py`. - * - * ``` - * ^core go$ | rb$ | py$ - * ``` - */ -class ExtendedSearch { - constructor( - pattern, - { - isCaseSensitive = Config.isCaseSensitive, - includeMatches = Config.includeMatches, - minMatchCharLength = Config.minMatchCharLength, - ignoreLocation = Config.ignoreLocation, - findAllMatches = Config.findAllMatches, - location = Config.location, - threshold = Config.threshold, - distance = Config.distance - } = {} - ) { - this.query = null; - this.options = { - isCaseSensitive, - includeMatches, - minMatchCharLength, - findAllMatches, - ignoreLocation, - location, - threshold, - distance - }; - - this.pattern = isCaseSensitive ? pattern : pattern.toLowerCase(); - this.query = parseQuery(this.pattern, this.options); - } - - static condition(_, options) { - return options.useExtendedSearch - } - - searchIn(text) { - const query = this.query; - - if (!query) { - return { - isMatch: false, - score: 1 - } - } - - const { includeMatches, isCaseSensitive } = this.options; - - text = isCaseSensitive ? text : text.toLowerCase(); - - let numMatches = 0; - let allIndices = []; - let totalScore = 0; - - // ORs - for (let i = 0, qLen = query.length; i < qLen; i += 1) { - const searchers = query[i]; - - // Reset indices - allIndices.length = 0; - numMatches = 0; - - // ANDs - for (let j = 0, pLen = searchers.length; j < pLen; j += 1) { - const searcher = searchers[j]; - const { isMatch, indices, score } = searcher.search(text); - - if (isMatch) { - numMatches += 1; - totalScore += score; - if (includeMatches) { - const type = searcher.constructor.type; - if (MultiMatchSet.has(type)) { - allIndices = [...allIndices, ...indices]; - } else { - allIndices.push(indices); - } - } - } else { - totalScore = 0; - numMatches = 0; - allIndices.length = 0; - break - } - } - - // OR condition, so if TRUE, return - if (numMatches) { - let result = { - isMatch: true, - score: totalScore / numMatches - }; - - if (includeMatches) { - result.indices = allIndices; - } - - return result - } - } - - // Nothing was matched - return { - isMatch: false, - score: 1 - } - } -} - -const registeredSearchers = []; - -function register(...args) { - registeredSearchers.push(...args); -} - -function createSearcher(pattern, options) { - for (let i = 0, len = registeredSearchers.length; i < len; i += 1) { - let searcherClass = registeredSearchers[i]; - if (searcherClass.condition(pattern, options)) { - return new searcherClass(pattern, options) - } - } - - return new BitapSearch(pattern, options) -} - -const LogicalOperator = { - AND: '$and', - OR: '$or' -}; - -const KeyType = { - PATH: '$path', - PATTERN: '$val' -}; - -const isExpression = (query) => - !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]); - -const isPath = (query) => !!query[KeyType.PATH]; - -const isLeaf = (query) => - !isArray(query) && isObject(query) && !isExpression(query); - -const convertToExplicit = (query) => ({ - [LogicalOperator.AND]: Object.keys(query).map((key) => ({ - [key]: query[key] - })) -}); - -// When `auto` is `true`, the parse function will infer and initialize and add -// the appropriate `Searcher` instance -function parse(query, options, { auto = true } = {}) { - const next = (query) => { - let keys = Object.keys(query); - - const isQueryPath = isPath(query); - - if (!isQueryPath && keys.length > 1 && !isExpression(query)) { - return next(convertToExplicit(query)) - } - - if (isLeaf(query)) { - const key = isQueryPath ? query[KeyType.PATH] : keys[0]; - - const pattern = isQueryPath ? query[KeyType.PATTERN] : query[key]; - - if (!isString(pattern)) { - throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key)) - } - - const obj = { - keyId: createKeyId(key), - pattern - }; - - if (auto) { - obj.searcher = createSearcher(pattern, options); - } - - return obj - } - - let node = { - children: [], - operator: keys[0] - }; - - keys.forEach((key) => { - const value = query[key]; - - if (isArray(value)) { - value.forEach((item) => { - node.children.push(next(item)); - }); - } - }); - - return node - }; - - if (!isExpression(query)) { - query = convertToExplicit(query); - } - - return next(query) -} - -// Practical scoring function -function computeScore( - results, - { ignoreFieldNorm = Config.ignoreFieldNorm } -) { - results.forEach((result) => { - let totalScore = 1; - - result.matches.forEach(({ key, norm, score }) => { - const weight = key ? key.weight : null; - - totalScore *= Math.pow( - score === 0 && weight ? Number.EPSILON : score, - (weight || 1) * (ignoreFieldNorm ? 1 : norm) - ); - }); - - result.score = totalScore; - }); -} - -function transformMatches(result, data) { - const matches = result.matches; - data.matches = []; - - if (!isDefined(matches)) { - return - } - - matches.forEach((match) => { - if (!isDefined(match.indices) || !match.indices.length) { - return - } - - const { indices, value } = match; - - let obj = { - indices, - value - }; - - if (match.key) { - obj.key = match.key.src; - } - - if (match.idx > -1) { - obj.refIndex = match.idx; - } - - data.matches.push(obj); - }); -} - -function transformScore(result, data) { - data.score = result.score; -} - -function format( - results, - docs, - { - includeMatches = Config.includeMatches, - includeScore = Config.includeScore - } = {} -) { - const transformers = []; - - if (includeMatches) transformers.push(transformMatches); - if (includeScore) transformers.push(transformScore); - - return results.map((result) => { - const { idx } = result; - - const data = { - item: docs[idx], - refIndex: idx - }; - - if (transformers.length) { - transformers.forEach((transformer) => { - transformer(result, data); - }); - } - - return data - }) -} - -class Fuse { - constructor(docs, options = {}, index) { - this.options = { ...Config, ...options }; - - if ( - this.options.useExtendedSearch && - !true - ) { - throw new Error(EXTENDED_SEARCH_UNAVAILABLE) - } - - this._keyStore = new KeyStore(this.options.keys); - - this.setCollection(docs, index); - } - - setCollection(docs, index) { - this._docs = docs; - - if (index && !(index instanceof FuseIndex)) { - throw new Error(INCORRECT_INDEX_TYPE) - } - - this._myIndex = - index || - createIndex(this.options.keys, this._docs, { - getFn: this.options.getFn, - fieldNormWeight: this.options.fieldNormWeight - }); - } - - add(doc) { - if (!isDefined(doc)) { - return - } - - this._docs.push(doc); - this._myIndex.add(doc); - } - - remove(predicate = (/* doc, idx */) => false) { - const results = []; - - for (let i = 0, len = this._docs.length; i < len; i += 1) { - const doc = this._docs[i]; - if (predicate(doc, i)) { - this.removeAt(i); - i -= 1; - len -= 1; - - results.push(doc); - } - } - - return results - } - - removeAt(idx) { - this._docs.splice(idx, 1); - this._myIndex.removeAt(idx); - } - - getIndex() { - return this._myIndex - } - - search(query, { limit = -1 } = {}) { - const { - includeMatches, - includeScore, - shouldSort, - sortFn, - ignoreFieldNorm - } = this.options; - - let results = isString(query) - ? isString(this._docs[0]) - ? this._searchStringList(query) - : this._searchObjectList(query) - : this._searchLogical(query); - - computeScore(results, { ignoreFieldNorm }); - - if (shouldSort) { - results.sort(sortFn); - } - - if (isNumber(limit) && limit > -1) { - results = results.slice(0, limit); - } - - return format(results, this._docs, { - includeMatches, - includeScore - }) - } - - _searchStringList(query) { - const searcher = createSearcher(query, this.options); - const { records } = this._myIndex; - const results = []; - - // Iterate over every string in the index - records.forEach(({ v: text, i: idx, n: norm }) => { - if (!isDefined(text)) { - return - } - - const { isMatch, score, indices } = searcher.searchIn(text); - - if (isMatch) { - results.push({ - item: text, - idx, - matches: [{ score, value: text, norm, indices }] - }); - } - }); - - return results - } - - _searchLogical(query) { - - const expression = parse(query, this.options); - - const evaluate = (node, item, idx) => { - if (!node.children) { - const { keyId, searcher } = node; - - const matches = this._findMatches({ - key: this._keyStore.get(keyId), - value: this._myIndex.getValueForItemAtKeyId(item, keyId), - searcher - }); - - if (matches && matches.length) { - return [ - { - idx, - item, - matches - } - ] - } - - return [] - } - - const res = []; - for (let i = 0, len = node.children.length; i < len; i += 1) { - const child = node.children[i]; - const result = evaluate(child, item, idx); - if (result.length) { - res.push(...result); - } else if (node.operator === LogicalOperator.AND) { - return [] - } - } - return res - }; - - const records = this._myIndex.records; - const resultMap = {}; - const results = []; - - records.forEach(({ $: item, i: idx }) => { - if (isDefined(item)) { - let expResults = evaluate(expression, item, idx); - - if (expResults.length) { - // Dedupe when adding - if (!resultMap[idx]) { - resultMap[idx] = { idx, item, matches: [] }; - results.push(resultMap[idx]); - } - expResults.forEach(({ matches }) => { - resultMap[idx].matches.push(...matches); - }); - } - } - }); - - return results - } - - _searchObjectList(query) { - const searcher = createSearcher(query, this.options); - const { keys, records } = this._myIndex; - const results = []; - - // List is Array - records.forEach(({ $: item, i: idx }) => { - if (!isDefined(item)) { - return - } - - let matches = []; - - // Iterate over every key (i.e, path), and fetch the value at that key - keys.forEach((key, keyIndex) => { - matches.push( - ...this._findMatches({ - key, - value: item[keyIndex], - searcher - }) - ); - }); - - if (matches.length) { - results.push({ - idx, - item, - matches - }); - } - }); - - return results - } - _findMatches({ key, value, searcher }) { - if (!isDefined(value)) { - return [] - } - - let matches = []; - - if (isArray(value)) { - value.forEach(({ v: text, i: idx, n: norm }) => { - if (!isDefined(text)) { - return - } - - const { isMatch, score, indices } = searcher.searchIn(text); - - if (isMatch) { - matches.push({ - score, - key, - value: text, - idx, - norm, - indices - }); - } - }); - } else { - const { v: text, n: norm } = value; - - const { isMatch, score, indices } = searcher.searchIn(text); - - if (isMatch) { - matches.push({ score, key, value: text, norm, indices }); - } - } - - return matches - } -} - -Fuse.version = '7.0.0'; -Fuse.createIndex = createIndex; -Fuse.parseIndex = parseIndex; -Fuse.config = Config; - -{ - Fuse.parseQuery = parse; -} - -{ - register(ExtendedSearch); -} - -const { format: formatNumber } = Intl.NumberFormat("en-GB", { - notation: "compact", - maximumFractionDigits: 1 -}); -const search = defineCommand({ - meta: { - name: "search", - description: "Search in Nuxt modules" - }, - args: { - ...sharedArgs, - query: { - type: "positional", - description: "keywords to search for", - required: true - }, - nuxtVersion: { - type: "string", - description: "Filter by Nuxt version and list compatible moduless only (auto detected by default)", - required: false - } - }, - async setup(ctx) { - const nuxtVersion = await getNuxtVersion(ctx.args.cwd || "."); - return findModuleByKeywords(ctx.args._.join(" "), nuxtVersion); - } -}); -async function findModuleByKeywords(query, nuxtVersion) { - const allModules = await fetchModules(); - const compatibleModules = allModules.filter( - (m) => checkNuxtCompatibility(m, nuxtVersion) - ); - const fuse = new Fuse(compatibleModules, { - threshold: 0.1, - keys: [ - { name: "name", weight: 1 }, - { name: "npm", weight: 1 }, - { name: "repo", weight: 1 }, - { name: "tags", weight: 1 }, - { name: "category", weight: 1 }, - { name: "description", weight: 0.5 }, - { name: "maintainers.name", weight: 0.5 }, - { name: "maintainers.github", weight: 0.5 } - ] - }); - const results = fuse.search(query).map((result) => { - const res = { - name: bold(result.item.name), - homepage: cyan(result.item.website), - compatibility: `nuxt: ${result.item.compatibility?.nuxt || "*"}`, - repository: gray(result.item.github), - description: gray(result.item.description), - package: gray(result.item.npm), - install: cyan(`npx nuxi module add ${result.item.name}`), - stars: yellow(formatNumber(result.item.stats.stars)), - monthlyDownloads: yellow(formatNumber(result.item.stats.downloads)) - }; - if (result.item.github === result.item.website) { - delete res.homepage; - } - if (result.item.name === result.item.npm) { - delete res.packageName; - } - return res; - }); - if (!results.length) { - consola.info( - `No Nuxt modules found matching query ${magenta(query)} for Nuxt ${cyan( - nuxtVersion - )}` - ); - return; - } - consola.success( - `Found ${results.length} Nuxt ${results.length > 1 ? "modules" : "module"} matching ${cyan(query)} ${nuxtVersion ? `for Nuxt ${cyan(nuxtVersion)}` : ""}: -` - ); - for (const foundModule of results) { - let maxLength = 0; - const entries = Object.entries(foundModule).map(([key, val]) => { - const label = upperFirst(kebabCase(key)).replace(/-/g, " "); - if (label.length > maxLength) { - maxLength = label.length; - } - return [label, val || "-"]; - }); - let infoStr = ""; - for (const [label, value] of entries) { - infoStr += bold(label === "Install" ? "\u2192 " : "- ") + green(label.padEnd(maxLength + 2)) + value + "\n"; - } - console.log(infoStr); - } -} - -export { search as default }; diff --git a/.pnpm-store/v3/files/2c/3697f9a13dc95e5357bc8f24b900d855f1d46a02911bed788a02550a85881cca04c3e03a9520f60bf7c7897e950088f77a3245908f4c0a38e808a620ec5075 b/.pnpm-store/v3/files/2c/3697f9a13dc95e5357bc8f24b900d855f1d46a02911bed788a02550a85881cca04c3e03a9520f60bf7c7897e950088f77a3245908f4c0a38e808a620ec5075 deleted file mode 100644 index aed4af230c0200849ec8cb84e1e56cb0ae4665d6..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/2c/3697f9a13dc95e5357bc8f24b900d855f1d46a02911bed788a02550a85881cca04c3e03a9520f60bf7c7897e950088f77a3245908f4c0a38e808a620ec5075 +++ /dev/null @@ -1,51 +0,0 @@ -import { existsSync } from 'node:fs'; -import { c as consola } from '../shared/nuxi.9edf0930.mjs'; -import 'node:util'; -import 'node:path'; -import 'node:process'; -import 'node:tty'; -import 'node:url'; - -async function startTunnel(opts) { - const { - installCloudflared, - startCloudflaredTunnel, - cloudflaredBinPath, - cloudflaredNotice - } = await import('./index7.mjs'); - const url = opts.url || `${opts.protocol || "http"}://${opts.hostname ?? "localhost"}:${opts.port ?? 3e3}`; - consola.start(`Starting cloudflared tunnel to ${url}`); - if (!existsSync(cloudflaredBinPath)) { - consola.log(cloudflaredNotice); - const canInstall = opts.acceptCloudflareNotice || process.env.UNTUN_ACCEPT_CLOUDFLARE_NOTICE || await consola.prompt( - `Do you agree with the above terms and wish to install the binary from GitHub?`, - { - type: "confirm" - } - ); - if (!canInstall) { - consola.fail("Skipping tunnel setup."); - return; - } - await installCloudflared(); - } - const args = [ - ["--url", url], - opts.verifyTLS ? void 0 : ["--no-tls-verify", ""] - ].filter(Boolean); - const tunnel = await startCloudflaredTunnel(Object.fromEntries(args)); - const cleanup = async () => { - await tunnel.stop(); - }; - for (const signal of ["SIGINT", "SIGUSR1", "SIGUSR2"]) { - process.once(signal, cleanup); - } - return { - getURL: async () => await tunnel.url, - close: async () => { - await cleanup(); - } - }; -} - -export { startTunnel }; diff --git a/.pnpm-store/v3/files/2d/ce6a69ca62e1588c5b9f8a4e14d8b64c1ef4fc2566b5a43dae6f5b743228b91f7697bb28254dafdcaf3141d8537e17505344b59db9f63db472dc3c089e15e7 b/.pnpm-store/v3/files/2d/ce6a69ca62e1588c5b9f8a4e14d8b64c1ef4fc2566b5a43dae6f5b743228b91f7697bb28254dafdcaf3141d8537e17505344b59db9f63db472dc3c089e15e7 deleted file mode 100644 index 248cd393ef72f0df47b76832d7fca8b649b0a090..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/2d/ce6a69ca62e1588c5b9f8a4e14d8b64c1ef4fc2566b5a43dae6f5b743228b91f7697bb28254dafdcaf3141d8537e17505344b59db9f63db472dc3c089e15e7 +++ /dev/null @@ -1,1202 +0,0 @@ -import Et from 'node:http'; -import https from 'node:https'; -import st from 'node:zlib'; -import me, { PassThrough, pipeline } from 'node:stream'; -import { Buffer as Buffer$1 } from 'node:buffer'; -import { promisify, deprecate, types } from 'node:util'; -import { format } from 'node:url'; -import { isIP } from 'node:net'; -import { statSync, promises, createReadStream } from 'node:fs'; -import { basename } from 'node:path'; -import { d as destr } from './nuxi.4ac76f59.mjs'; -import { b as withBase, c as withQuery } from './nuxi.53f5921c.mjs'; -import { a as semver$1, c as compare_1, r as reExports, b as requireRange, g as gt_1, d as requireComparator, e as satisfies_1, l as lt_1, f as lte_1, h as gte_1, i as constants$1, j as identifiers$1, k as eq_1, n as neq_1, m as cmp_1 } from '../chunks/satisfies.mjs'; -import { t as tryRequireModule } from './nuxi.5aaa4630.mjs'; - -var t$2=Object.defineProperty;var o$1=(e,l)=>t$2(e,"name",{value:l,configurable:!0});var n$1=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function f$1(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}o$1(f$1,"getDefaultExportFromCjs"); - -var Ps=Object.defineProperty;var n=(i,o)=>Ps(i,"name",{value:o,configurable:!0});var ui=(i,o,a)=>{if(!o.has(i))throw TypeError("Cannot "+a)};var O=(i,o,a)=>(ui(i,o,"read from private field"),a?a.call(i):o.get(i)),be=(i,o,a)=>{if(o.has(i))throw TypeError("Cannot add the same private member more than once");o instanceof WeakSet?o.add(i):o.set(i,a);},X=(i,o,a,u)=>(ui(i,o,"write to private field"),u?u.call(i,a):o.set(i,a),a);var Pe,Wt,bt,Cr,Ve,qt,Ot,zt,ee,It,Ne,He,Ft;function zs(i){if(!/^data:/i.test(i))throw new TypeError('`uri` does not appear to be a Data URI (must begin with "data:")');i=i.replace(/\r?\n/g,"");const o=i.indexOf(",");if(o===-1||o<=4)throw new TypeError("malformed data: URI");const a=i.substring(5,o).split(";");let u="",f=!1;const d=a[0]||"text/plain";let b=d;for(let D=1;D`Symbol(${e})`;function f(){}n(f,"noop");function d(e){return typeof e=="object"&&e!==null||typeof e=="function"}n(d,"typeIsObject");const b=f;function p(e,t){try{Object.defineProperty(e,"name",{value:t,configurable:!0});}catch{}}n(p,"setFunctionName");const E=Promise,w=Promise.prototype.then,D=Promise.reject.bind(E);function A(e){return new E(e)}n(A,"newPromise");function S(e){return A(t=>t(e))}n(S,"promiseResolvedWith");function m(e){return D(e)}n(m,"promiseRejectedWith");function R(e,t,r){return w.call(e,t,r)}n(R,"PerformPromiseThen");function q(e,t,r){R(R(e,t,r),void 0,b);}n(q,"uponPromise");function F(e,t){q(e,t);}n(F,"uponFulfillment");function Q(e,t){q(e,void 0,t);}n(Q,"uponRejection");function M(e,t,r){return R(e,t,r)}n(M,"transformPromiseWith");function ve(e){R(e,void 0,b);}n(ve,"setPromiseIsHandledToTrue");let z=n(e=>{if(typeof queueMicrotask=="function")z=queueMicrotask;else {const t=S(void 0);z=n(r=>R(t,r),"_queueMicrotask");}return z(e)},"_queueMicrotask");function j(e,t,r){if(typeof e!="function")throw new TypeError("Argument is not a function");return Function.prototype.apply.call(e,t,r)}n(j,"reflectCall");function I(e,t,r){try{return S(j(e,t,r))}catch(s){return m(s)}}n(I,"promiseCall");const mt=16384,cn=class cn{constructor(){this._cursor=0,this._size=0,this._front={_elements:[],_next:void 0},this._back=this._front,this._cursor=0,this._size=0;}get length(){return this._size}push(t){const r=this._back;let s=r;r._elements.length===mt-1&&(s={_elements:[],_next:void 0}),r._elements.push(t),s!==r&&(this._back=s,r._next=s),++this._size;}shift(){const t=this._front;let r=t;const s=this._cursor;let l=s+1;const c=t._elements,h=c[s];return l===mt&&(r=t._next,l=0),--this._size,this._cursor=l,t!==r&&(this._front=r),c[s]=void 0,h}forEach(t){let r=this._cursor,s=this._front,l=s._elements;for(;(r!==l.length||s._next!==void 0)&&!(r===l.length&&(s=s._next,l=s._elements,r=0,l.length===0));)t(l[r]),++r;}peek(){const t=this._front,r=this._cursor;return t._elements[r]}};n(cn,"SimpleQueue");let U=cn;const xn=u("[[AbortSteps]]"),Nn=u("[[ErrorSteps]]"),Ar=u("[[CancelSteps]]"),Br=u("[[PullSteps]]"),kr=u("[[ReleaseSteps]]");function Hn(e,t){e._ownerReadableStream=t,t._reader=e,t._state==="readable"?qr(e):t._state==="closed"?Fi(e):Vn(e,t._storedError);}n(Hn,"ReadableStreamReaderGenericInitialize");function Wr(e,t){const r=e._ownerReadableStream;return ie(r,t)}n(Wr,"ReadableStreamReaderGenericCancel");function ge(e){const t=e._ownerReadableStream;t._state==="readable"?Or(e,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")):ji(e,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")),t._readableStreamController[kr](),t._reader=void 0,e._ownerReadableStream=void 0;}n(ge,"ReadableStreamReaderGenericRelease");function jt(e){return new TypeError("Cannot "+e+" a stream using a released reader")}n(jt,"readerLockException");function qr(e){e._closedPromise=A((t,r)=>{e._closedPromise_resolve=t,e._closedPromise_reject=r;});}n(qr,"defaultReaderClosedPromiseInitialize");function Vn(e,t){qr(e),Or(e,t);}n(Vn,"defaultReaderClosedPromiseInitializeAsRejected");function Fi(e){qr(e),Qn(e);}n(Fi,"defaultReaderClosedPromiseInitializeAsResolved");function Or(e,t){e._closedPromise_reject!==void 0&&(ve(e._closedPromise),e._closedPromise_reject(t),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0);}n(Or,"defaultReaderClosedPromiseReject");function ji(e,t){Vn(e,t);}n(ji,"defaultReaderClosedPromiseResetToRejected");function Qn(e){e._closedPromise_resolve!==void 0&&(e._closedPromise_resolve(void 0),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0);}n(Qn,"defaultReaderClosedPromiseResolve");const Yn=Number.isFinite||function(e){return typeof e=="number"&&isFinite(e)},Li=Math.trunc||function(e){return e<0?Math.ceil(e):Math.floor(e)};function $i(e){return typeof e=="object"||typeof e=="function"}n($i,"isDictionary");function le(e,t){if(e!==void 0&&!$i(e))throw new TypeError(`${t} is not an object.`)}n(le,"assertDictionary");function Z(e,t){if(typeof e!="function")throw new TypeError(`${t} is not a function.`)}n(Z,"assertFunction");function Di(e){return typeof e=="object"&&e!==null||typeof e=="function"}n(Di,"isObject");function Gn(e,t){if(!Di(e))throw new TypeError(`${t} is not an object.`)}n(Gn,"assertObject");function _e(e,t,r){if(e===void 0)throw new TypeError(`Parameter ${t} is required in '${r}'.`)}n(_e,"assertRequiredArgument");function zr(e,t,r){if(e===void 0)throw new TypeError(`${t} is required in '${r}'.`)}n(zr,"assertRequiredField");function Ir(e){return Number(e)}n(Ir,"convertUnrestrictedDouble");function Zn(e){return e===0?0:e}n(Zn,"censorNegativeZero");function Mi(e){return Zn(Li(e))}n(Mi,"integerPart");function Fr(e,t){const s=Number.MAX_SAFE_INTEGER;let l=Number(e);if(l=Zn(l),!Yn(l))throw new TypeError(`${t} is not a finite number`);if(l=Mi(l),l<0||l>s)throw new TypeError(`${t} is outside the accepted range of 0 to ${s}, inclusive`);return !Yn(l)||l===0?0:l}n(Fr,"convertUnsignedLongLongWithEnforceRange");function jr(e,t){if(!We(e))throw new TypeError(`${t} is not a ReadableStream.`)}n(jr,"assertReadableStream");function Qe(e){return new fe(e)}n(Qe,"AcquireReadableStreamDefaultReader");function Kn(e,t){e._reader._readRequests.push(t);}n(Kn,"ReadableStreamAddReadRequest");function Lr(e,t,r){const l=e._reader._readRequests.shift();r?l._closeSteps():l._chunkSteps(t);}n(Lr,"ReadableStreamFulfillReadRequest");function Lt(e){return e._reader._readRequests.length}n(Lt,"ReadableStreamGetNumReadRequests");function Jn(e){const t=e._reader;return !(t===void 0||!Ee(t))}n(Jn,"ReadableStreamHasDefaultReader");const dn=class dn{constructor(t){if(_e(t,1,"ReadableStreamDefaultReader"),jr(t,"First parameter"),qe(t))throw new TypeError("This stream has already been locked for exclusive reading by another reader");Hn(this,t),this._readRequests=new U;}get closed(){return Ee(this)?this._closedPromise:m($t("closed"))}cancel(t=void 0){return Ee(this)?this._ownerReadableStream===void 0?m(jt("cancel")):Wr(this,t):m($t("cancel"))}read(){if(!Ee(this))return m($t("read"));if(this._ownerReadableStream===void 0)return m(jt("read from"));let t,r;const s=A((c,h)=>{t=c,r=h;});return yt(this,{_chunkSteps:c=>t({value:c,done:!1}),_closeSteps:()=>t({value:void 0,done:!0}),_errorSteps:c=>r(c)}),s}releaseLock(){if(!Ee(this))throw $t("releaseLock");this._ownerReadableStream!==void 0&&Ui(this);}};n(dn,"ReadableStreamDefaultReader");let fe=dn;Object.defineProperties(fe.prototype,{cancel:{enumerable:!0},read:{enumerable:!0},releaseLock:{enumerable:!0},closed:{enumerable:!0}}),p(fe.prototype.cancel,"cancel"),p(fe.prototype.read,"read"),p(fe.prototype.releaseLock,"releaseLock"),typeof u.toStringTag=="symbol"&&Object.defineProperty(fe.prototype,u.toStringTag,{value:"ReadableStreamDefaultReader",configurable:!0});function Ee(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_readRequests")?!1:e instanceof fe}n(Ee,"IsReadableStreamDefaultReader");function yt(e,t){const r=e._ownerReadableStream;r._disturbed=!0,r._state==="closed"?t._closeSteps():r._state==="errored"?t._errorSteps(r._storedError):r._readableStreamController[Br](t);}n(yt,"ReadableStreamDefaultReaderRead");function Ui(e){ge(e);const t=new TypeError("Reader was released");Xn(e,t);}n(Ui,"ReadableStreamDefaultReaderRelease");function Xn(e,t){const r=e._readRequests;e._readRequests=new U,r.forEach(s=>{s._errorSteps(t);});}n(Xn,"ReadableStreamDefaultReaderErrorReadRequests");function $t(e){return new TypeError(`ReadableStreamDefaultReader.prototype.${e} can only be used on a ReadableStreamDefaultReader`)}n($t,"defaultReaderBrandCheckException");const eo=Object.getPrototypeOf(Object.getPrototypeOf(async function*(){}).prototype),hn=class hn{constructor(t,r){this._ongoingPromise=void 0,this._isFinished=!1,this._reader=t,this._preventCancel=r;}next(){const t=n(()=>this._nextSteps(),"nextSteps");return this._ongoingPromise=this._ongoingPromise?M(this._ongoingPromise,t,t):t(),this._ongoingPromise}return(t){const r=n(()=>this._returnSteps(t),"returnSteps");return this._ongoingPromise?M(this._ongoingPromise,r,r):r()}_nextSteps(){if(this._isFinished)return Promise.resolve({value:void 0,done:!0});const t=this._reader;let r,s;const l=A((h,y)=>{r=h,s=y;});return yt(t,{_chunkSteps:h=>{this._ongoingPromise=void 0,z(()=>r({value:h,done:!1}));},_closeSteps:()=>{this._ongoingPromise=void 0,this._isFinished=!0,ge(t),r({value:void 0,done:!0});},_errorSteps:h=>{this._ongoingPromise=void 0,this._isFinished=!0,ge(t),s(h);}}),l}_returnSteps(t){if(this._isFinished)return Promise.resolve({value:t,done:!0});this._isFinished=!0;const r=this._reader;if(!this._preventCancel){const s=Wr(r,t);return ge(r),M(s,()=>({value:t,done:!0}))}return ge(r),S({value:t,done:!0})}};n(hn,"ReadableStreamAsyncIteratorImpl");let Dt=hn;const to={next(){return ro(this)?this._asyncIteratorImpl.next():m(no("next"))},return(e){return ro(this)?this._asyncIteratorImpl.return(e):m(no("return"))}};eo!==void 0&&Object.setPrototypeOf(to,eo);function xi(e,t){const r=Qe(e),s=new Dt(r,t),l=Object.create(to);return l._asyncIteratorImpl=s,l}n(xi,"AcquireReadableStreamAsyncIterator");function ro(e){if(!d(e)||!Object.prototype.hasOwnProperty.call(e,"_asyncIteratorImpl"))return !1;try{return e._asyncIteratorImpl instanceof Dt}catch{return !1}}n(ro,"IsReadableStreamAsyncIterator");function no(e){return new TypeError(`ReadableStreamAsyncIterator.${e} can only be used on a ReadableSteamAsyncIterator`)}n(no,"streamAsyncIteratorBrandCheckException");const oo=Number.isNaN||function(e){return e!==e};function gt(e){return e.slice()}n(gt,"CreateArrayFromList");function io(e,t,r,s,l){new Uint8Array(e).set(new Uint8Array(r,s,l),t);}n(io,"CopyDataBlockBytes");let Se=n(e=>(typeof e.transfer=="function"?Se=n(t=>t.transfer(),"TransferArrayBuffer"):typeof structuredClone=="function"?Se=n(t=>structuredClone(t,{transfer:[t]}),"TransferArrayBuffer"):Se=n(t=>t,"TransferArrayBuffer"),Se(e)),"TransferArrayBuffer"),Ae=n(e=>(typeof e.detached=="boolean"?Ae=n(t=>t.detached,"IsDetachedBuffer"):Ae=n(t=>t.byteLength===0,"IsDetachedBuffer"),Ae(e)),"IsDetachedBuffer");function ao(e,t,r){if(e.slice)return e.slice(t,r);const s=r-t,l=new ArrayBuffer(s);return io(l,0,e,t,s),l}n(ao,"ArrayBufferSlice");function Mt(e,t){const r=e[t];if(r!=null){if(typeof r!="function")throw new TypeError(`${String(t)} is not a function`);return r}}n(Mt,"GetMethod");function Ni(e){const t={[u.iterator]:()=>e.iterator},r=async function*(){return yield*t}(),s=r.next;return {iterator:r,nextMethod:s,done:!1}}n(Ni,"CreateAsyncFromSyncIterator");function so(e,t="sync",r){if(r===void 0)if(t==="async"){if(r=Mt(e,u.asyncIterator),r===void 0){const c=Mt(e,u.iterator),h=so(e,"sync",c);return Ni(h)}}else r=Mt(e,u.iterator);if(r===void 0)throw new TypeError("The object is not iterable");const s=j(r,e,[]);if(!d(s))throw new TypeError("The iterator method must return an object");const l=s.next;return {iterator:s,nextMethod:l,done:!1}}n(so,"GetIterator");function Hi(e){const t=j(e.nextMethod,e.iterator,[]);if(!d(t))throw new TypeError("The iterator.next() method must return an object");return t}n(Hi,"IteratorNext");function Vi(e){return !!e.done}n(Vi,"IteratorComplete");function Qi(e){return e.value}n(Qi,"IteratorValue");function Yi(e){return !(typeof e!="number"||oo(e)||e<0)}n(Yi,"IsNonNegativeNumber");function uo(e){const t=ao(e.buffer,e.byteOffset,e.byteOffset+e.byteLength);return new Uint8Array(t)}n(uo,"CloneAsUint8Array");function $r(e){const t=e._queue.shift();return e._queueTotalSize-=t.size,e._queueTotalSize<0&&(e._queueTotalSize=0),t.value}n($r,"DequeueValue");function Dr(e,t,r){if(!Yi(r)||r===1/0)throw new RangeError("Size must be a finite, non-NaN, non-negative number.");e._queue.push({value:t,size:r}),e._queueTotalSize+=r;}n(Dr,"EnqueueValueWithSize");function Gi(e){return e._queue.peek().value}n(Gi,"PeekQueueValue");function Be(e){e._queue=new U,e._queueTotalSize=0;}n(Be,"ResetQueue");function lo(e){return e===DataView}n(lo,"isDataViewConstructor");function Zi(e){return lo(e.constructor)}n(Zi,"isDataView");function Ki(e){return lo(e)?1:e.BYTES_PER_ELEMENT}n(Ki,"arrayBufferViewElementSize");const pn=class pn{constructor(){throw new TypeError("Illegal constructor")}get view(){if(!Mr(this))throw Vr("view");return this._view}respond(t){if(!Mr(this))throw Vr("respond");if(_e(t,1,"respond"),t=Fr(t,"First parameter"),this._associatedReadableByteStreamController===void 0)throw new TypeError("This BYOB request has been invalidated");if(Ae(this._view.buffer))throw new TypeError("The BYOB request's buffer has been detached and so cannot be used as a response");Ht(this._associatedReadableByteStreamController,t);}respondWithNewView(t){if(!Mr(this))throw Vr("respondWithNewView");if(_e(t,1,"respondWithNewView"),!ArrayBuffer.isView(t))throw new TypeError("You can only respond with array buffer views");if(this._associatedReadableByteStreamController===void 0)throw new TypeError("This BYOB request has been invalidated");if(Ae(t.buffer))throw new TypeError("The given view's buffer has been detached and so cannot be used as a response");Vt(this._associatedReadableByteStreamController,t);}};n(pn,"ReadableStreamBYOBRequest");let we=pn;Object.defineProperties(we.prototype,{respond:{enumerable:!0},respondWithNewView:{enumerable:!0},view:{enumerable:!0}}),p(we.prototype.respond,"respond"),p(we.prototype.respondWithNewView,"respondWithNewView"),typeof u.toStringTag=="symbol"&&Object.defineProperty(we.prototype,u.toStringTag,{value:"ReadableStreamBYOBRequest",configurable:!0});const bn=class bn{constructor(){throw new TypeError("Illegal constructor")}get byobRequest(){if(!ze(this))throw St("byobRequest");return Hr(this)}get desiredSize(){if(!ze(this))throw St("desiredSize");return So(this)}close(){if(!ze(this))throw St("close");if(this._closeRequested)throw new TypeError("The stream has already been closed; do not close it again!");const t=this._controlledReadableByteStream._state;if(t!=="readable")throw new TypeError(`The stream (in ${t} state) is not in the readable state and cannot be closed`);_t(this);}enqueue(t){if(!ze(this))throw St("enqueue");if(_e(t,1,"enqueue"),!ArrayBuffer.isView(t))throw new TypeError("chunk must be an array buffer view");if(t.byteLength===0)throw new TypeError("chunk must have non-zero byteLength");if(t.buffer.byteLength===0)throw new TypeError("chunk's buffer must have non-zero byteLength");if(this._closeRequested)throw new TypeError("stream is closed or draining");const r=this._controlledReadableByteStream._state;if(r!=="readable")throw new TypeError(`The stream (in ${r} state) is not in the readable state and cannot be enqueued to`);Nt(this,t);}error(t=void 0){if(!ze(this))throw St("error");K(this,t);}[Ar](t){fo(this),Be(this);const r=this._cancelAlgorithm(t);return xt(this),r}[Br](t){const r=this._controlledReadableByteStream;if(this._queueTotalSize>0){_o(this,t);return}const s=this._autoAllocateChunkSize;if(s!==void 0){let l;try{l=new ArrayBuffer(s);}catch(h){t._errorSteps(h);return}const c={buffer:l,bufferByteLength:s,byteOffset:0,byteLength:s,bytesFilled:0,minimumFill:1,elementSize:1,viewConstructor:Uint8Array,readerType:"default"};this._pendingPullIntos.push(c);}Kn(r,t),Ie(this);}[kr](){if(this._pendingPullIntos.length>0){const t=this._pendingPullIntos.peek();t.readerType="none",this._pendingPullIntos=new U,this._pendingPullIntos.push(t);}}};n(bn,"ReadableByteStreamController");let te=bn;Object.defineProperties(te.prototype,{close:{enumerable:!0},enqueue:{enumerable:!0},error:{enumerable:!0},byobRequest:{enumerable:!0},desiredSize:{enumerable:!0}}),p(te.prototype.close,"close"),p(te.prototype.enqueue,"enqueue"),p(te.prototype.error,"error"),typeof u.toStringTag=="symbol"&&Object.defineProperty(te.prototype,u.toStringTag,{value:"ReadableByteStreamController",configurable:!0});function ze(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_controlledReadableByteStream")?!1:e instanceof te}n(ze,"IsReadableByteStreamController");function Mr(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_associatedReadableByteStreamController")?!1:e instanceof we}n(Mr,"IsReadableStreamBYOBRequest");function Ie(e){if(!ra(e))return;if(e._pulling){e._pullAgain=!0;return}e._pulling=!0;const r=e._pullAlgorithm();q(r,()=>(e._pulling=!1,e._pullAgain&&(e._pullAgain=!1,Ie(e)),null),s=>(K(e,s),null));}n(Ie,"ReadableByteStreamControllerCallPullIfNeeded");function fo(e){xr(e),e._pendingPullIntos=new U;}n(fo,"ReadableByteStreamControllerClearPendingPullIntos");function Ur(e,t){let r=!1;e._state==="closed"&&(r=!0);const s=co(t);t.readerType==="default"?Lr(e,s,r):ua(e,s,r);}n(Ur,"ReadableByteStreamControllerCommitPullIntoDescriptor");function co(e){const t=e.bytesFilled,r=e.elementSize;return new e.viewConstructor(e.buffer,e.byteOffset,t/r)}n(co,"ReadableByteStreamControllerConvertPullIntoDescriptor");function Ut(e,t,r,s){e._queue.push({buffer:t,byteOffset:r,byteLength:s}),e._queueTotalSize+=s;}n(Ut,"ReadableByteStreamControllerEnqueueChunkToQueue");function ho(e,t,r,s){let l;try{l=ao(t,r,r+s);}catch(c){throw K(e,c),c}Ut(e,l,0,s);}n(ho,"ReadableByteStreamControllerEnqueueClonedChunkToQueue");function po(e,t){t.bytesFilled>0&&ho(e,t.buffer,t.byteOffset,t.bytesFilled),Ye(e);}n(po,"ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue");function bo(e,t){const r=Math.min(e._queueTotalSize,t.byteLength-t.bytesFilled),s=t.bytesFilled+r;let l=r,c=!1;const h=s%t.elementSize,y=s-h;y>=t.minimumFill&&(l=y-t.bytesFilled,c=!0);const T=e._queue;for(;l>0;){const g=T.peek(),C=Math.min(l,g.byteLength),P=t.byteOffset+t.bytesFilled;io(t.buffer,P,g.buffer,g.byteOffset,C),g.byteLength===C?T.shift():(g.byteOffset+=C,g.byteLength-=C),e._queueTotalSize-=C,mo(e,C,t),l-=C;}return c}n(bo,"ReadableByteStreamControllerFillPullIntoDescriptorFromQueue");function mo(e,t,r){r.bytesFilled+=t;}n(mo,"ReadableByteStreamControllerFillHeadPullIntoDescriptor");function yo(e){e._queueTotalSize===0&&e._closeRequested?(xt(e),vt(e._controlledReadableByteStream)):Ie(e);}n(yo,"ReadableByteStreamControllerHandleQueueDrain");function xr(e){e._byobRequest!==null&&(e._byobRequest._associatedReadableByteStreamController=void 0,e._byobRequest._view=null,e._byobRequest=null);}n(xr,"ReadableByteStreamControllerInvalidateBYOBRequest");function Nr(e){for(;e._pendingPullIntos.length>0;){if(e._queueTotalSize===0)return;const t=e._pendingPullIntos.peek();bo(e,t)&&(Ye(e),Ur(e._controlledReadableByteStream,t));}}n(Nr,"ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue");function Ji(e){const t=e._controlledReadableByteStream._reader;for(;t._readRequests.length>0;){if(e._queueTotalSize===0)return;const r=t._readRequests.shift();_o(e,r);}}n(Ji,"ReadableByteStreamControllerProcessReadRequestsUsingQueue");function Xi(e,t,r,s){const l=e._controlledReadableByteStream,c=t.constructor,h=Ki(c),{byteOffset:y,byteLength:T}=t,g=r*h;let C;try{C=Se(t.buffer);}catch(B){s._errorSteps(B);return}const P={buffer:C,bufferByteLength:C.byteLength,byteOffset:y,byteLength:T,bytesFilled:0,minimumFill:g,elementSize:h,viewConstructor:c,readerType:"byob"};if(e._pendingPullIntos.length>0){e._pendingPullIntos.push(P),To(l,s);return}if(l._state==="closed"){const B=new c(P.buffer,P.byteOffset,0);s._closeSteps(B);return}if(e._queueTotalSize>0){if(bo(e,P)){const B=co(P);yo(e),s._chunkSteps(B);return}if(e._closeRequested){const B=new TypeError("Insufficient bytes to fill elements in the given buffer");K(e,B),s._errorSteps(B);return}}e._pendingPullIntos.push(P),To(l,s),Ie(e);}n(Xi,"ReadableByteStreamControllerPullInto");function ea(e,t){t.readerType==="none"&&Ye(e);const r=e._controlledReadableByteStream;if(Qr(r))for(;Co(r)>0;){const s=Ye(e);Ur(r,s);}}n(ea,"ReadableByteStreamControllerRespondInClosedState");function ta(e,t,r){if(mo(e,t,r),r.readerType==="none"){po(e,r),Nr(e);return}if(r.bytesFilled0){const l=r.byteOffset+r.bytesFilled;ho(e,r.buffer,l-s,s);}r.bytesFilled-=s,Ur(e._controlledReadableByteStream,r),Nr(e);}n(ta,"ReadableByteStreamControllerRespondInReadableState");function go(e,t){const r=e._pendingPullIntos.peek();xr(e),e._controlledReadableByteStream._state==="closed"?ea(e,r):ta(e,t,r),Ie(e);}n(go,"ReadableByteStreamControllerRespondInternal");function Ye(e){return e._pendingPullIntos.shift()}n(Ye,"ReadableByteStreamControllerShiftPendingPullInto");function ra(e){const t=e._controlledReadableByteStream;return t._state!=="readable"||e._closeRequested||!e._started?!1:!!(Jn(t)&&Lt(t)>0||Qr(t)&&Co(t)>0||So(e)>0)}n(ra,"ReadableByteStreamControllerShouldCallPull");function xt(e){e._pullAlgorithm=void 0,e._cancelAlgorithm=void 0;}n(xt,"ReadableByteStreamControllerClearAlgorithms");function _t(e){const t=e._controlledReadableByteStream;if(!(e._closeRequested||t._state!=="readable")){if(e._queueTotalSize>0){e._closeRequested=!0;return}if(e._pendingPullIntos.length>0){const r=e._pendingPullIntos.peek();if(r.bytesFilled%r.elementSize!==0){const s=new TypeError("Insufficient bytes to fill elements in the given buffer");throw K(e,s),s}}xt(e),vt(t);}}n(_t,"ReadableByteStreamControllerClose");function Nt(e,t){const r=e._controlledReadableByteStream;if(e._closeRequested||r._state!=="readable")return;const{buffer:s,byteOffset:l,byteLength:c}=t;if(Ae(s))throw new TypeError("chunk's buffer is detached and so cannot be enqueued");const h=Se(s);if(e._pendingPullIntos.length>0){const y=e._pendingPullIntos.peek();if(Ae(y.buffer))throw new TypeError("The BYOB request's buffer has been detached and so cannot be filled with an enqueued chunk");xr(e),y.buffer=Se(y.buffer),y.readerType==="none"&&po(e,y);}if(Jn(r))if(Ji(e),Lt(r)===0)Ut(e,h,l,c);else {e._pendingPullIntos.length>0&&Ye(e);const y=new Uint8Array(h,l,c);Lr(r,y,!1);}else Qr(r)?(Ut(e,h,l,c),Nr(e)):Ut(e,h,l,c);Ie(e);}n(Nt,"ReadableByteStreamControllerEnqueue");function K(e,t){const r=e._controlledReadableByteStream;r._state==="readable"&&(fo(e),Be(e),xt(e),Yo(r,t));}n(K,"ReadableByteStreamControllerError");function _o(e,t){const r=e._queue.shift();e._queueTotalSize-=r.byteLength,yo(e);const s=new Uint8Array(r.buffer,r.byteOffset,r.byteLength);t._chunkSteps(s);}n(_o,"ReadableByteStreamControllerFillReadRequestFromQueue");function Hr(e){if(e._byobRequest===null&&e._pendingPullIntos.length>0){const t=e._pendingPullIntos.peek(),r=new Uint8Array(t.buffer,t.byteOffset+t.bytesFilled,t.byteLength-t.bytesFilled),s=Object.create(we.prototype);oa(s,e,r),e._byobRequest=s;}return e._byobRequest}n(Hr,"ReadableByteStreamControllerGetBYOBRequest");function So(e){const t=e._controlledReadableByteStream._state;return t==="errored"?null:t==="closed"?0:e._strategyHWM-e._queueTotalSize}n(So,"ReadableByteStreamControllerGetDesiredSize");function Ht(e,t){const r=e._pendingPullIntos.peek();if(e._controlledReadableByteStream._state==="closed"){if(t!==0)throw new TypeError("bytesWritten must be 0 when calling respond() on a closed stream")}else {if(t===0)throw new TypeError("bytesWritten must be greater than 0 when calling respond() on a readable stream");if(r.bytesFilled+t>r.byteLength)throw new RangeError("bytesWritten out of range")}r.buffer=Se(r.buffer),go(e,t);}n(Ht,"ReadableByteStreamControllerRespond");function Vt(e,t){const r=e._pendingPullIntos.peek();if(e._controlledReadableByteStream._state==="closed"){if(t.byteLength!==0)throw new TypeError("The view's length must be 0 when calling respondWithNewView() on a closed stream")}else if(t.byteLength===0)throw new TypeError("The view's length must be greater than 0 when calling respondWithNewView() on a readable stream");if(r.byteOffset+r.bytesFilled!==t.byteOffset)throw new RangeError("The region specified by view does not match byobRequest");if(r.bufferByteLength!==t.buffer.byteLength)throw new RangeError("The buffer of view has different capacity than byobRequest");if(r.bytesFilled+t.byteLength>r.byteLength)throw new RangeError("The region specified by view is larger than byobRequest");const l=t.byteLength;r.buffer=Se(t.buffer),go(e,l);}n(Vt,"ReadableByteStreamControllerRespondWithNewView");function wo(e,t,r,s,l,c,h){t._controlledReadableByteStream=e,t._pullAgain=!1,t._pulling=!1,t._byobRequest=null,t._queue=t._queueTotalSize=void 0,Be(t),t._closeRequested=!1,t._started=!1,t._strategyHWM=c,t._pullAlgorithm=s,t._cancelAlgorithm=l,t._autoAllocateChunkSize=h,t._pendingPullIntos=new U,e._readableStreamController=t;const y=r();q(S(y),()=>(t._started=!0,Ie(t),null),T=>(K(t,T),null));}n(wo,"SetUpReadableByteStreamController");function na(e,t,r){const s=Object.create(te.prototype);let l,c,h;t.start!==void 0?l=n(()=>t.start(s),"startAlgorithm"):l=n(()=>{},"startAlgorithm"),t.pull!==void 0?c=n(()=>t.pull(s),"pullAlgorithm"):c=n(()=>S(void 0),"pullAlgorithm"),t.cancel!==void 0?h=n(T=>t.cancel(T),"cancelAlgorithm"):h=n(()=>S(void 0),"cancelAlgorithm");const y=t.autoAllocateChunkSize;if(y===0)throw new TypeError("autoAllocateChunkSize must be greater than 0");wo(e,s,l,c,h,r,y);}n(na,"SetUpReadableByteStreamControllerFromUnderlyingSource");function oa(e,t,r){e._associatedReadableByteStreamController=t,e._view=r;}n(oa,"SetUpReadableStreamBYOBRequest");function Vr(e){return new TypeError(`ReadableStreamBYOBRequest.prototype.${e} can only be used on a ReadableStreamBYOBRequest`)}n(Vr,"byobRequestBrandCheckException");function St(e){return new TypeError(`ReadableByteStreamController.prototype.${e} can only be used on a ReadableByteStreamController`)}n(St,"byteStreamControllerBrandCheckException");function ia(e,t){le(e,t);const r=e?.mode;return {mode:r===void 0?void 0:aa(r,`${t} has member 'mode' that`)}}n(ia,"convertReaderOptions");function aa(e,t){if(e=`${e}`,e!=="byob")throw new TypeError(`${t} '${e}' is not a valid enumeration value for ReadableStreamReaderMode`);return e}n(aa,"convertReadableStreamReaderMode");function sa(e,t){var r;le(e,t);const s=(r=e?.min)!==null&&r!==void 0?r:1;return {min:Fr(s,`${t} has member 'min' that`)}}n(sa,"convertByobReadOptions");function Ro(e){return new ce(e)}n(Ro,"AcquireReadableStreamBYOBReader");function To(e,t){e._reader._readIntoRequests.push(t);}n(To,"ReadableStreamAddReadIntoRequest");function ua(e,t,r){const l=e._reader._readIntoRequests.shift();r?l._closeSteps(t):l._chunkSteps(t);}n(ua,"ReadableStreamFulfillReadIntoRequest");function Co(e){return e._reader._readIntoRequests.length}n(Co,"ReadableStreamGetNumReadIntoRequests");function Qr(e){const t=e._reader;return !(t===void 0||!Fe(t))}n(Qr,"ReadableStreamHasBYOBReader");const mn=class mn{constructor(t){if(_e(t,1,"ReadableStreamBYOBReader"),jr(t,"First parameter"),qe(t))throw new TypeError("This stream has already been locked for exclusive reading by another reader");if(!ze(t._readableStreamController))throw new TypeError("Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte source");Hn(this,t),this._readIntoRequests=new U;}get closed(){return Fe(this)?this._closedPromise:m(Qt("closed"))}cancel(t=void 0){return Fe(this)?this._ownerReadableStream===void 0?m(jt("cancel")):Wr(this,t):m(Qt("cancel"))}read(t,r={}){if(!Fe(this))return m(Qt("read"));if(!ArrayBuffer.isView(t))return m(new TypeError("view must be an array buffer view"));if(t.byteLength===0)return m(new TypeError("view must have non-zero byteLength"));if(t.buffer.byteLength===0)return m(new TypeError("view's buffer must have non-zero byteLength"));if(Ae(t.buffer))return m(new TypeError("view's buffer has been detached"));let s;try{s=sa(r,"options");}catch(g){return m(g)}const l=s.min;if(l===0)return m(new TypeError("options.min must be greater than 0"));if(Zi(t)){if(l>t.byteLength)return m(new RangeError("options.min must be less than or equal to view's byteLength"))}else if(l>t.length)return m(new RangeError("options.min must be less than or equal to view's length"));if(this._ownerReadableStream===void 0)return m(jt("read from"));let c,h;const y=A((g,C)=>{c=g,h=C;});return Po(this,t,l,{_chunkSteps:g=>c({value:g,done:!1}),_closeSteps:g=>c({value:g,done:!0}),_errorSteps:g=>h(g)}),y}releaseLock(){if(!Fe(this))throw Qt("releaseLock");this._ownerReadableStream!==void 0&&la(this);}};n(mn,"ReadableStreamBYOBReader");let ce=mn;Object.defineProperties(ce.prototype,{cancel:{enumerable:!0},read:{enumerable:!0},releaseLock:{enumerable:!0},closed:{enumerable:!0}}),p(ce.prototype.cancel,"cancel"),p(ce.prototype.read,"read"),p(ce.prototype.releaseLock,"releaseLock"),typeof u.toStringTag=="symbol"&&Object.defineProperty(ce.prototype,u.toStringTag,{value:"ReadableStreamBYOBReader",configurable:!0});function Fe(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_readIntoRequests")?!1:e instanceof ce}n(Fe,"IsReadableStreamBYOBReader");function Po(e,t,r,s){const l=e._ownerReadableStream;l._disturbed=!0,l._state==="errored"?s._errorSteps(l._storedError):Xi(l._readableStreamController,t,r,s);}n(Po,"ReadableStreamBYOBReaderRead");function la(e){ge(e);const t=new TypeError("Reader was released");vo(e,t);}n(la,"ReadableStreamBYOBReaderRelease");function vo(e,t){const r=e._readIntoRequests;e._readIntoRequests=new U,r.forEach(s=>{s._errorSteps(t);});}n(vo,"ReadableStreamBYOBReaderErrorReadIntoRequests");function Qt(e){return new TypeError(`ReadableStreamBYOBReader.prototype.${e} can only be used on a ReadableStreamBYOBReader`)}n(Qt,"byobReaderBrandCheckException");function wt(e,t){const{highWaterMark:r}=e;if(r===void 0)return t;if(oo(r)||r<0)throw new RangeError("Invalid highWaterMark");return r}n(wt,"ExtractHighWaterMark");function Yt(e){const{size:t}=e;return t||(()=>1)}n(Yt,"ExtractSizeAlgorithm");function Gt(e,t){le(e,t);const r=e?.highWaterMark,s=e?.size;return {highWaterMark:r===void 0?void 0:Ir(r),size:s===void 0?void 0:fa(s,`${t} has member 'size' that`)}}n(Gt,"convertQueuingStrategy");function fa(e,t){return Z(e,t),r=>Ir(e(r))}n(fa,"convertQueuingStrategySize");function ca(e,t){le(e,t);const r=e?.abort,s=e?.close,l=e?.start,c=e?.type,h=e?.write;return {abort:r===void 0?void 0:da(r,e,`${t} has member 'abort' that`),close:s===void 0?void 0:ha(s,e,`${t} has member 'close' that`),start:l===void 0?void 0:pa(l,e,`${t} has member 'start' that`),write:h===void 0?void 0:ba(h,e,`${t} has member 'write' that`),type:c}}n(ca,"convertUnderlyingSink");function da(e,t,r){return Z(e,r),s=>I(e,t,[s])}n(da,"convertUnderlyingSinkAbortCallback");function ha(e,t,r){return Z(e,r),()=>I(e,t,[])}n(ha,"convertUnderlyingSinkCloseCallback");function pa(e,t,r){return Z(e,r),s=>j(e,t,[s])}n(pa,"convertUnderlyingSinkStartCallback");function ba(e,t,r){return Z(e,r),(s,l)=>I(e,t,[s,l])}n(ba,"convertUnderlyingSinkWriteCallback");function Eo(e,t){if(!Ge(e))throw new TypeError(`${t} is not a WritableStream.`)}n(Eo,"assertWritableStream");function ma(e){if(typeof e!="object"||e===null)return !1;try{return typeof e.aborted=="boolean"}catch{return !1}}n(ma,"isAbortSignal");const ya=typeof AbortController=="function";function ga(){if(ya)return new AbortController}n(ga,"createAbortController");const yn=class yn{constructor(t={},r={}){t===void 0?t=null:Gn(t,"First parameter");const s=Gt(r,"Second parameter"),l=ca(t,"First parameter");if(Bo(this),l.type!==void 0)throw new RangeError("Invalid type is specified");const h=Yt(s),y=wt(s,1);qa(this,l,y,h);}get locked(){if(!Ge(this))throw er("locked");return Ze(this)}abort(t=void 0){return Ge(this)?Ze(this)?m(new TypeError("Cannot abort a stream that already has a writer")):Zt(this,t):m(er("abort"))}close(){return Ge(this)?Ze(this)?m(new TypeError("Cannot close a stream that already has a writer")):he(this)?m(new TypeError("Cannot close an already-closing stream")):ko(this):m(er("close"))}getWriter(){if(!Ge(this))throw er("getWriter");return Ao(this)}};n(yn,"WritableStream");let de=yn;Object.defineProperties(de.prototype,{abort:{enumerable:!0},close:{enumerable:!0},getWriter:{enumerable:!0},locked:{enumerable:!0}}),p(de.prototype.abort,"abort"),p(de.prototype.close,"close"),p(de.prototype.getWriter,"getWriter"),typeof u.toStringTag=="symbol"&&Object.defineProperty(de.prototype,u.toStringTag,{value:"WritableStream",configurable:!0});function Ao(e){return new re(e)}n(Ao,"AcquireWritableStreamDefaultWriter");function _a(e,t,r,s,l=1,c=()=>1){const h=Object.create(de.prototype);Bo(h);const y=Object.create(ke.prototype);return Fo(h,y,e,t,r,s,l,c),h}n(_a,"CreateWritableStream");function Bo(e){e._state="writable",e._storedError=void 0,e._writer=void 0,e._writableStreamController=void 0,e._writeRequests=new U,e._inFlightWriteRequest=void 0,e._closeRequest=void 0,e._inFlightCloseRequest=void 0,e._pendingAbortRequest=void 0,e._backpressure=!1;}n(Bo,"InitializeWritableStream");function Ge(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_writableStreamController")?!1:e instanceof de}n(Ge,"IsWritableStream");function Ze(e){return e._writer!==void 0}n(Ze,"IsWritableStreamLocked");function Zt(e,t){var r;if(e._state==="closed"||e._state==="errored")return S(void 0);e._writableStreamController._abortReason=t,(r=e._writableStreamController._abortController)===null||r===void 0||r.abort(t);const s=e._state;if(s==="closed"||s==="errored")return S(void 0);if(e._pendingAbortRequest!==void 0)return e._pendingAbortRequest._promise;let l=!1;s==="erroring"&&(l=!0,t=void 0);const c=A((h,y)=>{e._pendingAbortRequest={_promise:void 0,_resolve:h,_reject:y,_reason:t,_wasAlreadyErroring:l};});return e._pendingAbortRequest._promise=c,l||Gr(e,t),c}n(Zt,"WritableStreamAbort");function ko(e){const t=e._state;if(t==="closed"||t==="errored")return m(new TypeError(`The stream (in ${t} state) is not in the writable state and cannot be closed`));const r=A((l,c)=>{const h={_resolve:l,_reject:c};e._closeRequest=h;}),s=e._writer;return s!==void 0&&e._backpressure&&t==="writable"&&nn(s),Oa(e._writableStreamController),r}n(ko,"WritableStreamClose");function Sa(e){return A((r,s)=>{const l={_resolve:r,_reject:s};e._writeRequests.push(l);})}n(Sa,"WritableStreamAddWriteRequest");function Yr(e,t){if(e._state==="writable"){Gr(e,t);return}Zr(e);}n(Yr,"WritableStreamDealWithRejection");function Gr(e,t){const r=e._writableStreamController;e._state="erroring",e._storedError=t;const s=e._writer;s!==void 0&&qo(s,t),!Pa(e)&&r._started&&Zr(e);}n(Gr,"WritableStreamStartErroring");function Zr(e){e._state="errored",e._writableStreamController[Nn]();const t=e._storedError;if(e._writeRequests.forEach(l=>{l._reject(t);}),e._writeRequests=new U,e._pendingAbortRequest===void 0){Kt(e);return}const r=e._pendingAbortRequest;if(e._pendingAbortRequest=void 0,r._wasAlreadyErroring){r._reject(t),Kt(e);return}const s=e._writableStreamController[xn](r._reason);q(s,()=>(r._resolve(),Kt(e),null),l=>(r._reject(l),Kt(e),null));}n(Zr,"WritableStreamFinishErroring");function wa(e){e._inFlightWriteRequest._resolve(void 0),e._inFlightWriteRequest=void 0;}n(wa,"WritableStreamFinishInFlightWrite");function Ra(e,t){e._inFlightWriteRequest._reject(t),e._inFlightWriteRequest=void 0,Yr(e,t);}n(Ra,"WritableStreamFinishInFlightWriteWithError");function Ta(e){e._inFlightCloseRequest._resolve(void 0),e._inFlightCloseRequest=void 0,e._state==="erroring"&&(e._storedError=void 0,e._pendingAbortRequest!==void 0&&(e._pendingAbortRequest._resolve(),e._pendingAbortRequest=void 0)),e._state="closed";const r=e._writer;r!==void 0&&Do(r);}n(Ta,"WritableStreamFinishInFlightClose");function Ca(e,t){e._inFlightCloseRequest._reject(t),e._inFlightCloseRequest=void 0,e._pendingAbortRequest!==void 0&&(e._pendingAbortRequest._reject(t),e._pendingAbortRequest=void 0),Yr(e,t);}n(Ca,"WritableStreamFinishInFlightCloseWithError");function he(e){return !(e._closeRequest===void 0&&e._inFlightCloseRequest===void 0)}n(he,"WritableStreamCloseQueuedOrInFlight");function Pa(e){return !(e._inFlightWriteRequest===void 0&&e._inFlightCloseRequest===void 0)}n(Pa,"WritableStreamHasOperationMarkedInFlight");function va(e){e._inFlightCloseRequest=e._closeRequest,e._closeRequest=void 0;}n(va,"WritableStreamMarkCloseRequestInFlight");function Ea(e){e._inFlightWriteRequest=e._writeRequests.shift();}n(Ea,"WritableStreamMarkFirstWriteRequestInFlight");function Kt(e){e._closeRequest!==void 0&&(e._closeRequest._reject(e._storedError),e._closeRequest=void 0);const t=e._writer;t!==void 0&&tn(t,e._storedError);}n(Kt,"WritableStreamRejectCloseAndClosedPromiseIfNeeded");function Kr(e,t){const r=e._writer;r!==void 0&&t!==e._backpressure&&(t?Da(r):nn(r)),e._backpressure=t;}n(Kr,"WritableStreamUpdateBackpressure");const gn=class gn{constructor(t){if(_e(t,1,"WritableStreamDefaultWriter"),Eo(t,"First parameter"),Ze(t))throw new TypeError("This stream has already been locked for exclusive writing by another writer");this._ownerWritableStream=t,t._writer=this;const r=t._state;if(r==="writable")!he(t)&&t._backpressure?rr(this):Mo(this),tr(this);else if(r==="erroring")rn(this,t._storedError),tr(this);else if(r==="closed")Mo(this),La(this);else {const s=t._storedError;rn(this,s),$o(this,s);}}get closed(){return je(this)?this._closedPromise:m(Le("closed"))}get desiredSize(){if(!je(this))throw Le("desiredSize");if(this._ownerWritableStream===void 0)throw Tt("desiredSize");return Wa(this)}get ready(){return je(this)?this._readyPromise:m(Le("ready"))}abort(t=void 0){return je(this)?this._ownerWritableStream===void 0?m(Tt("abort")):Aa(this,t):m(Le("abort"))}close(){if(!je(this))return m(Le("close"));const t=this._ownerWritableStream;return t===void 0?m(Tt("close")):he(t)?m(new TypeError("Cannot close an already-closing stream")):Wo(this)}releaseLock(){if(!je(this))throw Le("releaseLock");this._ownerWritableStream!==void 0&&Oo(this);}write(t=void 0){return je(this)?this._ownerWritableStream===void 0?m(Tt("write to")):zo(this,t):m(Le("write"))}};n(gn,"WritableStreamDefaultWriter");let re=gn;Object.defineProperties(re.prototype,{abort:{enumerable:!0},close:{enumerable:!0},releaseLock:{enumerable:!0},write:{enumerable:!0},closed:{enumerable:!0},desiredSize:{enumerable:!0},ready:{enumerable:!0}}),p(re.prototype.abort,"abort"),p(re.prototype.close,"close"),p(re.prototype.releaseLock,"releaseLock"),p(re.prototype.write,"write"),typeof u.toStringTag=="symbol"&&Object.defineProperty(re.prototype,u.toStringTag,{value:"WritableStreamDefaultWriter",configurable:!0});function je(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_ownerWritableStream")?!1:e instanceof re}n(je,"IsWritableStreamDefaultWriter");function Aa(e,t){const r=e._ownerWritableStream;return Zt(r,t)}n(Aa,"WritableStreamDefaultWriterAbort");function Wo(e){const t=e._ownerWritableStream;return ko(t)}n(Wo,"WritableStreamDefaultWriterClose");function Ba(e){const t=e._ownerWritableStream,r=t._state;return he(t)||r==="closed"?S(void 0):r==="errored"?m(t._storedError):Wo(e)}n(Ba,"WritableStreamDefaultWriterCloseWithErrorPropagation");function ka(e,t){e._closedPromiseState==="pending"?tn(e,t):$a(e,t);}n(ka,"WritableStreamDefaultWriterEnsureClosedPromiseRejected");function qo(e,t){e._readyPromiseState==="pending"?Uo(e,t):Ma(e,t);}n(qo,"WritableStreamDefaultWriterEnsureReadyPromiseRejected");function Wa(e){const t=e._ownerWritableStream,r=t._state;return r==="errored"||r==="erroring"?null:r==="closed"?0:jo(t._writableStreamController)}n(Wa,"WritableStreamDefaultWriterGetDesiredSize");function Oo(e){const t=e._ownerWritableStream,r=new TypeError("Writer was released and can no longer be used to monitor the stream's closedness");qo(e,r),ka(e,r),t._writer=void 0,e._ownerWritableStream=void 0;}n(Oo,"WritableStreamDefaultWriterRelease");function zo(e,t){const r=e._ownerWritableStream,s=r._writableStreamController,l=za(s,t);if(r!==e._ownerWritableStream)return m(Tt("write to"));const c=r._state;if(c==="errored")return m(r._storedError);if(he(r)||c==="closed")return m(new TypeError("The stream is closing or closed and cannot be written to"));if(c==="erroring")return m(r._storedError);const h=Sa(r);return Ia(s,t,l),h}n(zo,"WritableStreamDefaultWriterWrite");const Io={},_n=class _n{constructor(){throw new TypeError("Illegal constructor")}get abortReason(){if(!Jr(this))throw en("abortReason");return this._abortReason}get signal(){if(!Jr(this))throw en("signal");if(this._abortController===void 0)throw new TypeError("WritableStreamDefaultController.prototype.signal is not supported");return this._abortController.signal}error(t=void 0){if(!Jr(this))throw en("error");this._controlledWritableStream._state==="writable"&&Lo(this,t);}[xn](t){const r=this._abortAlgorithm(t);return Jt(this),r}[Nn](){Be(this);}};n(_n,"WritableStreamDefaultController");let ke=_n;Object.defineProperties(ke.prototype,{abortReason:{enumerable:!0},signal:{enumerable:!0},error:{enumerable:!0}}),typeof u.toStringTag=="symbol"&&Object.defineProperty(ke.prototype,u.toStringTag,{value:"WritableStreamDefaultController",configurable:!0});function Jr(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_controlledWritableStream")?!1:e instanceof ke}n(Jr,"IsWritableStreamDefaultController");function Fo(e,t,r,s,l,c,h,y){t._controlledWritableStream=e,e._writableStreamController=t,t._queue=void 0,t._queueTotalSize=void 0,Be(t),t._abortReason=void 0,t._abortController=ga(),t._started=!1,t._strategySizeAlgorithm=y,t._strategyHWM=h,t._writeAlgorithm=s,t._closeAlgorithm=l,t._abortAlgorithm=c;const T=Xr(t);Kr(e,T);const g=r(),C=S(g);q(C,()=>(t._started=!0,Xt(t),null),P=>(t._started=!0,Yr(e,P),null));}n(Fo,"SetUpWritableStreamDefaultController");function qa(e,t,r,s){const l=Object.create(ke.prototype);let c,h,y,T;t.start!==void 0?c=n(()=>t.start(l),"startAlgorithm"):c=n(()=>{},"startAlgorithm"),t.write!==void 0?h=n(g=>t.write(g,l),"writeAlgorithm"):h=n(()=>S(void 0),"writeAlgorithm"),t.close!==void 0?y=n(()=>t.close(),"closeAlgorithm"):y=n(()=>S(void 0),"closeAlgorithm"),t.abort!==void 0?T=n(g=>t.abort(g),"abortAlgorithm"):T=n(()=>S(void 0),"abortAlgorithm"),Fo(e,l,c,h,y,T,r,s);}n(qa,"SetUpWritableStreamDefaultControllerFromUnderlyingSink");function Jt(e){e._writeAlgorithm=void 0,e._closeAlgorithm=void 0,e._abortAlgorithm=void 0,e._strategySizeAlgorithm=void 0;}n(Jt,"WritableStreamDefaultControllerClearAlgorithms");function Oa(e){Dr(e,Io,0),Xt(e);}n(Oa,"WritableStreamDefaultControllerClose");function za(e,t){try{return e._strategySizeAlgorithm(t)}catch(r){return Rt(e,r),1}}n(za,"WritableStreamDefaultControllerGetChunkSize");function jo(e){return e._strategyHWM-e._queueTotalSize}n(jo,"WritableStreamDefaultControllerGetDesiredSize");function Ia(e,t,r){try{Dr(e,t,r);}catch(l){Rt(e,l);return}const s=e._controlledWritableStream;if(!he(s)&&s._state==="writable"){const l=Xr(e);Kr(s,l);}Xt(e);}n(Ia,"WritableStreamDefaultControllerWrite");function Xt(e){const t=e._controlledWritableStream;if(!e._started||t._inFlightWriteRequest!==void 0)return;if(t._state==="erroring"){Zr(t);return}if(e._queue.length===0)return;const s=Gi(e);s===Io?Fa(e):ja(e,s);}n(Xt,"WritableStreamDefaultControllerAdvanceQueueIfNeeded");function Rt(e,t){e._controlledWritableStream._state==="writable"&&Lo(e,t);}n(Rt,"WritableStreamDefaultControllerErrorIfNeeded");function Fa(e){const t=e._controlledWritableStream;va(t),$r(e);const r=e._closeAlgorithm();Jt(e),q(r,()=>(Ta(t),null),s=>(Ca(t,s),null));}n(Fa,"WritableStreamDefaultControllerProcessClose");function ja(e,t){const r=e._controlledWritableStream;Ea(r);const s=e._writeAlgorithm(t);q(s,()=>{wa(r);const l=r._state;if($r(e),!he(r)&&l==="writable"){const c=Xr(e);Kr(r,c);}return Xt(e),null},l=>(r._state==="writable"&&Jt(e),Ra(r,l),null));}n(ja,"WritableStreamDefaultControllerProcessWrite");function Xr(e){return jo(e)<=0}n(Xr,"WritableStreamDefaultControllerGetBackpressure");function Lo(e,t){const r=e._controlledWritableStream;Jt(e),Gr(r,t);}n(Lo,"WritableStreamDefaultControllerError");function er(e){return new TypeError(`WritableStream.prototype.${e} can only be used on a WritableStream`)}n(er,"streamBrandCheckException$2");function en(e){return new TypeError(`WritableStreamDefaultController.prototype.${e} can only be used on a WritableStreamDefaultController`)}n(en,"defaultControllerBrandCheckException$2");function Le(e){return new TypeError(`WritableStreamDefaultWriter.prototype.${e} can only be used on a WritableStreamDefaultWriter`)}n(Le,"defaultWriterBrandCheckException");function Tt(e){return new TypeError("Cannot "+e+" a stream using a released writer")}n(Tt,"defaultWriterLockException");function tr(e){e._closedPromise=A((t,r)=>{e._closedPromise_resolve=t,e._closedPromise_reject=r,e._closedPromiseState="pending";});}n(tr,"defaultWriterClosedPromiseInitialize");function $o(e,t){tr(e),tn(e,t);}n($o,"defaultWriterClosedPromiseInitializeAsRejected");function La(e){tr(e),Do(e);}n(La,"defaultWriterClosedPromiseInitializeAsResolved");function tn(e,t){e._closedPromise_reject!==void 0&&(ve(e._closedPromise),e._closedPromise_reject(t),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0,e._closedPromiseState="rejected");}n(tn,"defaultWriterClosedPromiseReject");function $a(e,t){$o(e,t);}n($a,"defaultWriterClosedPromiseResetToRejected");function Do(e){e._closedPromise_resolve!==void 0&&(e._closedPromise_resolve(void 0),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0,e._closedPromiseState="resolved");}n(Do,"defaultWriterClosedPromiseResolve");function rr(e){e._readyPromise=A((t,r)=>{e._readyPromise_resolve=t,e._readyPromise_reject=r;}),e._readyPromiseState="pending";}n(rr,"defaultWriterReadyPromiseInitialize");function rn(e,t){rr(e),Uo(e,t);}n(rn,"defaultWriterReadyPromiseInitializeAsRejected");function Mo(e){rr(e),nn(e);}n(Mo,"defaultWriterReadyPromiseInitializeAsResolved");function Uo(e,t){e._readyPromise_reject!==void 0&&(ve(e._readyPromise),e._readyPromise_reject(t),e._readyPromise_resolve=void 0,e._readyPromise_reject=void 0,e._readyPromiseState="rejected");}n(Uo,"defaultWriterReadyPromiseReject");function Da(e){rr(e);}n(Da,"defaultWriterReadyPromiseReset");function Ma(e,t){rn(e,t);}n(Ma,"defaultWriterReadyPromiseResetToRejected");function nn(e){e._readyPromise_resolve!==void 0&&(e._readyPromise_resolve(void 0),e._readyPromise_resolve=void 0,e._readyPromise_reject=void 0,e._readyPromiseState="fulfilled");}n(nn,"defaultWriterReadyPromiseResolve");function Ua(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof n$1<"u")return n$1}n(Ua,"getGlobals");const on=Ua();function xa(e){if(!(typeof e=="function"||typeof e=="object")||e.name!=="DOMException")return !1;try{return new e,!0}catch{return !1}}n(xa,"isDOMExceptionConstructor");function Na(){const e=on?.DOMException;return xa(e)?e:void 0}n(Na,"getFromGlobal");function Ha(){const e=n(function(r,s){this.message=r||"",this.name=s||"Error",Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);},"DOMException");return p(e,"DOMException"),e.prototype=Object.create(Error.prototype),Object.defineProperty(e.prototype,"constructor",{value:e,writable:!0,configurable:!0}),e}n(Ha,"createPolyfill");const Va=Na()||Ha();function xo(e,t,r,s,l,c){const h=Qe(e),y=Ao(t);e._disturbed=!0;let T=!1,g=S(void 0);return A((C,P)=>{let B;if(c!==void 0){if(B=n(()=>{const _=c.reason!==void 0?c.reason:new Va("Aborted","AbortError"),v=[];s||v.push(()=>t._state==="writable"?Zt(t,_):S(void 0)),l||v.push(()=>e._state==="readable"?ie(e,_):S(void 0)),H(()=>Promise.all(v.map(k=>k())),!0,_);},"abortAlgorithm"),c.aborted){B();return}c.addEventListener("abort",B);}function ae(){return A((_,v)=>{function k(Y){Y?_():R(nt(),k,v);}n(k,"next"),k(!1);})}n(ae,"pipeLoop");function nt(){return T?S(!0):R(y._readyPromise,()=>A((_,v)=>{yt(h,{_chunkSteps:k=>{g=R(zo(y,k),void 0,f),_(!1);},_closeSteps:()=>_(!0),_errorSteps:v});}))}if(n(nt,"pipeStep"),Re(e,h._closedPromise,_=>(s?J(!0,_):H(()=>Zt(t,_),!0,_),null)),Re(t,y._closedPromise,_=>(l?J(!0,_):H(()=>ie(e,_),!0,_),null)),N(e,h._closedPromise,()=>(r?J():H(()=>Ba(y)),null)),he(t)||t._state==="closed"){const _=new TypeError("the destination writable stream closed before all data could be piped to it");l?J(!0,_):H(()=>ie(e,_),!0,_);}ve(ae());function Oe(){const _=g;return R(g,()=>_!==g?Oe():void 0)}n(Oe,"waitForWritesToFinish");function Re(_,v,k){_._state==="errored"?k(_._storedError):Q(v,k);}n(Re,"isOrBecomesErrored");function N(_,v,k){_._state==="closed"?k():F(v,k);}n(N,"isOrBecomesClosed");function H(_,v,k){if(T)return;T=!0,t._state==="writable"&&!he(t)?F(Oe(),Y):Y();function Y(){return q(_(),()=>Te(v,k),ot=>Te(!0,ot)),null}n(Y,"doTheRest");}n(H,"shutdownWithAction");function J(_,v){T||(T=!0,t._state==="writable"&&!he(t)?F(Oe(),()=>Te(_,v)):Te(_,v));}n(J,"shutdown");function Te(_,v){return Oo(y),ge(h),c!==void 0&&c.removeEventListener("abort",B),_?P(v):C(void 0),null}n(Te,"finalize");})}n(xo,"ReadableStreamPipeTo");const Sn=class Sn{constructor(){throw new TypeError("Illegal constructor")}get desiredSize(){if(!nr(this))throw ir("desiredSize");return an(this)}close(){if(!nr(this))throw ir("close");if(!Je(this))throw new TypeError("The stream is not in a state that permits close");$e(this);}enqueue(t=void 0){if(!nr(this))throw ir("enqueue");if(!Je(this))throw new TypeError("The stream is not in a state that permits enqueue");return Ke(this,t)}error(t=void 0){if(!nr(this))throw ir("error");oe(this,t);}[Ar](t){Be(this);const r=this._cancelAlgorithm(t);return or(this),r}[Br](t){const r=this._controlledReadableStream;if(this._queue.length>0){const s=$r(this);this._closeRequested&&this._queue.length===0?(or(this),vt(r)):Ct(this),t._chunkSteps(s);}else Kn(r,t),Ct(this);}[kr](){}};n(Sn,"ReadableStreamDefaultController");let ne=Sn;Object.defineProperties(ne.prototype,{close:{enumerable:!0},enqueue:{enumerable:!0},error:{enumerable:!0},desiredSize:{enumerable:!0}}),p(ne.prototype.close,"close"),p(ne.prototype.enqueue,"enqueue"),p(ne.prototype.error,"error"),typeof u.toStringTag=="symbol"&&Object.defineProperty(ne.prototype,u.toStringTag,{value:"ReadableStreamDefaultController",configurable:!0});function nr(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_controlledReadableStream")?!1:e instanceof ne}n(nr,"IsReadableStreamDefaultController");function Ct(e){if(!No(e))return;if(e._pulling){e._pullAgain=!0;return}e._pulling=!0;const r=e._pullAlgorithm();q(r,()=>(e._pulling=!1,e._pullAgain&&(e._pullAgain=!1,Ct(e)),null),s=>(oe(e,s),null));}n(Ct,"ReadableStreamDefaultControllerCallPullIfNeeded");function No(e){const t=e._controlledReadableStream;return !Je(e)||!e._started?!1:!!(qe(t)&&Lt(t)>0||an(e)>0)}n(No,"ReadableStreamDefaultControllerShouldCallPull");function or(e){e._pullAlgorithm=void 0,e._cancelAlgorithm=void 0,e._strategySizeAlgorithm=void 0;}n(or,"ReadableStreamDefaultControllerClearAlgorithms");function $e(e){if(!Je(e))return;const t=e._controlledReadableStream;e._closeRequested=!0,e._queue.length===0&&(or(e),vt(t));}n($e,"ReadableStreamDefaultControllerClose");function Ke(e,t){if(!Je(e))return;const r=e._controlledReadableStream;if(qe(r)&&Lt(r)>0)Lr(r,t,!1);else {let s;try{s=e._strategySizeAlgorithm(t);}catch(l){throw oe(e,l),l}try{Dr(e,t,s);}catch(l){throw oe(e,l),l}}Ct(e);}n(Ke,"ReadableStreamDefaultControllerEnqueue");function oe(e,t){const r=e._controlledReadableStream;r._state==="readable"&&(Be(e),or(e),Yo(r,t));}n(oe,"ReadableStreamDefaultControllerError");function an(e){const t=e._controlledReadableStream._state;return t==="errored"?null:t==="closed"?0:e._strategyHWM-e._queueTotalSize}n(an,"ReadableStreamDefaultControllerGetDesiredSize");function Qa(e){return !No(e)}n(Qa,"ReadableStreamDefaultControllerHasBackpressure");function Je(e){const t=e._controlledReadableStream._state;return !e._closeRequested&&t==="readable"}n(Je,"ReadableStreamDefaultControllerCanCloseOrEnqueue");function Ho(e,t,r,s,l,c,h){t._controlledReadableStream=e,t._queue=void 0,t._queueTotalSize=void 0,Be(t),t._started=!1,t._closeRequested=!1,t._pullAgain=!1,t._pulling=!1,t._strategySizeAlgorithm=h,t._strategyHWM=c,t._pullAlgorithm=s,t._cancelAlgorithm=l,e._readableStreamController=t;const y=r();q(S(y),()=>(t._started=!0,Ct(t),null),T=>(oe(t,T),null));}n(Ho,"SetUpReadableStreamDefaultController");function Ya(e,t,r,s){const l=Object.create(ne.prototype);let c,h,y;t.start!==void 0?c=n(()=>t.start(l),"startAlgorithm"):c=n(()=>{},"startAlgorithm"),t.pull!==void 0?h=n(()=>t.pull(l),"pullAlgorithm"):h=n(()=>S(void 0),"pullAlgorithm"),t.cancel!==void 0?y=n(T=>t.cancel(T),"cancelAlgorithm"):y=n(()=>S(void 0),"cancelAlgorithm"),Ho(e,l,c,h,y,r,s);}n(Ya,"SetUpReadableStreamDefaultControllerFromUnderlyingSource");function ir(e){return new TypeError(`ReadableStreamDefaultController.prototype.${e} can only be used on a ReadableStreamDefaultController`)}n(ir,"defaultControllerBrandCheckException$1");function Ga(e,t){return ze(e._readableStreamController)?Ka(e):Za(e)}n(Ga,"ReadableStreamTee");function Za(e,t){const r=Qe(e);let s=!1,l=!1,c=!1,h=!1,y,T,g,C,P;const B=A(N=>{P=N;});function ae(){return s?(l=!0,S(void 0)):(s=!0,yt(r,{_chunkSteps:H=>{z(()=>{l=!1;const J=H,Te=H;c||Ke(g._readableStreamController,J),h||Ke(C._readableStreamController,Te),s=!1,l&&ae();});},_closeSteps:()=>{s=!1,c||$e(g._readableStreamController),h||$e(C._readableStreamController),(!c||!h)&&P(void 0);},_errorSteps:()=>{s=!1;}}),S(void 0))}n(ae,"pullAlgorithm");function nt(N){if(c=!0,y=N,h){const H=gt([y,T]),J=ie(e,H);P(J);}return B}n(nt,"cancel1Algorithm");function Oe(N){if(h=!0,T=N,c){const H=gt([y,T]),J=ie(e,H);P(J);}return B}n(Oe,"cancel2Algorithm");function Re(){}return n(Re,"startAlgorithm"),g=Pt(Re,ae,nt),C=Pt(Re,ae,Oe),Q(r._closedPromise,N=>(oe(g._readableStreamController,N),oe(C._readableStreamController,N),(!c||!h)&&P(void 0),null)),[g,C]}n(Za,"ReadableStreamDefaultTee");function Ka(e){let t=Qe(e),r=!1,s=!1,l=!1,c=!1,h=!1,y,T,g,C,P;const B=A(_=>{P=_;});function ae(_){Q(_._closedPromise,v=>(_!==t||(K(g._readableStreamController,v),K(C._readableStreamController,v),(!c||!h)&&P(void 0)),null));}n(ae,"forwardReaderError");function nt(){Fe(t)&&(ge(t),t=Qe(e),ae(t)),yt(t,{_chunkSteps:v=>{z(()=>{s=!1,l=!1;const k=v;let Y=v;if(!c&&!h)try{Y=uo(v);}catch(ot){K(g._readableStreamController,ot),K(C._readableStreamController,ot),P(ie(e,ot));return}c||Nt(g._readableStreamController,k),h||Nt(C._readableStreamController,Y),r=!1,s?Re():l&&N();});},_closeSteps:()=>{r=!1,c||_t(g._readableStreamController),h||_t(C._readableStreamController),g._readableStreamController._pendingPullIntos.length>0&&Ht(g._readableStreamController,0),C._readableStreamController._pendingPullIntos.length>0&&Ht(C._readableStreamController,0),(!c||!h)&&P(void 0);},_errorSteps:()=>{r=!1;}});}n(nt,"pullWithDefaultReader");function Oe(_,v){Ee(t)&&(ge(t),t=Ro(e),ae(t));const k=v?C:g,Y=v?g:C;Po(t,_,1,{_chunkSteps:it=>{z(()=>{s=!1,l=!1;const at=v?h:c;if(v?c:h)at||Vt(k._readableStreamController,it);else {let si;try{si=uo(it);}catch(vn){K(k._readableStreamController,vn),K(Y._readableStreamController,vn),P(ie(e,vn));return}at||Vt(k._readableStreamController,it),Nt(Y._readableStreamController,si);}r=!1,s?Re():l&&N();});},_closeSteps:it=>{r=!1;const at=v?h:c,fr=v?c:h;at||_t(k._readableStreamController),fr||_t(Y._readableStreamController),it!==void 0&&(at||Vt(k._readableStreamController,it),!fr&&Y._readableStreamController._pendingPullIntos.length>0&&Ht(Y._readableStreamController,0)),(!at||!fr)&&P(void 0);},_errorSteps:()=>{r=!1;}});}n(Oe,"pullWithBYOBReader");function Re(){if(r)return s=!0,S(void 0);r=!0;const _=Hr(g._readableStreamController);return _===null?nt():Oe(_._view,!1),S(void 0)}n(Re,"pull1Algorithm");function N(){if(r)return l=!0,S(void 0);r=!0;const _=Hr(C._readableStreamController);return _===null?nt():Oe(_._view,!0),S(void 0)}n(N,"pull2Algorithm");function H(_){if(c=!0,y=_,h){const v=gt([y,T]),k=ie(e,v);P(k);}return B}n(H,"cancel1Algorithm");function J(_){if(h=!0,T=_,c){const v=gt([y,T]),k=ie(e,v);P(k);}return B}n(J,"cancel2Algorithm");function Te(){}return n(Te,"startAlgorithm"),g=Qo(Te,Re,H),C=Qo(Te,N,J),ae(t),[g,C]}n(Ka,"ReadableByteStreamTee");function Ja(e){return d(e)&&typeof e.getReader<"u"}n(Ja,"isReadableStreamLike");function Xa(e){return Ja(e)?ts(e.getReader()):es(e)}n(Xa,"ReadableStreamFrom");function es(e){let t;const r=so(e,"async"),s=f;function l(){let h;try{h=Hi(r);}catch(T){return m(T)}const y=S(h);return M(y,T=>{if(!d(T))throw new TypeError("The promise returned by the iterator.next() method must fulfill with an object");if(Vi(T))$e(t._readableStreamController);else {const C=Qi(T);Ke(t._readableStreamController,C);}})}n(l,"pullAlgorithm");function c(h){const y=r.iterator;let T;try{T=Mt(y,"return");}catch(P){return m(P)}if(T===void 0)return S(void 0);let g;try{g=j(T,y,[h]);}catch(P){return m(P)}const C=S(g);return M(C,P=>{if(!d(P))throw new TypeError("The promise returned by the iterator.return() method must fulfill with an object")})}return n(c,"cancelAlgorithm"),t=Pt(s,l,c,0),t}n(es,"ReadableStreamFromIterable");function ts(e){let t;const r=f;function s(){let c;try{c=e.read();}catch(h){return m(h)}return M(c,h=>{if(!d(h))throw new TypeError("The promise returned by the reader.read() method must fulfill with an object");if(h.done)$e(t._readableStreamController);else {const y=h.value;Ke(t._readableStreamController,y);}})}n(s,"pullAlgorithm");function l(c){try{return S(e.cancel(c))}catch(h){return m(h)}}return n(l,"cancelAlgorithm"),t=Pt(r,s,l,0),t}n(ts,"ReadableStreamFromDefaultReader");function rs(e,t){le(e,t);const r=e,s=r?.autoAllocateChunkSize,l=r?.cancel,c=r?.pull,h=r?.start,y=r?.type;return {autoAllocateChunkSize:s===void 0?void 0:Fr(s,`${t} has member 'autoAllocateChunkSize' that`),cancel:l===void 0?void 0:ns(l,r,`${t} has member 'cancel' that`),pull:c===void 0?void 0:os(c,r,`${t} has member 'pull' that`),start:h===void 0?void 0:is(h,r,`${t} has member 'start' that`),type:y===void 0?void 0:as(y,`${t} has member 'type' that`)}}n(rs,"convertUnderlyingDefaultOrByteSource");function ns(e,t,r){return Z(e,r),s=>I(e,t,[s])}n(ns,"convertUnderlyingSourceCancelCallback");function os(e,t,r){return Z(e,r),s=>I(e,t,[s])}n(os,"convertUnderlyingSourcePullCallback");function is(e,t,r){return Z(e,r),s=>j(e,t,[s])}n(is,"convertUnderlyingSourceStartCallback");function as(e,t){if(e=`${e}`,e!=="bytes")throw new TypeError(`${t} '${e}' is not a valid enumeration value for ReadableStreamType`);return e}n(as,"convertReadableStreamType");function ss(e,t){return le(e,t),{preventCancel:!!e?.preventCancel}}n(ss,"convertIteratorOptions");function Vo(e,t){le(e,t);const r=e?.preventAbort,s=e?.preventCancel,l=e?.preventClose,c=e?.signal;return c!==void 0&&us(c,`${t} has member 'signal' that`),{preventAbort:!!r,preventCancel:!!s,preventClose:!!l,signal:c}}n(Vo,"convertPipeOptions");function us(e,t){if(!ma(e))throw new TypeError(`${t} is not an AbortSignal.`)}n(us,"assertAbortSignal");function ls(e,t){le(e,t);const r=e?.readable;zr(r,"readable","ReadableWritablePair"),jr(r,`${t} has member 'readable' that`);const s=e?.writable;return zr(s,"writable","ReadableWritablePair"),Eo(s,`${t} has member 'writable' that`),{readable:r,writable:s}}n(ls,"convertReadableWritablePair");const wn=class wn{constructor(t={},r={}){t===void 0?t=null:Gn(t,"First parameter");const s=Gt(r,"Second parameter"),l=rs(t,"First parameter");if(sn(this),l.type==="bytes"){if(s.size!==void 0)throw new RangeError("The strategy for a byte stream cannot have a size function");const c=wt(s,0);na(this,l,c);}else {const c=Yt(s),h=wt(s,1);Ya(this,l,h,c);}}get locked(){if(!We(this))throw De("locked");return qe(this)}cancel(t=void 0){return We(this)?qe(this)?m(new TypeError("Cannot cancel a stream that already has a reader")):ie(this,t):m(De("cancel"))}getReader(t=void 0){if(!We(this))throw De("getReader");return ia(t,"First parameter").mode===void 0?Qe(this):Ro(this)}pipeThrough(t,r={}){if(!We(this))throw De("pipeThrough");_e(t,1,"pipeThrough");const s=ls(t,"First parameter"),l=Vo(r,"Second parameter");if(qe(this))throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream");if(Ze(s.writable))throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream");const c=xo(this,s.writable,l.preventClose,l.preventAbort,l.preventCancel,l.signal);return ve(c),s.readable}pipeTo(t,r={}){if(!We(this))return m(De("pipeTo"));if(t===void 0)return m("Parameter 1 is required in 'pipeTo'.");if(!Ge(t))return m(new TypeError("ReadableStream.prototype.pipeTo's first argument must be a WritableStream"));let s;try{s=Vo(r,"Second parameter");}catch(l){return m(l)}return qe(this)?m(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream")):Ze(t)?m(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream")):xo(this,t,s.preventClose,s.preventAbort,s.preventCancel,s.signal)}tee(){if(!We(this))throw De("tee");const t=Ga(this);return gt(t)}values(t=void 0){if(!We(this))throw De("values");const r=ss(t,"First parameter");return xi(this,r.preventCancel)}static from(t){return Xa(t)}};n(wn,"ReadableStream");let L=wn;Object.defineProperties(L,{from:{enumerable:!0}}),Object.defineProperties(L.prototype,{cancel:{enumerable:!0},getReader:{enumerable:!0},pipeThrough:{enumerable:!0},pipeTo:{enumerable:!0},tee:{enumerable:!0},values:{enumerable:!0},locked:{enumerable:!0}}),p(L.from,"from"),p(L.prototype.cancel,"cancel"),p(L.prototype.getReader,"getReader"),p(L.prototype.pipeThrough,"pipeThrough"),p(L.prototype.pipeTo,"pipeTo"),p(L.prototype.tee,"tee"),p(L.prototype.values,"values"),typeof u.toStringTag=="symbol"&&Object.defineProperty(L.prototype,u.toStringTag,{value:"ReadableStream",configurable:!0}),typeof u.asyncIterator=="symbol"&&Object.defineProperty(L.prototype,u.asyncIterator,{value:L.prototype.values,writable:!0,configurable:!0});function Pt(e,t,r,s=1,l=()=>1){const c=Object.create(L.prototype);sn(c);const h=Object.create(ne.prototype);return Ho(c,h,e,t,r,s,l),c}n(Pt,"CreateReadableStream");function Qo(e,t,r){const s=Object.create(L.prototype);sn(s);const l=Object.create(te.prototype);return wo(s,l,e,t,r,0,void 0),s}n(Qo,"CreateReadableByteStream");function sn(e){e._state="readable",e._reader=void 0,e._storedError=void 0,e._disturbed=!1;}n(sn,"InitializeReadableStream");function We(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_readableStreamController")?!1:e instanceof L}n(We,"IsReadableStream");function qe(e){return e._reader!==void 0}n(qe,"IsReadableStreamLocked");function ie(e,t){if(e._disturbed=!0,e._state==="closed")return S(void 0);if(e._state==="errored")return m(e._storedError);vt(e);const r=e._reader;if(r!==void 0&&Fe(r)){const l=r._readIntoRequests;r._readIntoRequests=new U,l.forEach(c=>{c._closeSteps(void 0);});}const s=e._readableStreamController[Ar](t);return M(s,f)}n(ie,"ReadableStreamCancel");function vt(e){e._state="closed";const t=e._reader;if(t!==void 0&&(Qn(t),Ee(t))){const r=t._readRequests;t._readRequests=new U,r.forEach(s=>{s._closeSteps();});}}n(vt,"ReadableStreamClose");function Yo(e,t){e._state="errored",e._storedError=t;const r=e._reader;r!==void 0&&(Or(r,t),Ee(r)?Xn(r,t):vo(r,t));}n(Yo,"ReadableStreamError");function De(e){return new TypeError(`ReadableStream.prototype.${e} can only be used on a ReadableStream`)}n(De,"streamBrandCheckException$1");function Go(e,t){le(e,t);const r=e?.highWaterMark;return zr(r,"highWaterMark","QueuingStrategyInit"),{highWaterMark:Ir(r)}}n(Go,"convertQueuingStrategyInit");const Zo=n(e=>e.byteLength,"byteLengthSizeFunction");p(Zo,"size");const Rn=class Rn{constructor(t){_e(t,1,"ByteLengthQueuingStrategy"),t=Go(t,"First parameter"),this._byteLengthQueuingStrategyHighWaterMark=t.highWaterMark;}get highWaterMark(){if(!Jo(this))throw Ko("highWaterMark");return this._byteLengthQueuingStrategyHighWaterMark}get size(){if(!Jo(this))throw Ko("size");return Zo}};n(Rn,"ByteLengthQueuingStrategy");let Xe=Rn;Object.defineProperties(Xe.prototype,{highWaterMark:{enumerable:!0},size:{enumerable:!0}}),typeof u.toStringTag=="symbol"&&Object.defineProperty(Xe.prototype,u.toStringTag,{value:"ByteLengthQueuingStrategy",configurable:!0});function Ko(e){return new TypeError(`ByteLengthQueuingStrategy.prototype.${e} can only be used on a ByteLengthQueuingStrategy`)}n(Ko,"byteLengthBrandCheckException");function Jo(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_byteLengthQueuingStrategyHighWaterMark")?!1:e instanceof Xe}n(Jo,"IsByteLengthQueuingStrategy");const Xo=n(()=>1,"countSizeFunction");p(Xo,"size");const Tn=class Tn{constructor(t){_e(t,1,"CountQueuingStrategy"),t=Go(t,"First parameter"),this._countQueuingStrategyHighWaterMark=t.highWaterMark;}get highWaterMark(){if(!ti(this))throw ei("highWaterMark");return this._countQueuingStrategyHighWaterMark}get size(){if(!ti(this))throw ei("size");return Xo}};n(Tn,"CountQueuingStrategy");let et=Tn;Object.defineProperties(et.prototype,{highWaterMark:{enumerable:!0},size:{enumerable:!0}}),typeof u.toStringTag=="symbol"&&Object.defineProperty(et.prototype,u.toStringTag,{value:"CountQueuingStrategy",configurable:!0});function ei(e){return new TypeError(`CountQueuingStrategy.prototype.${e} can only be used on a CountQueuingStrategy`)}n(ei,"countBrandCheckException");function ti(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_countQueuingStrategyHighWaterMark")?!1:e instanceof et}n(ti,"IsCountQueuingStrategy");function fs(e,t){le(e,t);const r=e?.cancel,s=e?.flush,l=e?.readableType,c=e?.start,h=e?.transform,y=e?.writableType;return {cancel:r===void 0?void 0:ps(r,e,`${t} has member 'cancel' that`),flush:s===void 0?void 0:cs(s,e,`${t} has member 'flush' that`),readableType:l,start:c===void 0?void 0:ds(c,e,`${t} has member 'start' that`),transform:h===void 0?void 0:hs(h,e,`${t} has member 'transform' that`),writableType:y}}n(fs,"convertTransformer");function cs(e,t,r){return Z(e,r),s=>I(e,t,[s])}n(cs,"convertTransformerFlushCallback");function ds(e,t,r){return Z(e,r),s=>j(e,t,[s])}n(ds,"convertTransformerStartCallback");function hs(e,t,r){return Z(e,r),(s,l)=>I(e,t,[s,l])}n(hs,"convertTransformerTransformCallback");function ps(e,t,r){return Z(e,r),s=>I(e,t,[s])}n(ps,"convertTransformerCancelCallback");const Cn=class Cn{constructor(t={},r={},s={}){t===void 0&&(t=null);const l=Gt(r,"Second parameter"),c=Gt(s,"Third parameter"),h=fs(t,"First parameter");if(h.readableType!==void 0)throw new RangeError("Invalid readableType specified");if(h.writableType!==void 0)throw new RangeError("Invalid writableType specified");const y=wt(c,0),T=Yt(c),g=wt(l,1),C=Yt(l);let P;const B=A(ae=>{P=ae;});bs(this,B,g,C,y,T),ys(this,h),h.start!==void 0?P(h.start(this._transformStreamController)):P(void 0);}get readable(){if(!ri(this))throw ai("readable");return this._readable}get writable(){if(!ri(this))throw ai("writable");return this._writable}};n(Cn,"TransformStream");let tt=Cn;Object.defineProperties(tt.prototype,{readable:{enumerable:!0},writable:{enumerable:!0}}),typeof u.toStringTag=="symbol"&&Object.defineProperty(tt.prototype,u.toStringTag,{value:"TransformStream",configurable:!0});function bs(e,t,r,s,l,c){function h(){return t}n(h,"startAlgorithm");function y(B){return Ss(e,B)}n(y,"writeAlgorithm");function T(B){return ws(e,B)}n(T,"abortAlgorithm");function g(){return Rs(e)}n(g,"closeAlgorithm"),e._writable=_a(h,y,g,T,r,s);function C(){return Ts(e)}n(C,"pullAlgorithm");function P(B){return Cs(e,B)}n(P,"cancelAlgorithm"),e._readable=Pt(h,C,P,l,c),e._backpressure=void 0,e._backpressureChangePromise=void 0,e._backpressureChangePromise_resolve=void 0,ar(e,!0),e._transformStreamController=void 0;}n(bs,"InitializeTransformStream");function ri(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_transformStreamController")?!1:e instanceof tt}n(ri,"IsTransformStream");function ni(e,t){oe(e._readable._readableStreamController,t),un(e,t);}n(ni,"TransformStreamError");function un(e,t){ur(e._transformStreamController),Rt(e._writable._writableStreamController,t),ln(e);}n(un,"TransformStreamErrorWritableAndUnblockWrite");function ln(e){e._backpressure&&ar(e,!1);}n(ln,"TransformStreamUnblockWrite");function ar(e,t){e._backpressureChangePromise!==void 0&&e._backpressureChangePromise_resolve(),e._backpressureChangePromise=A(r=>{e._backpressureChangePromise_resolve=r;}),e._backpressure=t;}n(ar,"TransformStreamSetBackpressure");const Pn=class Pn{constructor(){throw new TypeError("Illegal constructor")}get desiredSize(){if(!sr(this))throw lr("desiredSize");const t=this._controlledTransformStream._readable._readableStreamController;return an(t)}enqueue(t=void 0){if(!sr(this))throw lr("enqueue");oi(this,t);}error(t=void 0){if(!sr(this))throw lr("error");gs(this,t);}terminate(){if(!sr(this))throw lr("terminate");_s(this);}};n(Pn,"TransformStreamDefaultController");let pe=Pn;Object.defineProperties(pe.prototype,{enqueue:{enumerable:!0},error:{enumerable:!0},terminate:{enumerable:!0},desiredSize:{enumerable:!0}}),p(pe.prototype.enqueue,"enqueue"),p(pe.prototype.error,"error"),p(pe.prototype.terminate,"terminate"),typeof u.toStringTag=="symbol"&&Object.defineProperty(pe.prototype,u.toStringTag,{value:"TransformStreamDefaultController",configurable:!0});function sr(e){return !d(e)||!Object.prototype.hasOwnProperty.call(e,"_controlledTransformStream")?!1:e instanceof pe}n(sr,"IsTransformStreamDefaultController");function ms(e,t,r,s,l){t._controlledTransformStream=e,e._transformStreamController=t,t._transformAlgorithm=r,t._flushAlgorithm=s,t._cancelAlgorithm=l,t._finishPromise=void 0,t._finishPromise_resolve=void 0,t._finishPromise_reject=void 0;}n(ms,"SetUpTransformStreamDefaultController");function ys(e,t){const r=Object.create(pe.prototype);let s,l,c;t.transform!==void 0?s=n(h=>t.transform(h,r),"transformAlgorithm"):s=n(h=>{try{return oi(r,h),S(void 0)}catch(y){return m(y)}},"transformAlgorithm"),t.flush!==void 0?l=n(()=>t.flush(r),"flushAlgorithm"):l=n(()=>S(void 0),"flushAlgorithm"),t.cancel!==void 0?c=n(h=>t.cancel(h),"cancelAlgorithm"):c=n(()=>S(void 0),"cancelAlgorithm"),ms(e,r,s,l,c);}n(ys,"SetUpTransformStreamDefaultControllerFromTransformer");function ur(e){e._transformAlgorithm=void 0,e._flushAlgorithm=void 0,e._cancelAlgorithm=void 0;}n(ur,"TransformStreamDefaultControllerClearAlgorithms");function oi(e,t){const r=e._controlledTransformStream,s=r._readable._readableStreamController;if(!Je(s))throw new TypeError("Readable side is not in a state that permits enqueue");try{Ke(s,t);}catch(c){throw un(r,c),r._readable._storedError}Qa(s)!==r._backpressure&&ar(r,!0);}n(oi,"TransformStreamDefaultControllerEnqueue");function gs(e,t){ni(e._controlledTransformStream,t);}n(gs,"TransformStreamDefaultControllerError");function ii(e,t){const r=e._transformAlgorithm(t);return M(r,void 0,s=>{throw ni(e._controlledTransformStream,s),s})}n(ii,"TransformStreamDefaultControllerPerformTransform");function _s(e){const t=e._controlledTransformStream,r=t._readable._readableStreamController;$e(r);const s=new TypeError("TransformStream terminated");un(t,s);}n(_s,"TransformStreamDefaultControllerTerminate");function Ss(e,t){const r=e._transformStreamController;if(e._backpressure){const s=e._backpressureChangePromise;return M(s,()=>{const l=e._writable;if(l._state==="erroring")throw l._storedError;return ii(r,t)})}return ii(r,t)}n(Ss,"TransformStreamDefaultSinkWriteAlgorithm");function ws(e,t){const r=e._transformStreamController;if(r._finishPromise!==void 0)return r._finishPromise;const s=e._readable;r._finishPromise=A((c,h)=>{r._finishPromise_resolve=c,r._finishPromise_reject=h;});const l=r._cancelAlgorithm(t);return ur(r),q(l,()=>(s._state==="errored"?rt(r,s._storedError):(oe(s._readableStreamController,t),fn(r)),null),c=>(oe(s._readableStreamController,c),rt(r,c),null)),r._finishPromise}n(ws,"TransformStreamDefaultSinkAbortAlgorithm");function Rs(e){const t=e._transformStreamController;if(t._finishPromise!==void 0)return t._finishPromise;const r=e._readable;t._finishPromise=A((l,c)=>{t._finishPromise_resolve=l,t._finishPromise_reject=c;});const s=t._flushAlgorithm();return ur(t),q(s,()=>(r._state==="errored"?rt(t,r._storedError):($e(r._readableStreamController),fn(t)),null),l=>(oe(r._readableStreamController,l),rt(t,l),null)),t._finishPromise}n(Rs,"TransformStreamDefaultSinkCloseAlgorithm");function Ts(e){return ar(e,!1),e._backpressureChangePromise}n(Ts,"TransformStreamDefaultSourcePullAlgorithm");function Cs(e,t){const r=e._transformStreamController;if(r._finishPromise!==void 0)return r._finishPromise;const s=e._writable;r._finishPromise=A((c,h)=>{r._finishPromise_resolve=c,r._finishPromise_reject=h;});const l=r._cancelAlgorithm(t);return ur(r),q(l,()=>(s._state==="errored"?rt(r,s._storedError):(Rt(s._writableStreamController,t),ln(e),fn(r)),null),c=>(Rt(s._writableStreamController,c),ln(e),rt(r,c),null)),r._finishPromise}n(Cs,"TransformStreamDefaultSourceCancelAlgorithm");function lr(e){return new TypeError(`TransformStreamDefaultController.prototype.${e} can only be used on a TransformStreamDefaultController`)}n(lr,"defaultControllerBrandCheckException");function fn(e){e._finishPromise_resolve!==void 0&&(e._finishPromise_resolve(),e._finishPromise_resolve=void 0,e._finishPromise_reject=void 0);}n(fn,"defaultControllerFinishPromiseResolve");function rt(e,t){e._finishPromise_reject!==void 0&&(ve(e._finishPromise),e._finishPromise_reject(t),e._finishPromise_resolve=void 0,e._finishPromise_reject=void 0);}n(rt,"defaultControllerFinishPromiseReject");function ai(e){return new TypeError(`TransformStream.prototype.${e} can only be used on a TransformStream`)}n(ai,"streamBrandCheckException"),a.ByteLengthQueuingStrategy=Xe,a.CountQueuingStrategy=et,a.ReadableByteStreamController=te,a.ReadableStream=L,a.ReadableStreamBYOBReader=ce,a.ReadableStreamBYOBRequest=we,a.ReadableStreamDefaultController=ne,a.ReadableStreamDefaultReader=fe,a.TransformStream=tt,a.TransformStreamDefaultController=pe,a.WritableStream=de,a.WritableStreamDefaultController=ke,a.WritableStreamDefaultWriter=re;});}(pr,pr.exports)),pr.exports}n(Is,"requirePonyfill_es2018");const Fs=65536;if(!globalThis.ReadableStream)try{const i=require("node:process"),{emitWarning:o}=i;try{i.emitWarning=()=>{},Object.assign(globalThis,require("node:stream/web")),i.emitWarning=o;}catch(a){throw i.emitWarning=o,a}}catch{Object.assign(globalThis,Is());}try{const{Blob:i}=require("buffer");i&&!i.prototype.stream&&(i.prototype.stream=n(function(a){let u=0;const f=this;return new ReadableStream({type:"bytes",async pull(d){const p=await f.slice(u,Math.min(f.size,u+Fs)).arrayBuffer();u+=p.byteLength,d.enqueue(new Uint8Array(p)),u===f.size&&d.close();}})},"name"));}catch{}/*! fetch-blob. MIT License. Jimmy Wärting */const ci=65536;async function*An(i,o=!0){for(const a of i)if("stream"in a)yield*a.stream();else if(ArrayBuffer.isView(a))if(o){let u=a.byteOffset;const f=a.byteOffset+a.byteLength;for(;u!==f;){const d=Math.min(f-u,ci),b=a.buffer.slice(u,u+d);u+=b.byteLength,yield new Uint8Array(b);}}else yield a;else {let u=0,f=a;for(;u!==f.size;){const b=await f.slice(u,Math.min(f.size,u+ci)).arrayBuffer();u+=b.byteLength,yield new Uint8Array(b);}}}n(An,"toIterator");const di=(Ve=class{constructor(o=[],a={}){be(this,Pe,[]);be(this,Wt,"");be(this,bt,0);be(this,Cr,"transparent");if(typeof o!="object"||o===null)throw new TypeError("Failed to construct 'Blob': The provided value cannot be converted to a sequence.");if(typeof o[Symbol.iterator]!="function")throw new TypeError("Failed to construct 'Blob': The object must have a callable @@iterator property.");if(typeof a!="object"&&typeof a!="function")throw new TypeError("Failed to construct 'Blob': parameter 2 cannot convert to dictionary.");a===null&&(a={});const u=new TextEncoder;for(const d of o){let b;ArrayBuffer.isView(d)?b=new Uint8Array(d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength)):d instanceof ArrayBuffer?b=new Uint8Array(d.slice(0)):d instanceof Ve?b=d:b=u.encode(`${d}`),X(this,bt,O(this,bt)+(ArrayBuffer.isView(b)?b.byteLength:b.size)),O(this,Pe).push(b);}X(this,Cr,`${a.endings===void 0?"transparent":a.endings}`);const f=a.type===void 0?"":String(a.type);X(this,Wt,/^[\x20-\x7E]*$/.test(f)?f:"");}get size(){return O(this,bt)}get type(){return O(this,Wt)}async text(){const o=new TextDecoder;let a="";for await(const u of An(O(this,Pe),!1))a+=o.decode(u,{stream:!0});return a+=o.decode(),a}async arrayBuffer(){const o=new Uint8Array(this.size);let a=0;for await(const u of An(O(this,Pe),!1))o.set(u,a),a+=u.length;return o.buffer}stream(){const o=An(O(this,Pe),!0);return new globalThis.ReadableStream({type:"bytes",async pull(a){const u=await o.next();u.done?a.close():a.enqueue(u.value);},async cancel(){await o.return();}})}slice(o=0,a=this.size,u=""){const{size:f}=this;let d=o<0?Math.max(f+o,0):Math.min(o,f),b=a<0?Math.max(f+a,0):Math.min(a,f);const p=Math.max(b-d,0),E=O(this,Pe),w=[];let D=0;for(const S of E){if(D>=p)break;const m=ArrayBuffer.isView(S)?S.byteLength:S.size;if(d&&m<=d)d-=m,b-=m;else {let R;ArrayBuffer.isView(S)?(R=S.subarray(d,Math.min(m,b)),D+=R.byteLength):(R=S.slice(d,Math.min(m,b)),D+=R.size),b-=m,w.push(R),d=0;}}const A=new Ve([],{type:String(u).toLowerCase()});return X(A,bt,p),X(A,Pe,w),A}get[Symbol.toStringTag](){return "Blob"}static[Symbol.hasInstance](o){return o&&typeof o=="object"&&typeof o.constructor=="function"&&(typeof o.stream=="function"||typeof o.arrayBuffer=="function")&&/^(Blob|File)$/.test(o[Symbol.toStringTag])}},Pe=new WeakMap,Wt=new WeakMap,bt=new WeakMap,Cr=new WeakMap,n(Ve,"Blob"),Ve);Object.defineProperties(di.prototype,{size:{enumerable:!0},type:{enumerable:!0},slice:{enumerable:!0}});const js=di,lt$2=js,Ls=(zt=class extends lt$2{constructor(a,u,f={}){if(arguments.length<2)throw new TypeError(`Failed to construct 'File': 2 arguments required, but only ${arguments.length} present.`);super(a,f);be(this,qt,0);be(this,Ot,"");f===null&&(f={});const d=f.lastModified===void 0?Date.now():Number(f.lastModified);Number.isNaN(d)||X(this,qt,d),X(this,Ot,String(u));}get name(){return O(this,Ot)}get lastModified(){return O(this,qt)}get[Symbol.toStringTag](){return "File"}static[Symbol.hasInstance](a){return !!a&&a instanceof lt$2&&/^(File)$/.test(a[Symbol.toStringTag])}},qt=new WeakMap,Ot=new WeakMap,n(zt,"File"),zt),$s=Ls,Bn=$s;/*! formdata-polyfill. MIT License. Jimmy Wärting */var{toStringTag:At,iterator:Ds,hasInstance:Ms}=Symbol,hi=Math.random,Us="append,set,get,getAll,delete,keys,values,entries,forEach,constructor".split(","),pi=n((i,o,a)=>(i+="",/^(Blob|File)$/.test(o&&o[At])?[(a=a!==void 0?a+"":o[At]=="File"?o.name:"blob",i),o.name!==a||o[At]=="blob"?new Bn([o],a,o):o]:[i,o+""]),"f"),kn=n((i,o)=>(o?i:i.replace(/\r?\n|\r/g,`\r -`)).replace(/\n/g,"%0A").replace(/\r/g,"%0D").replace(/"/g,"%22"),"e$1"),Me=n((i,o,a)=>{if(o.lengthtypeof o[a]!="function")}append(...o){Me("append",arguments,2),O(this,ee).push(pi(...o));}delete(o){Me("delete",arguments,1),o+="",X(this,ee,O(this,ee).filter(([a])=>a!==o));}get(o){Me("get",arguments,1),o+="";for(var a=O(this,ee),u=a.length,f=0;fu[0]===o&&a.push(u[1])),a}has(o){return Me("has",arguments,1),o+="",O(this,ee).some(a=>a[0]===o)}forEach(o,a){Me("forEach",arguments,1);for(var[u,f]of this)o.call(a,f,u,this);}set(...o){Me("set",arguments,2);var a=[],u=!0;o=pi(...o),O(this,ee).forEach(f=>{f[0]===o[0]?u&&(u=!a.push(o)):a.push(f);}),u&&a.push(o),X(this,ee,a);}*entries(){yield*O(this,ee);}*keys(){for(var[o]of this)yield o;}*values(){for(var[,o]of this)yield o;}},ee=new WeakMap,n(It,"FormData"),It);function xs(i,o=lt$2){var a=`${hi()}${hi()}`.replace(/\./g,"").slice(-28).padStart(32,"-"),u=[],f=`--${a}\r -Content-Disposition: form-data; name="`;return i.forEach((d,b)=>typeof d=="string"?u.push(f+kn(b)+`"\r -\r -${d.replace(/\r(?!\n)|(?typeof i=="object"&&typeof i.append=="function"&&typeof i.delete=="function"&&typeof i.get=="function"&&typeof i.getAll=="function"&&typeof i.has=="function"&&typeof i.set=="function"&&typeof i.sort=="function"&&i[mr]==="URLSearchParams","isURLSearchParameters"),yr=n(i=>i&&typeof i=="object"&&typeof i.arrayBuffer=="function"&&typeof i.type=="string"&&typeof i.stream=="function"&&typeof i.constructor=="function"&&/^(Blob|File)$/.test(i[mr]),"isBlob"),Ns=n(i=>typeof i=="object"&&(i[mr]==="AbortSignal"||i[mr]==="EventTarget"),"isAbortSignal"),Hs=n((i,o)=>{const a=new URL(o).hostname,u=new URL(i).hostname;return a===u||a.endsWith(`.${u}`)},"isDomainOrSubdomain"),Vs=n((i,o)=>{const a=new URL(o).protocol,u=new URL(i).protocol;return a===u},"isSameProtocol"),Qs=promisify(me.pipeline),V=Symbol("Body internals"),Dn=class Dn{constructor(o,{size:a=0}={}){let u=null;o===null?o=null:bi(o)?o=Buffer$1.from(o.toString()):yr(o)||Buffer$1.isBuffer(o)||(types.isAnyArrayBuffer(o)?o=Buffer$1.from(o):ArrayBuffer.isView(o)?o=Buffer$1.from(o.buffer,o.byteOffset,o.byteLength):o instanceof me||(o instanceof br?(o=xs(o),u=o.type.split("=")[1]):o=Buffer$1.from(String(o))));let f=o;Buffer$1.isBuffer(o)?f=me.Readable.from(o):yr(o)&&(f=me.Readable.from(o.stream())),this[V]={body:o,stream:f,boundary:u,disturbed:!1,error:null},this.size=a,o instanceof me&&o.on("error",d=>{const b=d instanceof ft?d:new G(`Invalid response body while trying to fetch ${this.url}: ${d.message}`,"system",d);this[V].error=b;});}get body(){return this[V].stream}get bodyUsed(){return this[V].disturbed}async arrayBuffer(){const{buffer:o,byteOffset:a,byteLength:u}=await Wn(this);return o.slice(a,a+u)}async formData(){const o=this.headers.get("content-type");if(o.startsWith("application/x-www-form-urlencoded")){const u=new br,f=new URLSearchParams(await this.text());for(const[d,b]of f)u.append(d,b);return u}const{toFormData:a}=await import('../chunks/multipart-parser.mjs');return a(this.body,o)}async blob(){const o=this.headers&&this.headers.get("content-type")||this[V].body&&this[V].body.type||"",a=await this.arrayBuffer();return new lt$2([a],{type:o})}async json(){const o=await this.text();return JSON.parse(o)}async text(){const o=await Wn(this);return new TextDecoder().decode(o)}buffer(){return Wn(this)}};n(Dn,"Body");let Ue=Dn;Ue.prototype.buffer=deprecate(Ue.prototype.buffer,"Please use 'response.arrayBuffer()' instead of 'response.buffer()'","node-fetch#buffer"),Object.defineProperties(Ue.prototype,{body:{enumerable:!0},bodyUsed:{enumerable:!0},arrayBuffer:{enumerable:!0},blob:{enumerable:!0},json:{enumerable:!0},text:{enumerable:!0},data:{get:deprecate(()=>{},"data doesn't exist, use json(), text(), arrayBuffer(), or body instead","https://github.com/node-fetch/node-fetch/issues/1000 (response)")}});async function Wn(i){if(i[V].disturbed)throw new TypeError(`body used already for: ${i.url}`);if(i[V].disturbed=!0,i[V].error)throw i[V].error;const{body:o}=i;if(o===null)return Buffer$1.alloc(0);if(!(o instanceof me))return Buffer$1.alloc(0);const a=[];let u=0;try{for await(const f of o){if(i.size>0&&u+f.length>i.size){const d=new G(`content size at ${i.url} over limit: ${i.size}`,"max-size");throw o.destroy(d),d}u+=f.length,a.push(f);}}catch(f){throw f instanceof ft?f:new G(`Invalid response body while trying to fetch ${i.url}: ${f.message}`,"system",f)}if(o.readableEnded===!0||o._readableState.ended===!0)try{return a.every(f=>typeof f=="string")?Buffer$1.from(a.join("")):Buffer$1.concat(a,u)}catch(f){throw new G(`Could not create Buffer from response body for ${i.url}: ${f.message}`,"system",f)}else throw new G(`Premature close of server response while trying to fetch ${i.url}`)}n(Wn,"consumeBody");const qn=n((i,o)=>{let a,u,{body:f}=i[V];if(i.bodyUsed)throw new Error("cannot clone body after it is used");return f instanceof me&&typeof f.getBoundary!="function"&&(a=new PassThrough({highWaterMark:o}),u=new PassThrough({highWaterMark:o}),f.pipe(a),f.pipe(u),i[V].stream=a,f=u),f},"clone"),Ys=deprecate(i=>i.getBoundary(),"form-data doesn't follow the spec and requires special treatment. Use alternative package","https://github.com/node-fetch/node-fetch/issues/1167"),mi=n((i,o)=>i===null?null:typeof i=="string"?"text/plain;charset=UTF-8":bi(i)?"application/x-www-form-urlencoded;charset=UTF-8":yr(i)?i.type||null:Buffer$1.isBuffer(i)||types.isAnyArrayBuffer(i)||ArrayBuffer.isView(i)?null:i instanceof br?`multipart/form-data; boundary=${o[V].boundary}`:i&&typeof i.getBoundary=="function"?`multipart/form-data;boundary=${Ys(i)}`:i instanceof me?null:"text/plain;charset=UTF-8","extractContentType"),Gs=n(i=>{const{body:o}=i[V];return o===null?0:yr(o)?o.size:Buffer$1.isBuffer(o)?o.length:o&&typeof o.getLengthSync=="function"&&o.hasKnownLength&&o.hasKnownLength()?o.getLengthSync():null},"getTotalBytes"),Zs=n(async(i,{body:o})=>{o===null?i.end():await Qs(o,i);},"writeToStream"),gr=typeof Et.validateHeaderName=="function"?Et.validateHeaderName:i=>{if(!/^[\^`\-\w!#$%&'*+.|~]+$/.test(i)){const o=new TypeError(`Header name must be a valid HTTP token [${i}]`);throw Object.defineProperty(o,"code",{value:"ERR_INVALID_HTTP_TOKEN"}),o}},On=typeof Et.validateHeaderValue=="function"?Et.validateHeaderValue:(i,o)=>{if(/[^\t\u0020-\u007E\u0080-\u00FF]/.test(o)){const a=new TypeError(`Invalid character in header content ["${i}"]`);throw Object.defineProperty(a,"code",{value:"ERR_INVALID_CHAR"}),a}},Pr=class Pr extends URLSearchParams{constructor(o){let a=[];if(o instanceof Pr){const u=o.raw();for(const[f,d]of Object.entries(u))a.push(...d.map(b=>[f,b]));}else if(o!=null)if(typeof o=="object"&&!types.isBoxedPrimitive(o)){const u=o[Symbol.iterator];if(u==null)a.push(...Object.entries(o));else {if(typeof u!="function")throw new TypeError("Header pairs must be iterable");a=[...o].map(f=>{if(typeof f!="object"||types.isBoxedPrimitive(f))throw new TypeError("Each header pair must be an iterable object");return [...f]}).map(f=>{if(f.length!==2)throw new TypeError("Each header pair must be a name/value tuple");return [...f]});}}else throw new TypeError("Failed to construct 'Headers': The provided value is not of type '(sequence> or record)");return a=a.length>0?a.map(([u,f])=>(gr(u),On(u,String(f)),[String(u).toLowerCase(),String(f)])):void 0,super(a),new Proxy(this,{get(u,f,d){switch(f){case"append":case"set":return (b,p)=>(gr(b),On(b,String(p)),URLSearchParams.prototype[f].call(u,String(b).toLowerCase(),String(p)));case"delete":case"has":case"getAll":return b=>(gr(b),URLSearchParams.prototype[f].call(u,String(b).toLowerCase()));case"keys":return ()=>(u.sort(),new Set(URLSearchParams.prototype.keys.call(u)).keys());default:return Reflect.get(u,f,d)}}})}get[Symbol.toStringTag](){return this.constructor.name}toString(){return Object.prototype.toString.call(this)}get(o){const a=this.getAll(o);if(a.length===0)return null;let u=a.join(", ");return /^content-encoding$/i.test(o)&&(u=u.toLowerCase()),u}forEach(o,a=void 0){for(const u of this.keys())Reflect.apply(o,a,[this.get(u),u,this]);}*values(){for(const o of this.keys())yield this.get(o);}*entries(){for(const o of this.keys())yield [o,this.get(o)];}[Symbol.iterator](){return this.entries()}raw(){return [...this.keys()].reduce((o,a)=>(o[a]=this.getAll(a),o),{})}[Symbol.for("nodejs.util.inspect.custom")](){return [...this.keys()].reduce((o,a)=>{const u=this.getAll(a);return a==="host"?o[a]=u[0]:o[a]=u.length>1?u:u[0],o},{})}};n(Pr,"Headers");let ye=Pr;Object.defineProperties(ye.prototype,["get","entries","forEach","values"].reduce((i,o)=>(i[o]={enumerable:!0},i),{}));function Ks(i=[]){return new ye(i.reduce((o,a,u,f)=>(u%2===0&&o.push(f.slice(u,u+2)),o),[]).filter(([o,a])=>{try{return gr(o),On(o,String(a)),!0}catch{return !1}}))}n(Ks,"fromRawHeaders");const Js=new Set([301,302,303,307,308]),zn=n(i=>Js.has(i),"isRedirect"),se=Symbol("Response internals"),xe=class xe extends Ue{constructor(o=null,a={}){super(o,a);const u=a.status!=null?a.status:200,f=new ye(a.headers);if(o!==null&&!f.has("Content-Type")){const d=mi(o,this);d&&f.append("Content-Type",d);}this[se]={type:"default",url:a.url,status:u,statusText:a.statusText||"",headers:f,counter:a.counter,highWaterMark:a.highWaterMark};}get type(){return this[se].type}get url(){return this[se].url||""}get status(){return this[se].status}get ok(){return this[se].status>=200&&this[se].status<300}get redirected(){return this[se].counter>0}get statusText(){return this[se].statusText}get headers(){return this[se].headers}get highWaterMark(){return this[se].highWaterMark}clone(){return new xe(qn(this,this.highWaterMark),{type:this.type,url:this.url,status:this.status,statusText:this.statusText,headers:this.headers,ok:this.ok,redirected:this.redirected,size:this.size,highWaterMark:this.highWaterMark})}static redirect(o,a=302){if(!zn(a))throw new RangeError('Failed to execute "redirect" on "response": Invalid status code');return new xe(null,{headers:{location:new URL(o).toString()},status:a})}static error(){const o=new xe(null,{status:0,statusText:""});return o[se].type="error",o}static json(o=void 0,a={}){const u=JSON.stringify(o);if(u===void 0)throw new TypeError("data is not JSON serializable");const f=new ye(a&&a.headers);return f.has("content-type")||f.set("content-type","application/json"),new xe(u,{...a,headers:f})}get[Symbol.toStringTag](){return "Response"}};n(xe,"Response");let ue=xe;Object.defineProperties(ue.prototype,{type:{enumerable:!0},url:{enumerable:!0},status:{enumerable:!0},ok:{enumerable:!0},redirected:{enumerable:!0},statusText:{enumerable:!0},headers:{enumerable:!0},clone:{enumerable:!0}});const Xs=n(i=>{if(i.search)return i.search;const o=i.href.length-1,a=i.hash||(i.href[o]==="#"?"#":"");return i.href[o-a.length]==="?"?"?":""},"getSearch");function yi(i,o=!1){return i==null||(i=new URL(i),/^(about|blob|data):$/.test(i.protocol))?"no-referrer":(i.username="",i.password="",i.hash="",o&&(i.pathname="",i.search=""),i)}n(yi,"stripURLForUseAsAReferrer");const gi=new Set(["","no-referrer","no-referrer-when-downgrade","same-origin","origin","strict-origin","origin-when-cross-origin","strict-origin-when-cross-origin","unsafe-url"]),eu="strict-origin-when-cross-origin";function tu(i){if(!gi.has(i))throw new TypeError(`Invalid referrerPolicy: ${i}`);return i}n(tu,"validateReferrerPolicy");function ru(i){if(/^(http|ws)s:$/.test(i.protocol))return !0;const o=i.host.replace(/(^\[)|(]$)/g,""),a=isIP(o);return a===4&&/^127\./.test(o)||a===6&&/^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(o)?!0:i.host==="localhost"||i.host.endsWith(".localhost")?!1:i.protocol==="file:"}n(ru,"isOriginPotentiallyTrustworthy");function ct(i){return /^about:(blank|srcdoc)$/.test(i)||i.protocol==="data:"||/^(blob|filesystem):$/.test(i.protocol)?!0:ru(i)}n(ct,"isUrlPotentiallyTrustworthy");function nu(i,{referrerURLCallback:o,referrerOriginCallback:a}={}){if(i.referrer==="no-referrer"||i.referrerPolicy==="")return null;const u=i.referrerPolicy;if(i.referrer==="about:client")return "no-referrer";const f=i.referrer;let d=yi(f),b=yi(f,!0);d.toString().length>4096&&(d=b),o&&(d=o(d)),a&&(b=a(b));const p=new URL(i.url);switch(u){case"no-referrer":return "no-referrer";case"origin":return b;case"unsafe-url":return d;case"strict-origin":return ct(d)&&!ct(p)?"no-referrer":b.toString();case"strict-origin-when-cross-origin":return d.origin===p.origin?d:ct(d)&&!ct(p)?"no-referrer":b;case"same-origin":return d.origin===p.origin?d:"no-referrer";case"origin-when-cross-origin":return d.origin===p.origin?d:b;case"no-referrer-when-downgrade":return ct(d)&&!ct(p)?"no-referrer":d;default:throw new TypeError(`Invalid referrerPolicy: ${u}`)}}n(nu,"determineRequestsReferrer");function ou(i){const o=(i.get("referrer-policy")||"").split(/[,\s]+/);let a="";for(const u of o)u&&gi.has(u)&&(a=u);return a}n(ou,"parseReferrerPolicyFromHeader");const $=Symbol("Request internals"),Bt=n(i=>typeof i=="object"&&typeof i[$]=="object","isRequest"),iu=deprecate(()=>{},".data is not a valid RequestInit property, use .body instead","https://github.com/node-fetch/node-fetch/issues/1000 (request)"),vr=class vr extends Ue{constructor(o,a={}){let u;if(Bt(o)?u=new URL(o.url):(u=new URL(o),o={}),u.username!==""||u.password!=="")throw new TypeError(`${u} is an url with embedded credentials.`);let f=a.method||o.method||"GET";if(/^(delete|get|head|options|post|put)$/i.test(f)&&(f=f.toUpperCase()),!Bt(a)&&"data"in a&&iu(),(a.body!=null||Bt(o)&&o.body!==null)&&(f==="GET"||f==="HEAD"))throw new TypeError("Request with GET/HEAD method cannot have body");const d=a.body?a.body:Bt(o)&&o.body!==null?qn(o):null;super(d,{size:a.size||o.size||0});const b=new ye(a.headers||o.headers||{});if(d!==null&&!b.has("Content-Type")){const w=mi(d,this);w&&b.set("Content-Type",w);}let p=Bt(o)?o.signal:null;if("signal"in a&&(p=a.signal),p!=null&&!Ns(p))throw new TypeError("Expected signal to be an instanceof AbortSignal or EventTarget");let E=a.referrer==null?o.referrer:a.referrer;if(E==="")E="no-referrer";else if(E){const w=new URL(E);E=/^about:(\/\/)?client$/.test(w)?"client":w;}else E=void 0;this[$]={method:f,redirect:a.redirect||o.redirect||"follow",headers:b,parsedURL:u,signal:p,referrer:E},this.follow=a.follow===void 0?o.follow===void 0?20:o.follow:a.follow,this.compress=a.compress===void 0?o.compress===void 0?!0:o.compress:a.compress,this.counter=a.counter||o.counter||0,this.agent=a.agent||o.agent,this.highWaterMark=a.highWaterMark||o.highWaterMark||16384,this.insecureHTTPParser=a.insecureHTTPParser||o.insecureHTTPParser||!1,this.referrerPolicy=a.referrerPolicy||o.referrerPolicy||"";}get method(){return this[$].method}get url(){return format(this[$].parsedURL)}get headers(){return this[$].headers}get redirect(){return this[$].redirect}get signal(){return this[$].signal}get referrer(){if(this[$].referrer==="no-referrer")return "";if(this[$].referrer==="client")return "about:client";if(this[$].referrer)return this[$].referrer.toString()}get referrerPolicy(){return this[$].referrerPolicy}set referrerPolicy(o){this[$].referrerPolicy=tu(o);}clone(){return new vr(this)}get[Symbol.toStringTag](){return "Request"}};n(vr,"Request");let dt=vr;Object.defineProperties(dt.prototype,{method:{enumerable:!0},url:{enumerable:!0},headers:{enumerable:!0},redirect:{enumerable:!0},clone:{enumerable:!0},signal:{enumerable:!0},referrer:{enumerable:!0},referrerPolicy:{enumerable:!0}});const au=n(i=>{const{parsedURL:o}=i[$],a=new ye(i[$].headers);a.has("Accept")||a.set("Accept","*/*");let u=null;if(i.body===null&&/^(post|put)$/i.test(i.method)&&(u="0"),i.body!==null){const p=Gs(i);typeof p=="number"&&!Number.isNaN(p)&&(u=String(p));}u&&a.set("Content-Length",u),i.referrerPolicy===""&&(i.referrerPolicy=eu),i.referrer&&i.referrer!=="no-referrer"?i[$].referrer=nu(i):i[$].referrer="no-referrer",i[$].referrer instanceof URL&&a.set("Referer",i.referrer),a.has("User-Agent")||a.set("User-Agent","node-fetch"),i.compress&&!a.has("Accept-Encoding")&&a.set("Accept-Encoding","gzip, deflate, br");let{agent:f}=i;typeof f=="function"&&(f=f(o));const d=Xs(o),b={path:o.pathname+d,method:i.method,headers:a[Symbol.for("nodejs.util.inspect.custom")](),insecureHTTPParser:i.insecureHTTPParser,agent:f};return {parsedURL:o,options:b}},"getNodeRequestOptions"),Mn=class Mn extends ft{constructor(o,a="aborted"){super(o,a);}};n(Mn,"AbortError");let _r=Mn;/*! node-domexception. MIT License. Jimmy Wärting */if(!globalThis.DOMException)try{const{MessageChannel:i}=require("worker_threads"),o=new i().port1,a=new ArrayBuffer;o.postMessage(a,[a,a]);}catch(i){i.constructor.name==="DOMException"&&(globalThis.DOMException=i.constructor);}var su=globalThis.DOMException;const uu=f$1(su),{stat:In}=promises;n((i,o)=>_i(statSync(i),i,o),"blobFromSync");n((i,o)=>In(i).then(a=>_i(a,i,o)),"blobFrom");n((i,o)=>In(i).then(a=>Si(a,i,o)),"fileFrom");n((i,o)=>Si(statSync(i),i,o),"fileFromSync");const _i=n((i,o,a="")=>new lt$2([new Sr({path:o,size:i.size,lastModified:i.mtimeMs,start:0})],{type:a}),"fromBlob"),Si=n((i,o,a="")=>new Bn([new Sr({path:o,size:i.size,lastModified:i.mtimeMs,start:0})],basename(o),{type:a,lastModified:i.mtimeMs}),"fromFile"),Er=class Er{constructor(o){be(this,Ne,void 0);be(this,He,void 0);X(this,Ne,o.path),X(this,He,o.start),this.size=o.size,this.lastModified=o.lastModified;}slice(o,a){return new Er({path:O(this,Ne),lastModified:this.lastModified,size:a-o,start:O(this,He)+o})}async*stream(){const{mtimeMs:o}=await In(O(this,Ne));if(o>this.lastModified)throw new uu("The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.","NotReadableError");yield*createReadStream(O(this,Ne),{start:O(this,He),end:O(this,He)+this.size-1});}get[Symbol.toStringTag](){return "Blob"}};Ne=new WeakMap,He=new WeakMap,n(Er,"BlobDataItem");let Sr=Er;const hu=new Set(["data:","http:","https:"]);async function wi(i,o){return new Promise((a,u)=>{const f=new dt(i,o),{parsedURL:d,options:b}=au(f);if(!hu.has(d.protocol))throw new TypeError(`node-fetch cannot load ${i}. URL scheme "${d.protocol.replace(/:$/,"")}" is not supported.`);if(d.protocol==="data:"){const R=zs(f.url),q=new ue(R,{headers:{"Content-Type":R.typeFull}});a(q);return}const p=(d.protocol==="https:"?https:Et).request,{signal:E}=f;let w=null;const D=n(()=>{const R=new _r("The operation was aborted.");u(R),f.body&&f.body instanceof me.Readable&&f.body.destroy(R),!(!w||!w.body)&&w.body.emit("error",R);},"abort");if(E&&E.aborted){D();return}const A=n(()=>{D(),m();},"abortAndFinalize"),S=p(d.toString(),b);E&&E.addEventListener("abort",A);const m=n(()=>{S.abort(),E&&E.removeEventListener("abort",A);},"finalize");S.on("error",R=>{u(new G(`request to ${f.url} failed, reason: ${R.message}`,"system",R)),m();}),pu(S,R=>{w&&w.body&&w.body.destroy(R);}),process.version<"v14"&&S.on("socket",R=>{let q;R.prependListener("end",()=>{q=R._eventsCount;}),R.prependListener("close",F=>{if(w&&q{S.setTimeout(0);const q=Ks(R.rawHeaders);if(zn(R.statusCode)){const z=q.get("Location");let j=null;try{j=z===null?null:new URL(z,f.url);}catch{if(f.redirect!=="manual"){u(new G(`uri requested responds with an invalid redirect URL: ${z}`,"invalid-redirect")),m();return}}switch(f.redirect){case"error":u(new G(`uri requested responds with a redirect, redirect mode is set to error: ${f.url}`,"no-redirect")),m();return;case"manual":break;case"follow":{if(j===null)break;if(f.counter>=f.follow){u(new G(`maximum redirect reached at: ${f.url}`,"max-redirect")),m();return}const I={headers:new ye(f.headers),follow:f.follow,counter:f.counter+1,agent:f.agent,compress:f.compress,method:f.method,body:qn(f),signal:f.signal,size:f.size,referrer:f.referrer,referrerPolicy:f.referrerPolicy};if(!Hs(f.url,j)||!Vs(f.url,j))for(const U of ["authorization","www-authenticate","cookie","cookie2"])I.headers.delete(U);if(R.statusCode!==303&&f.body&&o.body instanceof me.Readable){u(new G("Cannot follow redirect with body being a readable stream","unsupported-redirect")),m();return}(R.statusCode===303||(R.statusCode===301||R.statusCode===302)&&f.method==="POST")&&(I.method="GET",I.body=void 0,I.headers.delete("content-length"));const mt=ou(q);mt&&(I.referrerPolicy=mt),a(wi(new dt(j,I))),m();return}default:return u(new TypeError(`Redirect option '${f.redirect}' is not a valid value of RequestRedirect`))}}E&&R.once("end",()=>{E.removeEventListener("abort",A);});let F=pipeline(R,new PassThrough,z=>{z&&u(z);});process.version<"v12.10"&&R.on("aborted",A);const Q={url:f.url,status:R.statusCode,statusText:R.statusMessage,headers:q,size:f.size,counter:f.counter,highWaterMark:f.highWaterMark},M=q.get("Content-Encoding");if(!f.compress||f.method==="HEAD"||M===null||R.statusCode===204||R.statusCode===304){w=new ue(F,Q),a(w);return}const ve={flush:st.Z_SYNC_FLUSH,finishFlush:st.Z_SYNC_FLUSH};if(M==="gzip"||M==="x-gzip"){F=pipeline(F,st.createGunzip(ve),z=>{z&&u(z);}),w=new ue(F,Q),a(w);return}if(M==="deflate"||M==="x-deflate"){const z=pipeline(R,new PassThrough,j=>{j&&u(j);});z.once("data",j=>{(j[0]&15)===8?F=pipeline(F,st.createInflate(),I=>{I&&u(I);}):F=pipeline(F,st.createInflateRaw(),I=>{I&&u(I);}),w=new ue(F,Q),a(w);}),z.once("end",()=>{w||(w=new ue(F,Q),a(w));});return}if(M==="br"){F=pipeline(F,st.createBrotliDecompress(),z=>{z&&u(z);}),w=new ue(F,Q),a(w);return}w=new ue(F,Q),a(w);}),Zs(S,f).catch(u);})}n(wi,"fetch$1");function pu(i,o){const a=Buffer$1.from(`0\r -\r -`);let u=!1,f=!1,d;i.on("response",b=>{const{headers:p}=b;u=p["transfer-encoding"]==="chunked"&&!p["content-length"];}),i.on("socket",b=>{const p=n(()=>{if(u&&!f){const w=new Error("Premature close");w.code="ERR_STREAM_PREMATURE_CLOSE",o(w);}},"onSocketClose"),E=n(w=>{f=Buffer$1.compare(w.slice(-5),a)===0,!f&&d&&(f=Buffer$1.compare(d.slice(-3),a.slice(0,3))===0&&Buffer$1.compare(w.slice(-2),a.slice(3))===0),d=w;},"onData");b.prependListener("close",p),b.on("data",E),i.on("close",()=>{b.removeListener("close",p),b.removeListener("data",E);});});}n(pu,"fixResponseChunkedTransferBadEnding");const Ri=new WeakMap,Fn=new WeakMap;function W(i){const o=Ri.get(i);return console.assert(o!=null,"'this' is expected an Event object, but got",i),o}n(W,"pd");function Ti(i){if(i.passiveListener!=null){typeof console<"u"&&typeof console.error=="function"&&console.error("Unable to preventDefault inside passive event listener invocation.",i.passiveListener);return}i.event.cancelable&&(i.canceled=!0,typeof i.event.preventDefault=="function"&&i.event.preventDefault());}n(Ti,"setCancelFlag");function ht(i,o){Ri.set(this,{eventTarget:i,event:o,eventPhase:2,currentTarget:i,canceled:!1,stopped:!1,immediateStopped:!1,passiveListener:null,timeStamp:o.timeStamp||Date.now()}),Object.defineProperty(this,"isTrusted",{value:!1,enumerable:!0});const a=Object.keys(o);for(let u=0;u0){const i=new Array(arguments.length);for(let o=0;oCu(i,"name",{value:o,configurable:!0}),"e");const zi=wi;Ii();function Ii(){!globalThis.process?.versions?.node&&!globalThis.process?.env.DISABLE_NODE_FETCH_NATIVE_WARN&&console.warn("[node-fetch-native] Node.js compatible build of `node-fetch-native` is being used in a non-Node.js environment. Please make sure you are using proper export conditions or report this issue to https://github.com/unjs/node-fetch-native. You can set `process.env.DISABLE_NODE_FETCH_NATIVE_WARN` to disable this warning.");}n(Ii,"s"),Pu(Ii,"checkNodeEnvironment"); - -var a=Object.defineProperty;var t$1=(e,r)=>a(e,"name",{value:r,configurable:!0});var f=Object.defineProperty,g=t$1((e,r)=>f(e,"name",{value:r,configurable:!0}),"e");const o=!!globalThis.process?.env?.FORCE_NODE_FETCH;function l(){return !o&&globalThis.fetch?globalThis.fetch:zi}t$1(l,"p"),g(l,"_getFetch");const s=l(),d=!o&&globalThis.Headers||ye,A=!o&&globalThis.AbortController||jn; - -class FetchError extends Error { - constructor(message, opts) { - super(message, opts); - this.name = "FetchError"; - if (opts?.cause && !this.cause) { - this.cause = opts.cause; - } - } -} -function createFetchError(ctx) { - const errorMessage = ctx.error?.message || ctx.error?.toString() || ""; - const method = ctx.request?.method || ctx.options?.method || "GET"; - const url = ctx.request?.url || String(ctx.request) || "/"; - const requestStr = `[${method}] ${JSON.stringify(url)}`; - const statusStr = ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : ""; - const message = `${requestStr}: ${statusStr}${errorMessage ? ` ${errorMessage}` : ""}`; - const fetchError = new FetchError( - message, - ctx.error ? { cause: ctx.error } : void 0 - ); - for (const key of ["request", "options", "response"]) { - Object.defineProperty(fetchError, key, { - get() { - return ctx[key]; - } - }); - } - for (const [key, refKey] of [ - ["data", "_data"], - ["status", "status"], - ["statusCode", "status"], - ["statusText", "statusText"], - ["statusMessage", "statusText"] - ]) { - Object.defineProperty(fetchError, key, { - get() { - return ctx.response && ctx.response[refKey]; - } - }); - } - return fetchError; -} - -const payloadMethods = new Set( - Object.freeze(["PATCH", "POST", "PUT", "DELETE"]) -); -function isPayloadMethod(method = "GET") { - return payloadMethods.has(method.toUpperCase()); -} -function isJSONSerializable(value) { - if (value === void 0) { - return false; - } - const t = typeof value; - if (t === "string" || t === "number" || t === "boolean" || t === null) { - return true; - } - if (t !== "object") { - return false; - } - if (Array.isArray(value)) { - return true; - } - if (value.buffer) { - return false; - } - return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function"; -} -const textTypes = /* @__PURE__ */ new Set([ - "image/svg", - "application/xml", - "application/xhtml", - "application/html" -]); -const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i; -function detectResponseType(_contentType = "") { - if (!_contentType) { - return "json"; - } - const contentType = _contentType.split(";").shift() || ""; - if (JSON_RE.test(contentType)) { - return "json"; - } - if (textTypes.has(contentType) || contentType.startsWith("text/")) { - return "text"; - } - return "blob"; -} -function mergeFetchOptions(input, defaults, Headers = globalThis.Headers) { - const merged = { - ...defaults, - ...input - }; - if (defaults?.params && input?.params) { - merged.params = { - ...defaults?.params, - ...input?.params - }; - } - if (defaults?.query && input?.query) { - merged.query = { - ...defaults?.query, - ...input?.query - }; - } - if (defaults?.headers && input?.headers) { - merged.headers = new Headers(defaults?.headers || {}); - for (const [key, value] of new Headers(input?.headers || {})) { - merged.headers.set(key, value); - } - } - return merged; -} - -const retryStatusCodes = /* @__PURE__ */ new Set([ - 408, - // Request Timeout - 409, - // Conflict - 425, - // Too Early - 429, - // Too Many Requests - 500, - // Internal Server Error - 502, - // Bad Gateway - 503, - // Service Unavailable - 504 - // Gateway Timeout -]); -const nullBodyResponses = /* @__PURE__ */ new Set([101, 204, 205, 304]); -function createFetch(globalOptions = {}) { - const { - fetch = globalThis.fetch, - Headers = globalThis.Headers, - AbortController = globalThis.AbortController - } = globalOptions; - async function onError(context) { - const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false; - if (context.options.retry !== false && !isAbort) { - let retries; - if (typeof context.options.retry === "number") { - retries = context.options.retry; - } else { - retries = isPayloadMethod(context.options.method) ? 0 : 1; - } - const responseCode = context.response && context.response.status || 500; - if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) { - const retryDelay = context.options.retryDelay || 0; - if (retryDelay > 0) { - await new Promise((resolve) => setTimeout(resolve, retryDelay)); - } - return $fetchRaw(context.request, { - ...context.options, - retry: retries - 1, - timeout: context.options.timeout - }); - } - } - const error = createFetchError(context); - if (Error.captureStackTrace) { - Error.captureStackTrace(error, $fetchRaw); - } - throw error; - } - const $fetchRaw = async function $fetchRaw2(_request, _options = {}) { - const context = { - request: _request, - options: mergeFetchOptions(_options, globalOptions.defaults, Headers), - response: void 0, - error: void 0 - }; - context.options.method = context.options.method?.toUpperCase(); - if (context.options.onRequest) { - await context.options.onRequest(context); - } - if (typeof context.request === "string") { - if (context.options.baseURL) { - context.request = withBase(context.request, context.options.baseURL); - } - if (context.options.query || context.options.params) { - context.request = withQuery(context.request, { - ...context.options.params, - ...context.options.query - }); - } - } - if (context.options.body && isPayloadMethod(context.options.method)) { - if (isJSONSerializable(context.options.body)) { - context.options.body = typeof context.options.body === "string" ? context.options.body : JSON.stringify(context.options.body); - context.options.headers = new Headers(context.options.headers || {}); - if (!context.options.headers.has("content-type")) { - context.options.headers.set("content-type", "application/json"); - } - if (!context.options.headers.has("accept")) { - context.options.headers.set("accept", "application/json"); - } - } else if ( - // ReadableStream Body - "pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || // Node.js Stream Body - typeof context.options.body.pipe === "function" - ) { - if (!("duplex" in context.options)) { - context.options.duplex = "half"; - } - } - } - if (!context.options.signal && context.options.timeout) { - const controller = new AbortController(); - setTimeout(() => controller.abort(), context.options.timeout); - context.options.signal = controller.signal; - } - try { - context.response = await fetch( - context.request, - context.options - ); - } catch (error) { - context.error = error; - if (context.options.onRequestError) { - await context.options.onRequestError(context); - } - return await onError(context); - } - const hasBody = context.response.body && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD"; - if (hasBody) { - const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || ""); - switch (responseType) { - case "json": { - const data = await context.response.text(); - const parseFunction = context.options.parseResponse || destr; - context.response._data = parseFunction(data); - break; - } - case "stream": { - context.response._data = context.response.body; - break; - } - default: { - context.response._data = await context.response[responseType](); - } - } - } - if (context.options.onResponse) { - await context.options.onResponse(context); - } - if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) { - if (context.options.onResponseError) { - await context.options.onResponseError(context); - } - return await onError(context); - } - return context.response; - }; - const $fetch = async function $fetch2(request, options) { - const r = await $fetchRaw(request, options); - return r._data; - }; - $fetch.raw = $fetchRaw; - $fetch.native = (...args) => fetch(...args); - $fetch.create = (defaultOptions = {}) => createFetch({ - ...globalOptions, - defaults: { - ...globalOptions.defaults, - ...defaultOptions - } - }); - return $fetch; -} - -function createNodeFetch() { - const useKeepAlive = JSON.parse(process.env.FETCH_KEEP_ALIVE || "false"); - if (!useKeepAlive) { - return s; - } - const agentOptions = { keepAlive: true }; - const httpAgent = new Et.Agent(agentOptions); - const httpsAgent = new https.Agent(agentOptions); - const nodeFetchOptions = { - agent(parsedURL) { - return parsedURL.protocol === "http:" ? httpAgent : httpsAgent; - } - }; - return function nodeFetchWithKeepAlive(input, init) { - return s(input, { ...nodeFetchOptions, ...init }); - }; -} -const fetch = globalThis.fetch || createNodeFetch(); -const Headers = globalThis.Headers || d; -const AbortController$1 = globalThis.AbortController || A; -const ofetch = createFetch({ fetch, Headers, AbortController: AbortController$1 }); -const $fetch = ofetch; - -const SemVer$b = semver$1; -const parse$6 = (version, options, throwErrors = false) => { - if (version instanceof SemVer$b) { - return version - } - try { - return new SemVer$b(version, options) - } catch (er) { - if (!throwErrors) { - return null - } - throw er - } -}; - -var parse_1 = parse$6; - -const parse$5 = parse_1; -const valid$2 = (version, options) => { - const v = parse$5(version, options); - return v ? v.version : null -}; -var valid_1 = valid$2; - -const parse$4 = parse_1; -const clean$1 = (version, options) => { - const s = parse$4(version.trim().replace(/^[=v]+/, ''), options); - return s ? s.version : null -}; -var clean_1 = clean$1; - -const SemVer$a = semver$1; - -const inc$1 = (version, release, options, identifier, identifierBase) => { - if (typeof (options) === 'string') { - identifierBase = identifier; - identifier = options; - options = undefined; - } - - try { - return new SemVer$a( - version instanceof SemVer$a ? version.version : version, - options - ).inc(release, identifier, identifierBase).version - } catch (er) { - return null - } -}; -var inc_1 = inc$1; - -const parse$3 = parse_1; - -const diff$1 = (version1, version2) => { - const v1 = parse$3(version1, null, true); - const v2 = parse$3(version2, null, true); - const comparison = v1.compare(v2); - - if (comparison === 0) { - return null - } - - const v1Higher = comparison > 0; - const highVersion = v1Higher ? v1 : v2; - const lowVersion = v1Higher ? v2 : v1; - const highHasPre = !!highVersion.prerelease.length; - const lowHasPre = !!lowVersion.prerelease.length; - - if (lowHasPre && !highHasPre) { - // Going from prerelease -> no prerelease requires some special casing - - // If the low version has only a major, then it will always be a major - // Some examples: - // 1.0.0-1 -> 1.0.0 - // 1.0.0-1 -> 1.1.1 - // 1.0.0-1 -> 2.0.0 - if (!lowVersion.patch && !lowVersion.minor) { - return 'major' - } - - // Otherwise it can be determined by checking the high version - - if (highVersion.patch) { - // anything higher than a patch bump would result in the wrong version - return 'patch' - } - - if (highVersion.minor) { - // anything higher than a minor bump would result in the wrong version - return 'minor' - } - - // bumping major/minor/patch all have same result - return 'major' - } - - // add the `pre` prefix if we are going to a prerelease version - const prefix = highHasPre ? 'pre' : ''; - - if (v1.major !== v2.major) { - return prefix + 'major' - } - - if (v1.minor !== v2.minor) { - return prefix + 'minor' - } - - if (v1.patch !== v2.patch) { - return prefix + 'patch' - } - - // high and low are preleases - return 'prerelease' -}; - -var diff_1 = diff$1; - -const SemVer$9 = semver$1; -const major$1 = (a, loose) => new SemVer$9(a, loose).major; -var major_1 = major$1; - -const SemVer$8 = semver$1; -const minor$1 = (a, loose) => new SemVer$8(a, loose).minor; -var minor_1 = minor$1; - -const SemVer$7 = semver$1; -const patch$1 = (a, loose) => new SemVer$7(a, loose).patch; -var patch_1 = patch$1; - -const parse$2 = parse_1; -const prerelease$1 = (version, options) => { - const parsed = parse$2(version, options); - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null -}; -var prerelease_1 = prerelease$1; - -const compare$4 = compare_1; -const rcompare$1 = (a, b, loose) => compare$4(b, a, loose); -var rcompare_1 = rcompare$1; - -const compare$3 = compare_1; -const compareLoose$1 = (a, b) => compare$3(a, b, true); -var compareLoose_1 = compareLoose$1; - -const SemVer$6 = semver$1; -const compareBuild$3 = (a, b, loose) => { - const versionA = new SemVer$6(a, loose); - const versionB = new SemVer$6(b, loose); - return versionA.compare(versionB) || versionA.compareBuild(versionB) -}; -var compareBuild_1 = compareBuild$3; - -const compareBuild$2 = compareBuild_1; -const sort$1 = (list, loose) => list.sort((a, b) => compareBuild$2(a, b, loose)); -var sort_1 = sort$1; - -const compareBuild$1 = compareBuild_1; -const rsort$1 = (list, loose) => list.sort((a, b) => compareBuild$1(b, a, loose)); -var rsort_1 = rsort$1; - -const SemVer$5 = semver$1; -const parse$1 = parse_1; -const { safeRe: re, t } = reExports; - -const coerce$1 = (version, options) => { - if (version instanceof SemVer$5) { - return version - } - - if (typeof version === 'number') { - version = String(version); - } - - if (typeof version !== 'string') { - return null - } - - options = options || {}; - - let match = null; - if (!options.rtl) { - match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); - } else { - // Find the right-most coercible string that does not share - // a terminus with a more left-ward coercible string. - // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' - // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4' - // - // Walk through the string checking with a /g regexp - // Manually set the index so as to pick up overlapping matches. - // Stop when we get a match that ends at the string end, since no - // coercible string can be more right-ward without the same terminus. - const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; - let next; - while ((next = coerceRtlRegex.exec(version)) && - (!match || match.index + match[0].length !== version.length) - ) { - if (!match || - next.index + next[0].length !== match.index + match[0].length) { - match = next; - } - coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length; - } - // leave it in a clean state - coerceRtlRegex.lastIndex = -1; - } - - if (match === null) { - return null - } - - const major = match[2]; - const minor = match[3] || '0'; - const patch = match[4] || '0'; - const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : ''; - const build = options.includePrerelease && match[6] ? `+${match[6]}` : ''; - - return parse$1(`${major}.${minor}.${patch}${prerelease}${build}`, options) -}; -var coerce_1 = coerce$1; - -const Range$8 = requireRange(); - -// Mostly just for testing and legacy API reasons -const toComparators$1 = (range, options) => - new Range$8(range, options).set - .map(comp => comp.map(c => c.value).join(' ').trim().split(' ')); - -var toComparators_1 = toComparators$1; - -const SemVer$4 = semver$1; -const Range$7 = requireRange(); - -const maxSatisfying$1 = (versions, range, options) => { - let max = null; - let maxSV = null; - let rangeObj = null; - try { - rangeObj = new Range$7(range, options); - } catch (er) { - return null - } - versions.forEach((v) => { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!max || maxSV.compare(v) === -1) { - // compare(max, v, true) - max = v; - maxSV = new SemVer$4(max, options); - } - } - }); - return max -}; -var maxSatisfying_1 = maxSatisfying$1; - -const SemVer$3 = semver$1; -const Range$6 = requireRange(); -const minSatisfying$1 = (versions, range, options) => { - let min = null; - let minSV = null; - let rangeObj = null; - try { - rangeObj = new Range$6(range, options); - } catch (er) { - return null - } - versions.forEach((v) => { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!min || minSV.compare(v) === 1) { - // compare(min, v, true) - min = v; - minSV = new SemVer$3(min, options); - } - } - }); - return min -}; -var minSatisfying_1 = minSatisfying$1; - -const SemVer$2 = semver$1; -const Range$5 = requireRange(); -const gt$2 = gt_1; - -const minVersion$1 = (range, loose) => { - range = new Range$5(range, loose); - - let minver = new SemVer$2('0.0.0'); - if (range.test(minver)) { - return minver - } - - minver = new SemVer$2('0.0.0-0'); - if (range.test(minver)) { - return minver - } - - minver = null; - for (let i = 0; i < range.set.length; ++i) { - const comparators = range.set[i]; - - let setMin = null; - comparators.forEach((comparator) => { - // Clone to avoid manipulating the comparator's semver object. - const compver = new SemVer$2(comparator.semver.version); - switch (comparator.operator) { - case '>': - if (compver.prerelease.length === 0) { - compver.patch++; - } else { - compver.prerelease.push(0); - } - compver.raw = compver.format(); - /* fallthrough */ - case '': - case '>=': - if (!setMin || gt$2(compver, setMin)) { - setMin = compver; - } - break - case '<': - case '<=': - /* Ignore maximum versions */ - break - /* istanbul ignore next */ - default: - throw new Error(`Unexpected operation: ${comparator.operator}`) - } - }); - if (setMin && (!minver || gt$2(minver, setMin))) { - minver = setMin; - } - } - - if (minver && range.test(minver)) { - return minver - } - - return null -}; -var minVersion_1 = minVersion$1; - -const Range$4 = requireRange(); -const validRange$1 = (range, options) => { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range$4(range, options).range || '*' - } catch (er) { - return null - } -}; -var valid$1 = validRange$1; - -const SemVer$1 = semver$1; -const Comparator$2 = requireComparator(); -const { ANY: ANY$1 } = Comparator$2; -const Range$3 = requireRange(); -const satisfies$3 = satisfies_1; -const gt$1 = gt_1; -const lt$1 = lt_1; -const lte$1 = lte_1; -const gte$1 = gte_1; - -const outside$3 = (version, range, hilo, options) => { - version = new SemVer$1(version, options); - range = new Range$3(range, options); - - let gtfn, ltefn, ltfn, comp, ecomp; - switch (hilo) { - case '>': - gtfn = gt$1; - ltefn = lte$1; - ltfn = lt$1; - comp = '>'; - ecomp = '>='; - break - case '<': - gtfn = lt$1; - ltefn = gte$1; - ltfn = gt$1; - comp = '<'; - ecomp = '<='; - break - default: - throw new TypeError('Must provide a hilo val of "<" or ">"') - } - - // If it satisfies the range it is not outside - if (satisfies$3(version, range, options)) { - return false - } - - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. - - for (let i = 0; i < range.set.length; ++i) { - const comparators = range.set[i]; - - let high = null; - let low = null; - - comparators.forEach((comparator) => { - if (comparator.semver === ANY$1) { - comparator = new Comparator$2('>=0.0.0'); - } - high = high || comparator; - low = low || comparator; - if (gtfn(comparator.semver, high.semver, options)) { - high = comparator; - } else if (ltfn(comparator.semver, low.semver, options)) { - low = comparator; - } - }); - - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false - } - - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false - } - } - return true -}; - -var outside_1 = outside$3; - -// Determine if version is greater than all the versions possible in the range. -const outside$2 = outside_1; -const gtr$1 = (version, range, options) => outside$2(version, range, '>', options); -var gtr_1 = gtr$1; - -const outside$1 = outside_1; -// Determine if version is less than all the versions possible in the range -const ltr$1 = (version, range, options) => outside$1(version, range, '<', options); -var ltr_1 = ltr$1; - -const Range$2 = requireRange(); -const intersects$1 = (r1, r2, options) => { - r1 = new Range$2(r1, options); - r2 = new Range$2(r2, options); - return r1.intersects(r2, options) -}; -var intersects_1 = intersects$1; - -// given a set of versions and a range, create a "simplified" range -// that includes the same versions that the original range does -// If the original range is shorter than the simplified one, return that. -const satisfies$2 = satisfies_1; -const compare$2 = compare_1; -var simplify = (versions, range, options) => { - const set = []; - let first = null; - let prev = null; - const v = versions.sort((a, b) => compare$2(a, b, options)); - for (const version of v) { - const included = satisfies$2(version, range, options); - if (included) { - prev = version; - if (!first) { - first = version; - } - } else { - if (prev) { - set.push([first, prev]); - } - prev = null; - first = null; - } - } - if (first) { - set.push([first, null]); - } - - const ranges = []; - for (const [min, max] of set) { - if (min === max) { - ranges.push(min); - } else if (!max && min === v[0]) { - ranges.push('*'); - } else if (!max) { - ranges.push(`>=${min}`); - } else if (min === v[0]) { - ranges.push(`<=${max}`); - } else { - ranges.push(`${min} - ${max}`); - } - } - const simplified = ranges.join(' || '); - const original = typeof range.raw === 'string' ? range.raw : String(range); - return simplified.length < original.length ? simplified : range -}; - -const Range$1 = requireRange(); -const Comparator$1 = requireComparator(); -const { ANY } = Comparator$1; -const satisfies$1 = satisfies_1; -const compare$1 = compare_1; - -// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff: -// - Every simple range `r1, r2, ...` is a null set, OR -// - Every simple range `r1, r2, ...` which is not a null set is a subset of -// some `R1, R2, ...` -// -// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff: -// - If c is only the ANY comparator -// - If C is only the ANY comparator, return true -// - Else if in prerelease mode, return false -// - else replace c with `[>=0.0.0]` -// - If C is only the ANY comparator -// - if in prerelease mode, return true -// - else replace C with `[>=0.0.0]` -// - Let EQ be the set of = comparators in c -// - If EQ is more than one, return true (null set) -// - Let GT be the highest > or >= comparator in c -// - Let LT be the lowest < or <= comparator in c -// - If GT and LT, and GT.semver > LT.semver, return true (null set) -// - If any C is a = range, and GT or LT are set, return false -// - If EQ -// - If GT, and EQ does not satisfy GT, return true (null set) -// - If LT, and EQ does not satisfy LT, return true (null set) -// - If EQ satisfies every C, return true -// - Else return false -// - If GT -// - If GT.semver is lower than any > or >= comp in C, return false -// - If GT is >=, and GT.semver does not satisfy every C, return false -// - If GT.semver has a prerelease, and not in prerelease mode -// - If no C has a prerelease and the GT.semver tuple, return false -// - If LT -// - If LT.semver is greater than any < or <= comp in C, return false -// - If LT is <=, and LT.semver does not satisfy every C, return false -// - If GT.semver has a prerelease, and not in prerelease mode -// - If no C has a prerelease and the LT.semver tuple, return false -// - Else return true - -const subset$1 = (sub, dom, options = {}) => { - if (sub === dom) { - return true - } - - sub = new Range$1(sub, options); - dom = new Range$1(dom, options); - let sawNonNull = false; - - OUTER: for (const simpleSub of sub.set) { - for (const simpleDom of dom.set) { - const isSub = simpleSubset(simpleSub, simpleDom, options); - sawNonNull = sawNonNull || isSub !== null; - if (isSub) { - continue OUTER - } - } - // the null set is a subset of everything, but null simple ranges in - // a complex range should be ignored. so if we saw a non-null range, - // then we know this isn't a subset, but if EVERY simple range was null, - // then it is a subset. - if (sawNonNull) { - return false - } - } - return true -}; - -const minimumVersionWithPreRelease = [new Comparator$1('>=0.0.0-0')]; -const minimumVersion = [new Comparator$1('>=0.0.0')]; - -const simpleSubset = (sub, dom, options) => { - if (sub === dom) { - return true - } - - if (sub.length === 1 && sub[0].semver === ANY) { - if (dom.length === 1 && dom[0].semver === ANY) { - return true - } else if (options.includePrerelease) { - sub = minimumVersionWithPreRelease; - } else { - sub = minimumVersion; - } - } - - if (dom.length === 1 && dom[0].semver === ANY) { - if (options.includePrerelease) { - return true - } else { - dom = minimumVersion; - } - } - - const eqSet = new Set(); - let gt, lt; - for (const c of sub) { - if (c.operator === '>' || c.operator === '>=') { - gt = higherGT(gt, c, options); - } else if (c.operator === '<' || c.operator === '<=') { - lt = lowerLT(lt, c, options); - } else { - eqSet.add(c.semver); - } - } - - if (eqSet.size > 1) { - return null - } - - let gtltComp; - if (gt && lt) { - gtltComp = compare$1(gt.semver, lt.semver, options); - if (gtltComp > 0) { - return null - } else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) { - return null - } - } - - // will iterate one or zero times - for (const eq of eqSet) { - if (gt && !satisfies$1(eq, String(gt), options)) { - return null - } - - if (lt && !satisfies$1(eq, String(lt), options)) { - return null - } - - for (const c of dom) { - if (!satisfies$1(eq, String(c), options)) { - return false - } - } - - return true - } - - let higher, lower; - let hasDomLT, hasDomGT; - // if the subset has a prerelease, we need a comparator in the superset - // with the same tuple and a prerelease, or it's not a subset - let needDomLTPre = lt && - !options.includePrerelease && - lt.semver.prerelease.length ? lt.semver : false; - let needDomGTPre = gt && - !options.includePrerelease && - gt.semver.prerelease.length ? gt.semver : false; - // exception: <1.2.3-0 is the same as <1.2.3 - if (needDomLTPre && needDomLTPre.prerelease.length === 1 && - lt.operator === '<' && needDomLTPre.prerelease[0] === 0) { - needDomLTPre = false; - } - - for (const c of dom) { - hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='; - hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='; - if (gt) { - if (needDomGTPre) { - if (c.semver.prerelease && c.semver.prerelease.length && - c.semver.major === needDomGTPre.major && - c.semver.minor === needDomGTPre.minor && - c.semver.patch === needDomGTPre.patch) { - needDomGTPre = false; - } - } - if (c.operator === '>' || c.operator === '>=') { - higher = higherGT(gt, c, options); - if (higher === c && higher !== gt) { - return false - } - } else if (gt.operator === '>=' && !satisfies$1(gt.semver, String(c), options)) { - return false - } - } - if (lt) { - if (needDomLTPre) { - if (c.semver.prerelease && c.semver.prerelease.length && - c.semver.major === needDomLTPre.major && - c.semver.minor === needDomLTPre.minor && - c.semver.patch === needDomLTPre.patch) { - needDomLTPre = false; - } - } - if (c.operator === '<' || c.operator === '<=') { - lower = lowerLT(lt, c, options); - if (lower === c && lower !== lt) { - return false - } - } else if (lt.operator === '<=' && !satisfies$1(lt.semver, String(c), options)) { - return false - } - } - if (!c.operator && (lt || gt) && gtltComp !== 0) { - return false - } - } - - // if there was a < or >, and nothing in the dom, then must be false - // UNLESS it was limited by another range in the other direction. - // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0 - if (gt && hasDomLT && !lt && gtltComp !== 0) { - return false - } - - if (lt && hasDomGT && !gt && gtltComp !== 0) { - return false - } - - // we needed a prerelease range in a specific tuple, but didn't get one - // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0, - // because it includes prereleases in the 1.2.3 tuple - if (needDomGTPre || needDomLTPre) { - return false - } - - return true -}; - -// >=1.2.3 is lower than >1.2.3 -const higherGT = (a, b, options) => { - if (!a) { - return b - } - const comp = compare$1(a.semver, b.semver, options); - return comp > 0 ? a - : comp < 0 ? b - : b.operator === '>' && a.operator === '>=' ? b - : a -}; - -// <=1.2.3 is higher than <1.2.3 -const lowerLT = (a, b, options) => { - if (!a) { - return b - } - const comp = compare$1(a.semver, b.semver, options); - return comp < 0 ? a - : comp > 0 ? b - : b.operator === '<' && a.operator === '<=' ? b - : a -}; - -var subset_1 = subset$1; - -// just pre-load all the stuff that index.js lazily exports -const internalRe = reExports; -const constants = constants$1; -const SemVer = semver$1; -const identifiers = identifiers$1; -const parse = parse_1; -const valid = valid_1; -const clean = clean_1; -const inc = inc_1; -const diff = diff_1; -const major = major_1; -const minor = minor_1; -const patch = patch_1; -const prerelease = prerelease_1; -const compare = compare_1; -const rcompare = rcompare_1; -const compareLoose = compareLoose_1; -const compareBuild = compareBuild_1; -const sort = sort_1; -const rsort = rsort_1; -const gt = gt_1; -const lt = lt_1; -const eq = eq_1; -const neq = neq_1; -const gte = gte_1; -const lte = lte_1; -const cmp = cmp_1; -const coerce = coerce_1; -const Comparator = requireComparator(); -const Range = requireRange(); -const satisfies = satisfies_1; -const toComparators = toComparators_1; -const maxSatisfying = maxSatisfying_1; -const minSatisfying = minSatisfying_1; -const minVersion = minVersion_1; -const validRange = valid$1; -const outside = outside_1; -const gtr = gtr_1; -const ltr = ltr_1; -const intersects = intersects_1; -const simplifyRange = simplify; -const subset = subset_1; -var semver = { - parse, - valid, - clean, - inc, - diff, - major, - minor, - patch, - prerelease, - compare, - rcompare, - compareLoose, - compareBuild, - sort, - rsort, - gt, - lt, - eq, - neq, - gte, - lte, - cmp, - coerce, - Comparator, - Range, - satisfies, - toComparators, - maxSatisfying, - minSatisfying, - minVersion, - validRange, - outside, - gtr, - ltr, - intersects, - simplifyRange, - subset, - SemVer, - re: internalRe.re, - src: internalRe.src, - tokens: internalRe.t, - SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION, - RELEASE_TYPES: constants.RELEASE_TYPES, - compareIdentifiers: identifiers.compareIdentifiers, - rcompareIdentifiers: identifiers.rcompareIdentifiers, -}; - -async function fetchModules() { - const { modules } = await $fetch( - `https://api.nuxt.com/modules?version=all` - ); - return modules; -} -function checkNuxtCompatibility(module, nuxtVersion) { - if (!module.compatibility?.nuxt) { - return true; - } - return semver.satisfies(nuxtVersion, module.compatibility.nuxt, { - includePrerelease: true - }); -} -async function getNuxtVersion(cwd) { - const nuxtPkg = tryRequireModule("nuxt/package.json", cwd); - if (nuxtPkg) { - return nuxtPkg.version; - } - const pkg = await getProjectPackage(cwd); - const pkgDep = pkg?.dependencies?.["nuxt"] || pkg?.devDependencies?.["nuxt"]; - return pkgDep && semver.coerce(pkgDep)?.version || "3.0.0"; -} -async function getProjectPackage(cwd) { - return await tryRequireModule("./package.json", cwd); -} - -export { $fetch as $, Bn as B, getNuxtVersion as a, br as b, checkNuxtCompatibility as c, fetchModules as f, getProjectPackage as g, semver as s }; diff --git a/.pnpm-store/v3/files/3b/f1299e9874b4aa87e9c4316447b242e7e89a8394f873a1e78bb29ed8cc57d71b6dcef47cb51f53289fa28230ae82f2cd5b58fff39ee9948c34a09f381096de b/.pnpm-store/v3/files/3b/f1299e9874b4aa87e9c4316447b242e7e89a8394f873a1e78bb29ed8cc57d71b6dcef47cb51f53289fa28230ae82f2cd5b58fff39ee9948c34a09f381096de deleted file mode 100644 index 6a0f644dd00bf13b772f14a2a9303abedc9b6fb5..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/3b/f1299e9874b4aa87e9c4316447b242e7e89a8394f873a1e78bb29ed8cc57d71b6dcef47cb51f53289fa28230ae82f2cd5b58fff39ee9948c34a09f381096de +++ /dev/null @@ -1,427 +0,0 @@ -import { stdin, stdout } from 'node:process'; -import f from 'node:readline'; -import { WriteStream } from 'node:tty'; -import { i as isUnicodeSupported, a as colors, f as getDefaultExportFromCjs } from '../shared/nuxi.9edf0930.mjs'; -import tty__default from 'tty'; -import 'node:util'; -import 'node:path'; -import 'node:url'; - -const ESC = '\x1B'; -const CSI = `${ESC}[`; -const beep = '\u0007'; - -const cursor = { - to(x, y) { - if (!y) return `${CSI}${x + 1}G`; - return `${CSI}${y + 1};${x + 1}H`; - }, - move(x, y) { - let ret = ''; - - if (x < 0) ret += `${CSI}${-x}D`; - else if (x > 0) ret += `${CSI}${x}C`; - - if (y < 0) ret += `${CSI}${-y}A`; - else if (y > 0) ret += `${CSI}${y}B`; - - return ret; - }, - up: (count = 1) => `${CSI}${count}A`, - down: (count = 1) => `${CSI}${count}B`, - forward: (count = 1) => `${CSI}${count}C`, - backward: (count = 1) => `${CSI}${count}D`, - nextLine: (count = 1) => `${CSI}E`.repeat(count), - prevLine: (count = 1) => `${CSI}F`.repeat(count), - left: `${CSI}G`, - hide: `${CSI}?25l`, - show: `${CSI}?25h`, - save: `${ESC}7`, - restore: `${ESC}8` -}; - -const scroll = { - up: (count = 1) => `${CSI}S`.repeat(count), - down: (count = 1) => `${CSI}T`.repeat(count) -}; - -const erase = { - screen: `${CSI}2J`, - up: (count = 1) => `${CSI}1J`.repeat(count), - down: (count = 1) => `${CSI}J`.repeat(count), - line: `${CSI}2K`, - lineEnd: `${CSI}K`, - lineStart: `${CSI}1K`, - lines(count) { - let clear = ''; - for (let i = 0; i < count; i++) - clear += this.line + (i < count - 1 ? cursor.up() : ''); - if (count) - clear += cursor.left; - return clear; - } -}; - -var src = { cursor, scroll, erase, beep }; - -var picocolors = {exports: {}}; - -let tty = tty__default; - -let isColorSupported = - !("NO_COLOR" in process.env || process.argv.includes("--no-color")) && - ("FORCE_COLOR" in process.env || - process.argv.includes("--color") || - process.platform === "win32" || - (tty.isatty(1) && process.env.TERM !== "dumb") || - "CI" in process.env); - -let formatter = - (open, close, replace = open) => - input => { - let string = "" + input; - let index = string.indexOf(close, open.length); - return ~index - ? open + replaceClose(string, close, replace, index) + close - : open + string + close - }; - -let replaceClose = (string, close, replace, index) => { - let start = string.substring(0, index) + replace; - let end = string.substring(index + close.length); - let nextIndex = end.indexOf(close); - return ~nextIndex ? start + replaceClose(end, close, replace, nextIndex) : start + end -}; - -let createColors = (enabled = isColorSupported) => ({ - isColorSupported: enabled, - reset: enabled ? s => `\x1b[0m${s}\x1b[0m` : String, - bold: enabled ? formatter("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m") : String, - dim: enabled ? formatter("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m") : String, - italic: enabled ? formatter("\x1b[3m", "\x1b[23m") : String, - underline: enabled ? formatter("\x1b[4m", "\x1b[24m") : String, - inverse: enabled ? formatter("\x1b[7m", "\x1b[27m") : String, - hidden: enabled ? formatter("\x1b[8m", "\x1b[28m") : String, - strikethrough: enabled ? formatter("\x1b[9m", "\x1b[29m") : String, - black: enabled ? formatter("\x1b[30m", "\x1b[39m") : String, - red: enabled ? formatter("\x1b[31m", "\x1b[39m") : String, - green: enabled ? formatter("\x1b[32m", "\x1b[39m") : String, - yellow: enabled ? formatter("\x1b[33m", "\x1b[39m") : String, - blue: enabled ? formatter("\x1b[34m", "\x1b[39m") : String, - magenta: enabled ? formatter("\x1b[35m", "\x1b[39m") : String, - cyan: enabled ? formatter("\x1b[36m", "\x1b[39m") : String, - white: enabled ? formatter("\x1b[37m", "\x1b[39m") : String, - gray: enabled ? formatter("\x1b[90m", "\x1b[39m") : String, - bgBlack: enabled ? formatter("\x1b[40m", "\x1b[49m") : String, - bgRed: enabled ? formatter("\x1b[41m", "\x1b[49m") : String, - bgGreen: enabled ? formatter("\x1b[42m", "\x1b[49m") : String, - bgYellow: enabled ? formatter("\x1b[43m", "\x1b[49m") : String, - bgBlue: enabled ? formatter("\x1b[44m", "\x1b[49m") : String, - bgMagenta: enabled ? formatter("\x1b[45m", "\x1b[49m") : String, - bgCyan: enabled ? formatter("\x1b[46m", "\x1b[49m") : String, - bgWhite: enabled ? formatter("\x1b[47m", "\x1b[49m") : String, -}); - -picocolors.exports = createColors(); -picocolors.exports.createColors = createColors; - -var picocolorsExports = picocolors.exports; -const l = /*@__PURE__*/getDefaultExportFromCjs(picocolorsExports); - -function z({onlyFirst:t=!1}={}){const u=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"].join("|");return new RegExp(u,t?void 0:"g")}function $(t){if(typeof t!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof t}\``);return t.replace(z(),"")}var m={},G={get exports(){return m},set exports(t){m=t;}};(function(t){var u={};t.exports=u,u.eastAsianWidth=function(e){var s=e.charCodeAt(0),C=e.length==2?e.charCodeAt(1):0,D=s;return 55296<=s&&s<=56319&&56320<=C&&C<=57343&&(s&=1023,C&=1023,D=s<<10|C,D+=65536),D==12288||65281<=D&&D<=65376||65504<=D&&D<=65510?"F":D==8361||65377<=D&&D<=65470||65474<=D&&D<=65479||65482<=D&&D<=65487||65490<=D&&D<=65495||65498<=D&&D<=65500||65512<=D&&D<=65518?"H":4352<=D&&D<=4447||4515<=D&&D<=4519||4602<=D&&D<=4607||9001<=D&&D<=9002||11904<=D&&D<=11929||11931<=D&&D<=12019||12032<=D&&D<=12245||12272<=D&&D<=12283||12289<=D&&D<=12350||12353<=D&&D<=12438||12441<=D&&D<=12543||12549<=D&&D<=12589||12593<=D&&D<=12686||12688<=D&&D<=12730||12736<=D&&D<=12771||12784<=D&&D<=12830||12832<=D&&D<=12871||12880<=D&&D<=13054||13056<=D&&D<=19903||19968<=D&&D<=42124||42128<=D&&D<=42182||43360<=D&&D<=43388||44032<=D&&D<=55203||55216<=D&&D<=55238||55243<=D&&D<=55291||63744<=D&&D<=64255||65040<=D&&D<=65049||65072<=D&&D<=65106||65108<=D&&D<=65126||65128<=D&&D<=65131||110592<=D&&D<=110593||127488<=D&&D<=127490||127504<=D&&D<=127546||127552<=D&&D<=127560||127568<=D&&D<=127569||131072<=D&&D<=194367||177984<=D&&D<=196605||196608<=D&&D<=262141?"W":32<=D&&D<=126||162<=D&&D<=163||165<=D&&D<=166||D==172||D==175||10214<=D&&D<=10221||10629<=D&&D<=10630?"Na":D==161||D==164||167<=D&&D<=168||D==170||173<=D&&D<=174||176<=D&&D<=180||182<=D&&D<=186||188<=D&&D<=191||D==198||D==208||215<=D&&D<=216||222<=D&&D<=225||D==230||232<=D&&D<=234||236<=D&&D<=237||D==240||242<=D&&D<=243||247<=D&&D<=250||D==252||D==254||D==257||D==273||D==275||D==283||294<=D&&D<=295||D==299||305<=D&&D<=307||D==312||319<=D&&D<=322||D==324||328<=D&&D<=331||D==333||338<=D&&D<=339||358<=D&&D<=359||D==363||D==462||D==464||D==466||D==468||D==470||D==472||D==474||D==476||D==593||D==609||D==708||D==711||713<=D&&D<=715||D==717||D==720||728<=D&&D<=731||D==733||D==735||768<=D&&D<=879||913<=D&&D<=929||931<=D&&D<=937||945<=D&&D<=961||963<=D&&D<=969||D==1025||1040<=D&&D<=1103||D==1105||D==8208||8211<=D&&D<=8214||8216<=D&&D<=8217||8220<=D&&D<=8221||8224<=D&&D<=8226||8228<=D&&D<=8231||D==8240||8242<=D&&D<=8243||D==8245||D==8251||D==8254||D==8308||D==8319||8321<=D&&D<=8324||D==8364||D==8451||D==8453||D==8457||D==8467||D==8470||8481<=D&&D<=8482||D==8486||D==8491||8531<=D&&D<=8532||8539<=D&&D<=8542||8544<=D&&D<=8555||8560<=D&&D<=8569||D==8585||8592<=D&&D<=8601||8632<=D&&D<=8633||D==8658||D==8660||D==8679||D==8704||8706<=D&&D<=8707||8711<=D&&D<=8712||D==8715||D==8719||D==8721||D==8725||D==8730||8733<=D&&D<=8736||D==8739||D==8741||8743<=D&&D<=8748||D==8750||8756<=D&&D<=8759||8764<=D&&D<=8765||D==8776||D==8780||D==8786||8800<=D&&D<=8801||8804<=D&&D<=8807||8810<=D&&D<=8811||8814<=D&&D<=8815||8834<=D&&D<=8835||8838<=D&&D<=8839||D==8853||D==8857||D==8869||D==8895||D==8978||9312<=D&&D<=9449||9451<=D&&D<=9547||9552<=D&&D<=9587||9600<=D&&D<=9615||9618<=D&&D<=9621||9632<=D&&D<=9633||9635<=D&&D<=9641||9650<=D&&D<=9651||9654<=D&&D<=9655||9660<=D&&D<=9661||9664<=D&&D<=9665||9670<=D&&D<=9672||D==9675||9678<=D&&D<=9681||9698<=D&&D<=9701||D==9711||9733<=D&&D<=9734||D==9737||9742<=D&&D<=9743||9748<=D&&D<=9749||D==9756||D==9758||D==9792||D==9794||9824<=D&&D<=9825||9827<=D&&D<=9829||9831<=D&&D<=9834||9836<=D&&D<=9837||D==9839||9886<=D&&D<=9887||9918<=D&&D<=9919||9924<=D&&D<=9933||9935<=D&&D<=9953||D==9955||9960<=D&&D<=9983||D==10045||D==10071||10102<=D&&D<=10111||11093<=D&&D<=11097||12872<=D&&D<=12879||57344<=D&&D<=63743||65024<=D&&D<=65039||D==65533||127232<=D&&D<=127242||127248<=D&&D<=127277||127280<=D&&D<=127337||127344<=D&&D<=127386||917760<=D&&D<=917999||983040<=D&&D<=1048573||1048576<=D&&D<=1114109?"A":"N"},u.characterLength=function(e){var s=this.eastAsianWidth(e);return s=="F"||s=="W"||s=="A"?2:1};function F(e){return e.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g)||[]}u.length=function(e){for(var s=F(e),C=0,D=0;D=s-(n==2?1:0))if(i+n<=C)D+=a;else break;i+=n;}return D};})(G);const K=m;var Y=function(){return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g};function c(t,u={}){if(typeof t!="string"||t.length===0||(u={ambiguousIsNarrow:!0,...u},t=$(t),t.length===0))return 0;t=t.replace(Y()," ");const F=u.ambiguousIsNarrow?1:2;let e=0;for(const s of t){const C=s.codePointAt(0);if(C<=31||C>=127&&C<=159||C>=768&&C<=879)continue;switch(K.eastAsianWidth(s)){case"F":case"W":e+=2;break;case"A":e+=F;break;default:e+=1;}}return e}const v=10,L=(t=0)=>u=>`\x1B[${u+t}m`,M=(t=0)=>u=>`\x1B[${38+t};5;${u}m`,T=(t=0)=>(u,F,e)=>`\x1B[${38+t};2;${u};${F};${e}m`,r={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};Object.keys(r.modifier);const Z=Object.keys(r.color),H=Object.keys(r.bgColor);[...Z,...H];function U(){const t=new Map;for(const[u,F]of Object.entries(r)){for(const[e,s]of Object.entries(F))r[e]={open:`\x1B[${s[0]}m`,close:`\x1B[${s[1]}m`},F[e]=r[e],t.set(s[0],s[1]);Object.defineProperty(r,u,{value:F,enumerable:!1});}return Object.defineProperty(r,"codes",{value:t,enumerable:!1}),r.color.close="\x1B[39m",r.bgColor.close="\x1B[49m",r.color.ansi=L(),r.color.ansi256=M(),r.color.ansi16m=T(),r.bgColor.ansi=L(v),r.bgColor.ansi256=M(v),r.bgColor.ansi16m=T(v),Object.defineProperties(r,{rgbToAnsi256:{value:(u,F,e)=>u===F&&F===e?u<8?16:u>248?231:Math.round((u-8)/247*24)+232:16+36*Math.round(u/255*5)+6*Math.round(F/255*5)+Math.round(e/255*5),enumerable:!1},hexToRgb:{value:u=>{const F=/[a-f\d]{6}|[a-f\d]{3}/i.exec(u.toString(16));if(!F)return [0,0,0];let[e]=F;e.length===3&&(e=[...e].map(C=>C+C).join(""));const s=Number.parseInt(e,16);return [s>>16&255,s>>8&255,s&255]},enumerable:!1},hexToAnsi256:{value:u=>r.rgbToAnsi256(...r.hexToRgb(u)),enumerable:!1},ansi256ToAnsi:{value:u=>{if(u<8)return 30+u;if(u<16)return 90+(u-8);let F,e,s;if(u>=232)F=((u-232)*10+8)/255,e=F,s=F;else {u-=16;const i=u%36;F=Math.floor(u/36)/5,e=Math.floor(i/6)/5,s=i%6/5;}const C=Math.max(F,e,s)*2;if(C===0)return 30;let D=30+(Math.round(s)<<2|Math.round(e)<<1|Math.round(F));return C===2&&(D+=60),D},enumerable:!1},rgbToAnsi:{value:(u,F,e)=>r.ansi256ToAnsi(r.rgbToAnsi256(u,F,e)),enumerable:!1},hexToAnsi:{value:u=>r.ansi256ToAnsi(r.hexToAnsi256(u)),enumerable:!1}}),r}const q=U(),p=new Set(["\x1B","\x9B"]),J=39,b="\x07",W="[",Q="]",I="m",w=`${Q}8;;`,N=t=>`${p.values().next().value}${W}${t}${I}`,j=t=>`${p.values().next().value}${w}${t}${b}`,X=t=>t.split(" ").map(u=>c(u)),_=(t,u,F)=>{const e=[...u];let s=!1,C=!1,D=c($(t[t.length-1]));for(const[i,o]of e.entries()){const E=c(o);if(D+E<=F?t[t.length-1]+=o:(t.push(o),D=0),p.has(o)&&(s=!0,C=e.slice(i+1).join("").startsWith(w)),s){C?o===b&&(s=!1,C=!1):o===I&&(s=!1);continue}D+=E,D===F&&i0&&t.length>1&&(t[t.length-2]+=t.pop());},DD=t=>{const u=t.split(" ");let F=u.length;for(;F>0&&!(c(u[F-1])>0);)F--;return F===u.length?t:u.slice(0,F).join(" ")+u.slice(F).join("")},uD=(t,u,F={})=>{if(F.trim!==!1&&t.trim()==="")return "";let e="",s,C;const D=X(t);let i=[""];for(const[E,a]of t.split(" ").entries()){F.trim!==!1&&(i[i.length-1]=i[i.length-1].trimStart());let n=c(i[i.length-1]);if(E!==0&&(n>=u&&(F.wordWrap===!1||F.trim===!1)&&(i.push(""),n=0),(n>0||F.trim===!1)&&(i[i.length-1]+=" ",n++)),F.hard&&D[E]>u){const B=u-n,A=1+Math.floor((D[E]-B-1)/u);Math.floor((D[E]-1)/u)u&&n>0&&D[E]>0){if(F.wordWrap===!1&&nu&&F.wordWrap===!1){_(i,a,u);continue}i[i.length-1]+=a;}F.trim!==!1&&(i=i.map(E=>DD(E)));const o=[...i.join(` -`)];for(const[E,a]of o.entries()){if(e+=a,p.has(a)){const{groups:B}=new RegExp(`(?:\\${W}(?\\d+)m|\\${w}(?.*)${b})`).exec(o.slice(E).join(""))||{groups:{}};if(B.code!==void 0){const A=Number.parseFloat(B.code);s=A===J?void 0:A;}else B.uri!==void 0&&(C=B.uri.length===0?void 0:B.uri);}const n=q.codes.get(Number(s));o[E+1]===` -`?(C&&(e+=j("")),s&&n&&(e+=N(n))):a===` -`&&(s&&n&&(e+=N(s)),C&&(e+=j(C)));}return e};function P(t,u,F){return String(t).normalize().replace(/\r\n/g,` -`).split(` -`).map(e=>uD(e,u,F)).join(` -`)}function FD(t,u){if(t===u)return;const F=t.split(` -`),e=u.split(` -`),s=[];for(let C=0;C{this._track&&(this.value=this.rl.line.replace(/\t/g,""),this._cursor=this.rl.cursor,this.emit("value",this.value)),s();},this.input.pipe(u),this.rl=f.createInterface({input:this.input,output:u,tabSize:2,prompt:"",escapeCodeTimeout:50}),f.emitKeypressEvents(this.input,this.rl),this.rl.prompt(),this.opts.initialValue!==void 0&&this._track&&this.rl.write(this.opts.initialValue),this.input.on("keypress",this.onKeypress),g(this.input,!0),this.output.on("resize",this.render),this.render(),new Promise((F,e)=>{this.once("submit",()=>{this.output.write(src.cursor.show),this.output.off("resize",this.render),g(this.input,!1),F(this.value);}),this.once("cancel",()=>{this.output.write(src.cursor.show),this.output.off("resize",this.render),g(this.input,!1),F(R);});})}on(u,F){const e=this.subscribers.get(u)??[];e.push({cb:F}),this.subscribers.set(u,e);}once(u,F){const e=this.subscribers.get(u)??[];e.push({cb:F,once:!0}),this.subscribers.set(u,e);}emit(u,...F){const e=this.subscribers.get(u)??[],s=[];for(const C of e)C.cb(...F),C.once&&s.push(()=>e.splice(e.indexOf(C),1));for(const C of s)C();}unsubscribe(){this.subscribers.clear();}onKeypress(u,F){if(this.state==="error"&&(this.state="active"),F?.name&&!this._track&&V.has(F.name)&&this.emit("cursor",V.get(F.name)),F?.name&&tD.has(F.name)&&this.emit("cursor",F.name),u&&(u.toLowerCase()==="y"||u.toLowerCase()==="n")&&this.emit("confirm",u.toLowerCase()==="y"),u&&this.emit("key",u.toLowerCase()),F?.name==="return"){if(this.opts.validate){const e=this.opts.validate(this.value);e&&(this.error=e,this.state="error",this.rl.write(this.value));}this.state!=="error"&&(this.state="submit");}u===""&&(this.state="cancel"),(this.state==="submit"||this.state==="cancel")&&this.emit("finalize"),this.render(),(this.state==="submit"||this.state==="cancel")&&this.close();}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(` -`),g(this.input,!1),this.rl.close(),this.emit(`${this.state}`,this.value),this.unsubscribe();}restoreCursor(){const u=P(this._prevFrame,process.stdout.columns,{hard:!0}).split(` -`).length-1;this.output.write(src.cursor.move(-999,u*-1));}render(){const u=P(this._render(this)??"",process.stdout.columns,{hard:!0});if(u!==this._prevFrame){if(this.state==="initial")this.output.write(src.cursor.hide);else {const F=FD(this._prevFrame,u);if(this.restoreCursor(),F&&F?.length===1){const e=F[0];this.output.write(src.cursor.move(0,e)),this.output.write(src.erase.lines(1));const s=u.split(` -`);this.output.write(s[e]),this._prevFrame=u,this.output.write(src.cursor.move(0,s.length-e-1));return}else if(F&&F?.length>1){const e=F[0];this.output.write(src.cursor.move(0,e)),this.output.write(src.erase.down());const C=u.split(` -`).slice(e);this.output.write(C.join(` -`)),this._prevFrame=u;return}this.output.write(src.erase.down());}this.output.write(u),this.state==="initial"&&(this.state="active"),this._prevFrame=u;}}}class sD extends h{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(u){super(u,!1),this.value=!!u.initialValue,this.on("value",()=>{this.value=this._value;}),this.on("confirm",F=>{this.output.write(src.cursor.move(0,-1)),this.value=F,this.state="submit",this.close();}),this.on("cursor",()=>{this.value=!this.value;});}}class iD extends h{constructor(u){super(u,!1),this.cursor=0,this.options=u.options,this.value=[...u.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:F})=>F===u.cursorAt),0),this.on("key",F=>{F==="a"&&this.toggleAll();}),this.on("cursor",F=>{switch(F){case"left":case"up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break;case"space":this.toggleValue();break}});}get _value(){return this.options[this.cursor].value}toggleAll(){const u=this.value.length===this.options.length;this.value=u?[]:this.options.map(F=>F.value);}toggleValue(){const u=this.value.includes(this._value);this.value=u?this.value.filter(F=>F!==this._value):[...this.value,this._value];}}class ED extends h{constructor(u){super(u,!1),this.cursor=0,this.options=u.options,this.cursor=this.options.findIndex(({value:F})=>F===u.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",F=>{switch(F){case"left":case"up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case"down":case"right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue();});}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value;}}class oD extends h{constructor(u){super(u),this.valueWithCursor="",this.on("finalize",()=>{this.value||(this.value=u.defaultValue),this.valueWithCursor=this.value;}),this.on("value",()=>{if(this.cursor>=this.value.length)this.valueWithCursor=`${this.value}${l.inverse(l.hidden("_"))}`;else {const F=this.value.slice(0,this.cursor),e=this.value.slice(this.cursor);this.valueWithCursor=`${F}${l.inverse(e[0])}${e.slice(1)}`;}});}get cursor(){return this._cursor}} - -const unicode = isUnicodeSupported(); -const s = (c, fallback) => unicode ? c : fallback; -const S_STEP_ACTIVE = s("\u276F", ">"); -const S_STEP_CANCEL = s("\u25A0", "x"); -const S_STEP_ERROR = s("\u25B2", "x"); -const S_STEP_SUBMIT = s("\u2714", "\u221A"); -const S_BAR = ""; -const S_BAR_END = ""; -const S_RADIO_ACTIVE = s("\u25CF", ">"); -const S_RADIO_INACTIVE = s("\u25CB", " "); -const S_CHECKBOX_ACTIVE = s("\u25FB", "[\u2022]"); -const S_CHECKBOX_SELECTED = s("\u25FC", "[+]"); -const S_CHECKBOX_INACTIVE = s("\u25FB", "[ ]"); -const symbol = (state) => { - switch (state) { - case "initial": - case "active": { - return colors.cyan(S_STEP_ACTIVE); - } - case "cancel": { - return colors.red(S_STEP_CANCEL); - } - case "error": { - return colors.yellow(S_STEP_ERROR); - } - case "submit": { - return colors.green(S_STEP_SUBMIT); - } - } -}; -const text = (opts) => { - return new oD({ - validate: opts.validate, - placeholder: opts.placeholder, - defaultValue: opts.defaultValue, - initialValue: opts.initialValue, - render() { - const title = `${colors.gray(S_BAR)} -${symbol(this.state)} ${opts.message} -`; - const placeholder = opts.placeholder ? colors.inverse(opts.placeholder[0]) + colors.dim(opts.placeholder.slice(1)) : colors.inverse(colors.hidden("_")); - const value = this.value ? this.valueWithCursor : placeholder; - switch (this.state) { - case "error": { - return `${title.trim()} -${colors.yellow( - S_BAR - )} ${value} -${colors.yellow(S_BAR_END)} ${colors.yellow( - this.error - )} -`; - } - case "submit": { - return `${title}${colors.gray(S_BAR)} ${colors.dim( - this.value || opts.placeholder - )}`; - } - case "cancel": { - return `${title}${colors.gray(S_BAR)} ${colors.strikethrough( - colors.dim(this.value ?? "") - )}${this.value?.trim() ? "\n" + colors.gray(S_BAR) : ""}`; - } - default: { - return `${title}${colors.cyan(S_BAR)} ${value} -${colors.cyan( - S_BAR_END - )} -`; - } - } - } - }).prompt(); -}; -const confirm = (opts) => { - const active = opts.active ?? "Yes"; - const inactive = opts.inactive ?? "No"; - return new sD({ - active, - inactive, - initialValue: opts.initialValue ?? true, - render() { - const title = `${colors.gray(S_BAR)} -${symbol(this.state)} ${opts.message} -`; - const value = this.value ? active : inactive; - switch (this.state) { - case "submit": { - return `${title}${colors.gray(S_BAR)} ${colors.dim(value)}`; - } - case "cancel": { - return `${title}${colors.gray(S_BAR)} ${colors.strikethrough( - colors.dim(value) - )} -${colors.gray(S_BAR)}`; - } - default: { - return `${title}${colors.cyan(S_BAR)} ${this.value ? `${colors.green(S_RADIO_ACTIVE)} ${active}` : `${colors.dim(S_RADIO_INACTIVE)} ${colors.dim(active)}`} ${colors.dim("/")} ${this.value ? `${colors.dim(S_RADIO_INACTIVE)} ${colors.dim(inactive)}` : `${colors.green(S_RADIO_ACTIVE)} ${inactive}`} -${colors.cyan(S_BAR_END)} -`; - } - } - } - }).prompt(); -}; -const select = (opts) => { - const opt = (option, state) => { - const label = option.label ?? String(option.value); - switch (state) { - case "active": { - return `${colors.green(S_RADIO_ACTIVE)} ${label} ${option.hint ? colors.dim(`(${option.hint})`) : ""}`; - } - case "selected": { - return `${colors.dim(label)}`; - } - case "cancelled": { - return `${colors.strikethrough(colors.dim(label))}`; - } - } - return `${colors.dim(S_RADIO_INACTIVE)} ${colors.dim(label)}`; - }; - return new ED({ - options: opts.options, - initialValue: opts.initialValue, - render() { - const title = `${colors.gray(S_BAR)} -${symbol(this.state)} ${opts.message} -`; - switch (this.state) { - case "submit": { - return `${title}${colors.gray(S_BAR)} ${opt( - this.options[this.cursor], - "selected" - )}`; - } - case "cancel": { - return `${title}${colors.gray(S_BAR)} ${opt( - this.options[this.cursor], - "cancelled" - )} -${colors.gray(S_BAR)}`; - } - default: { - return `${title}${colors.cyan(S_BAR)} ${this.options.map( - (option, i) => opt(option, i === this.cursor ? "active" : "inactive") - ).join(` -${colors.cyan(S_BAR)} `)} -${colors.cyan(S_BAR_END)} -`; - } - } - } - }).prompt(); -}; -const multiselect = (opts) => { - const opt = (option, state) => { - const label = option.label ?? String(option.value); - switch (state) { - case "active": { - return `${colors.cyan(S_CHECKBOX_ACTIVE)} ${label} ${option.hint ? colors.dim(`(${option.hint})`) : ""}`; - } - case "selected": { - return `${colors.green(S_CHECKBOX_SELECTED)} ${colors.dim(label)}`; - } - case "cancelled": { - return `${colors.strikethrough(colors.dim(label))}`; - } - case "active-selected": { - return `${colors.green(S_CHECKBOX_SELECTED)} ${label} ${option.hint ? colors.dim(`(${option.hint})`) : ""}`; - } - case "submitted": { - return `${colors.dim(label)}`; - } - } - return `${colors.dim(S_CHECKBOX_INACTIVE)} ${colors.dim(label)}`; - }; - return new iD({ - options: opts.options, - initialValues: opts.initialValues, - required: opts.required ?? true, - cursorAt: opts.cursorAt, - validate(selected) { - if (this.required && selected.length === 0) { - return `Please select at least one option. -${colors.reset( - colors.dim( - `Press ${colors.gray( - colors.bgWhite(colors.inverse(" space ")) - )} to select, ${colors.gray( - colors.bgWhite(colors.inverse(" enter ")) - )} to submit` - ) - )}`; - } - }, - render() { - const title = `${colors.gray(S_BAR)} -${symbol(this.state)} ${opts.message} -`; - switch (this.state) { - case "submit": { - return `${title}${colors.gray(S_BAR)} ${this.options.filter(({ value }) => this.value.includes(value)).map((option) => opt(option, "submitted")).join(colors.dim(", ")) || colors.dim("none")}`; - } - case "cancel": { - const label = this.options.filter(({ value }) => this.value.includes(value)).map((option) => opt(option, "cancelled")).join(colors.dim(", ")); - return `${title}${colors.gray(S_BAR)} ${label.trim() ? `${label} -${colors.gray(S_BAR)}` : ""}`; - } - case "error": { - const footer = this.error.split("\n").map( - (ln, i) => i === 0 ? `${colors.yellow(S_BAR_END)} ${colors.yellow(ln)}` : ` ${ln}` - ).join("\n"); - return title + colors.yellow(S_BAR) + " " + this.options.map((option, i) => { - const selected = this.value.includes(option.value); - const active = i === this.cursor; - if (active && selected) { - return opt(option, "active-selected"); - } - if (selected) { - return opt(option, "selected"); - } - return opt(option, active ? "active" : "inactive"); - }).join(` -${colors.yellow(S_BAR)} `) + "\n" + footer + "\n"; - } - default: { - return `${title}${colors.cyan(S_BAR)} ${this.options.map((option, i) => { - const selected = this.value.includes(option.value); - const active = i === this.cursor; - if (active && selected) { - return opt(option, "active-selected"); - } - if (selected) { - return opt(option, "selected"); - } - return opt(option, active ? "active" : "inactive"); - }).join(` -${colors.cyan(S_BAR)} `)} -${colors.cyan(S_BAR_END)} -`; - } - } - } - }).prompt(); -}; - -async function prompt(message, opts = {}) { - if (!opts.type || opts.type === "text") { - return await text({ - message, - defaultValue: opts.default, - placeholder: opts.placeholder, - initialValue: opts.initial - }); - } - if (opts.type === "confirm") { - return await confirm({ - message, - initialValue: opts.initial - }); - } - if (opts.type === "select") { - return await select({ - message, - options: opts.options.map( - (o) => typeof o === "string" ? { value: o, label: o } : o - ) - }); - } - if (opts.type === "multiselect") { - return await multiselect({ - message, - options: opts.options.map( - (o) => typeof o === "string" ? { value: o, label: o } : o - ), - required: opts.required - }); - } - throw new Error(`Unknown prompt type: ${opts.type}`); -} - -export { prompt }; diff --git a/.pnpm-store/v3/files/3d/2d3c15ab6149c0a115e870b0978a8cdce7d229b90ad0c4c0933a52f30beac6ceeb7f61831d67b7128e651cccdcf65a6ed69c3b25a4bf1d7fc96272814cfd17 b/.pnpm-store/v3/files/3d/2d3c15ab6149c0a115e870b0978a8cdce7d229b90ad0c4c0933a52f30beac6ceeb7f61831d67b7128e651cccdcf65a6ed69c3b25a4bf1d7fc96272814cfd17 deleted file mode 100644 index 75816f5ea31c5619f1faf40ad7f66a09bf71b2b9..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/3d/2d3c15ab6149c0a115e870b0978a8cdce7d229b90ad0c4c0933a52f30beac6ceeb7f61831d67b7128e651cccdcf65a6ed69c3b25a4bf1d7fc96272814cfd17 +++ /dev/null @@ -1,29902 +0,0 @@ -import { createServer as createServer$2 } from 'node:http'; -import { createServer as createServer$1 } from 'node:https'; -import { promisify } from 'node:util'; -import { createServer } from 'node:net'; -import os, { networkInterfaces } from 'node:os'; -import { g as getDefaultExportFromCjs, c as commonjsGlobal } from '../shared/nuxi.2155838d.mjs'; -import require$$2 from 'http'; -import require$$1 from 'https'; -import { c as consola, g as getColor, a as colors, b as d } from '../shared/nuxi.9edf0930.mjs'; -import { join } from 'node:path'; -import 'node:process'; -import 'node:tty'; -import { d as defu } from '../shared/nuxi.eaa29140.mjs'; -import childProcess from 'node:child_process'; -import fs, { statSync, readFileSync, promises, accessSync, constants } from 'node:fs'; -import require$$1$1 from 'crypto'; -import 'node:fs/promises'; -import { a as relative } from '../shared/nuxi.610c92ff.mjs'; -import 'node:url'; - -const unsafePorts = /* @__PURE__ */ new Set([ - 1, - // tcpmux - 7, - // echo - 9, - // discard - 11, - // systat - 13, - // daytime - 15, - // netstat - 17, - // qotd - 19, - // chargen - 20, - // ftp data - 21, - // ftp access - 22, - // ssh - 23, - // telnet - 25, - // smtp - 37, - // time - 42, - // name - 43, - // nicname - 53, - // domain - 69, - // tftp - 77, - // priv-rjs - 79, - // finger - 87, - // ttylink - 95, - // supdup - 101, - // hostriame - 102, - // iso-tsap - 103, - // gppitnp - 104, - // acr-nema - 109, - // pop2 - 110, - // pop3 - 111, - // sunrpc - 113, - // auth - 115, - // sftp - 117, - // uucp-path - 119, - // nntp - 123, - // NTP - 135, - // loc-srv /epmap - 137, - // netbios - 139, - // netbios - 143, - // imap2 - 161, - // snmp - 179, - // BGP - 389, - // ldap - 427, - // SLP (Also used by Apple Filing Protocol) - 465, - // smtp+ssl - 512, - // print / exec - 513, - // login - 514, - // shell - 515, - // printer - 526, - // tempo - 530, - // courier - 531, - // chat - 532, - // netnews - 540, - // uucp - 548, - // AFP (Apple Filing Protocol) - 554, - // rtsp - 556, - // remotefs - 563, - // nntp+ssl - 587, - // smtp (rfc6409) - 601, - // syslog-conn (rfc3195) - 636, - // ldap+ssl - 989, - // ftps-data - 990, - // ftps - 993, - // ldap+ssl - 995, - // pop3+ssl - 1719, - // h323gatestat - 1720, - // h323hostcall - 1723, - // pptp - 2049, - // nfs - 3659, - // apple-sasl / PasswordServer - 4045, - // lockd - 5060, - // sip - 5061, - // sips - 6e3, - // X11 - 6566, - // sane-port - 6665, - // Alternate IRC [Apple addition] - 6666, - // Alternate IRC [Apple addition] - 6667, - // Standard IRC [Apple addition] - 6668, - // Alternate IRC [Apple addition] - 6669, - // Alternate IRC [Apple addition] - 6697, - // IRC + TLS - 10080 - // Amanda -]); -function isUnsafePort(port) { - return unsafePorts.has(port); -} -function isSafePort(port) { - return !isUnsafePort(port); -} - -var __defProp$1 = Object.defineProperty; -var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; -var __publicField$1 = (obj, key, value) => { - __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value); - return value; -}; -class GetPortError extends Error { - constructor(message, opts) { - super(message, opts); - this.message = message; - __publicField$1(this, "name", "GetPortError"); - } -} -function _log(verbose, message) { - if (verbose) { - console.log(`[get-port] ${message}`); - } -} -function _generateRange(from, to) { - if (to < from) { - return []; - } - const r = []; - for (let index = from; index <= to; index++) { - r.push(index); - } - return r; -} -function _tryPort(port, host) { - return new Promise((resolve) => { - const server = createServer(); - server.unref(); - server.on("error", () => { - resolve(false); - }); - server.listen({ port, host }, () => { - const { port: port2 } = server.address(); - server.close(() => { - resolve(isSafePort(port2) && port2); - }); - }); - }); -} -function _getLocalHosts(additional) { - const hosts = new Set(additional); - for (const _interface of Object.values(networkInterfaces())) { - for (const config of _interface || []) { - if (config.address && !config.internal && !config.address.startsWith("fe80::")) { - hosts.add(config.address); - } - } - } - return [...hosts]; -} -async function _findPort(ports, host) { - for (const port of ports) { - const r = await _tryPort(port, host); - if (r) { - return r; - } - } -} -function _fmtOnHost(hostname) { - return hostname ? `on host ${JSON.stringify(hostname)}` : "on any host"; -} -const HOSTNAME_RE$1 = /^(?!-)[\d.:A-Za-z-]{1,63}(? { - if (!port) { - return false; - } - if (!isSafePort(port)) { - _log(options.verbose, `Ignoring unsafe port: ${port}`); - return false; - } - return true; - }); - if (portsToCheck.length === 0) { - portsToCheck.push(3e3); - } - let availablePort = await _findPort(portsToCheck, options.host); - if (!availablePort && options.alternativePortRange.length > 0) { - availablePort = await _findPort( - _generateRange(...options.alternativePortRange), - options.host - ); - if (portsToCheck.length > 0) { - let message = `Unable to find an available port (tried ${portsToCheck.join( - "-" - )} ${_fmtOnHost(options.host)}).`; - if (availablePort) { - message += ` Using alternative port ${availablePort}.`; - } - _log(options.verbose, message); - } - } - if (!availablePort && _userOptions.random !== false) { - availablePort = await getRandomPort(options.host); - if (availablePort) { - _log(options.verbose, `Using random port ${availablePort}`); - } - } - if (!availablePort) { - const triedRanges = [ - options.port, - options.portRange.join("-"), - options.alternativePortRange.join("-") - ].filter(Boolean).join(", "); - throw new GetPortError( - `Unable to find an available port ${_fmtOnHost( - options.host - )} (tried ${triedRanges})` - ); - } - return availablePort; -} -async function getRandomPort(host) { - const port = await checkPort(0, host); - if (port === false) { - throw new GetPortError(`Unable to find a random port ${_fmtOnHost(host)}`); - } - return port; -} -async function checkPort(port, host = process.env.HOST, verbose) { - if (!host) { - host = _getLocalHosts([void 0, "0.0.0.0"]); - } - if (!Array.isArray(host)) { - return _tryPort(port, host); - } - for (const _host of host) { - const _port = await _tryPort(port, _host); - if (_port === false) { - if (port < 1024 && verbose) { - _log( - verbose, - `Unable to listen to the privileged port ${port} ${_fmtOnHost( - _host - )}` - ); - } - return false; - } - if (port === 0 && _port !== 0) { - port = _port; - } - } - return port; -} - -var httpShutdown = {exports: {}}; - -(function (module, exports) { - var http = require$$2; - var https = require$$1; - - /** - * Expose `addShutdown`. - */ - exports = module.exports = addShutdown; - - /** - * Adds shutdown functionaility to the `http.Server` object - * @param {http.Server} server The server to add shutdown functionaility to - */ - function addShutdown(server) { - var connections = {}; - var isShuttingDown = false; - var connectionCounter = 0; - - function destroy(socket, force) { - if (force || (socket._isIdle && isShuttingDown)) { - socket.destroy(); - delete connections[socket._connectionId]; - } - } - function onConnection(socket) { - var id = connectionCounter++; - socket._isIdle = true; - socket._connectionId = id; - connections[id] = socket; - - socket.on('close', function() { - delete connections[id]; - }); - } - server.on('request', function(req, res) { - req.socket._isIdle = false; - - res.on('finish', function() { - req.socket._isIdle = true; - destroy(req.socket); - }); - }); - - server.on('connection', onConnection); - server.on('secureConnection', onConnection); - - function shutdown(force, cb) { - isShuttingDown = true; - server.close(function(err) { - if (cb) { - process.nextTick(function() { cb(err); }); - } - }); - - Object.keys(connections).forEach(function(key) { - destroy(connections[key], force); - }); - } - server.shutdown = function(cb) { - shutdown(false, cb); - }; - - server.forceShutdown = function(cb) { - shutdown(true, cb); - }; - - return server; - } - /** - * Extends the {http.Server} object with shutdown functionaility. - * @return {http.Server} The decorated server object - */ - exports.extend = function() { - http.Server.prototype.withShutdown = function() { - return addShutdown(this); - }; - - https.Server.prototype.withShutdown = function() { - return addShutdown(this); - }; - }; -} (httpShutdown, httpShutdown.exports)); - -var httpShutdownExports = httpShutdown.exports; -const addShutdown = /*@__PURE__*/getDefaultExportFromCjs(httpShutdownExports); - -var QrCodeDataType = /* @__PURE__ */ ((QrCodeDataType2) => { - QrCodeDataType2[QrCodeDataType2["Border"] = -1] = "Border"; - QrCodeDataType2[QrCodeDataType2["Data"] = 0] = "Data"; - QrCodeDataType2[QrCodeDataType2["Function"] = 1] = "Function"; - QrCodeDataType2[QrCodeDataType2["Position"] = 2] = "Position"; - QrCodeDataType2[QrCodeDataType2["Timing"] = 3] = "Timing"; - QrCodeDataType2[QrCodeDataType2["Alignment"] = 4] = "Alignment"; - return QrCodeDataType2; -})(QrCodeDataType || {}); - -var __defProp = Object.defineProperty; -var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; -var __publicField = (obj, key, value) => { - __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); - return value; -}; -const LOW = [0, 1]; -const MEDIUM = [1, 0]; -const QUARTILE = [2, 3]; -const HIGH = [3, 2]; -const EccMap = { - L: LOW, - M: MEDIUM, - Q: QUARTILE, - H: HIGH -}; -const NUMERIC_REGEX = /^[0-9]*$/; -const ALPHANUMERIC_REGEX = /^[A-Z0-9 $%*+.\/:-]*$/; -const ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; -const MIN_VERSION = 1; -const MAX_VERSION = 40; -const PENALTY_N1 = 3; -const PENALTY_N2 = 3; -const PENALTY_N3 = 40; -const PENALTY_N4 = 10; -const ECC_CODEWORDS_PER_BLOCK = [ - // Version: (note that index 0 is for padding, and is set to an illegal value) - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - [-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], - // Low - [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28], - // Medium - [-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], - // Quartile - [-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30] - // High -]; -const NUM_ERROR_CORRECTION_BLOCKS = [ - // Version: (note that index 0 is for padding, and is set to an illegal value) - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - [-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25], - // Low - [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49], - // Medium - [-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68], - // Quartile - [-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81] - // High -]; -class QrCode { - /* -- Constructor (low level) and fields -- */ - // Creates a new QR Code with the given version number, - // error correction level, data codeword bytes, and mask number. - // This is a low-level API that most users should not use directly. - // A mid-level API is the encodeSegments() function. - constructor(version, ecc, dataCodewords, msk) { - this.version = version; - this.ecc = ecc; - /* -- Fields -- */ - // The width and height of this QR Code, measured in modules, between - // 21 and 177 (inclusive). This is equal to version * 4 + 17. - __publicField(this, "size"); - // The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive). - // Even if a QR Code is created with automatic masking requested (mask = -1), - // the resulting object still has a mask value between 0 and 7. - __publicField(this, "mask"); - // The modules of this QR Code (false = light, true = dark). - // Immutable after constructor finishes. Accessed through getModule(). - __publicField(this, "modules", []); - __publicField(this, "types", []); - if (version < MIN_VERSION || version > MAX_VERSION) - throw new RangeError("Version value out of range"); - if (msk < -1 || msk > 7) - throw new RangeError("Mask value out of range"); - this.size = version * 4 + 17; - const row = Array.from({ length: this.size }, () => false); - for (let i = 0; i < this.size; i++) { - this.modules.push(row.slice()); - this.types.push(row.map(() => 0)); - } - this.drawFunctionPatterns(); - const allCodewords = this.addEccAndInterleave(dataCodewords); - this.drawCodewords(allCodewords); - if (msk === -1) { - let minPenalty = 1e9; - for (let i = 0; i < 8; i++) { - this.applyMask(i); - this.drawFormatBits(i); - const penalty = this.getPenaltyScore(); - if (penalty < minPenalty) { - msk = i; - minPenalty = penalty; - } - this.applyMask(i); - } - } - this.mask = msk; - this.applyMask(msk); - this.drawFormatBits(msk); - } - /* -- Accessor methods -- */ - // Returns the color of the module (pixel) at the given coordinates, which is false - // for light or true for dark. The top left corner has the coordinates (x=0, y=0). - // If the given coordinates are out of bounds, then false (light) is returned. - getModule(x, y) { - return x >= 0 && x < this.size && y >= 0 && y < this.size && this.modules[y][x]; - } - /* -- Private helper methods for constructor: Drawing function modules -- */ - // Reads this object's version field, and draws and marks all function modules. - drawFunctionPatterns() { - for (let i = 0; i < this.size; i++) { - this.setFunctionModule(6, i, i % 2 === 0, QrCodeDataType.Timing); - this.setFunctionModule(i, 6, i % 2 === 0, QrCodeDataType.Timing); - } - this.drawFinderPattern(3, 3); - this.drawFinderPattern(this.size - 4, 3); - this.drawFinderPattern(3, this.size - 4); - const alignPatPos = this.getAlignmentPatternPositions(); - const numAlign = alignPatPos.length; - for (let i = 0; i < numAlign; i++) { - for (let j = 0; j < numAlign; j++) { - if (!(i === 0 && j === 0 || i === 0 && j === numAlign - 1 || i === numAlign - 1 && j === 0)) - this.drawAlignmentPattern(alignPatPos[i], alignPatPos[j]); - } - } - this.drawFormatBits(0); - this.drawVersion(); - } - // Draws two copies of the format bits (with its own error correction code) - // based on the given mask and this object's error correction level field. - drawFormatBits(mask) { - const data = this.ecc[1] << 3 | mask; - let rem = data; - for (let i = 0; i < 10; i++) - rem = rem << 1 ^ (rem >>> 9) * 1335; - const bits = (data << 10 | rem) ^ 21522; - for (let i = 0; i <= 5; i++) - this.setFunctionModule(8, i, getBit(bits, i)); - this.setFunctionModule(8, 7, getBit(bits, 6)); - this.setFunctionModule(8, 8, getBit(bits, 7)); - this.setFunctionModule(7, 8, getBit(bits, 8)); - for (let i = 9; i < 15; i++) - this.setFunctionModule(14 - i, 8, getBit(bits, i)); - for (let i = 0; i < 8; i++) - this.setFunctionModule(this.size - 1 - i, 8, getBit(bits, i)); - for (let i = 8; i < 15; i++) - this.setFunctionModule(8, this.size - 15 + i, getBit(bits, i)); - this.setFunctionModule(8, this.size - 8, true); - } - // Draws two copies of the version bits (with its own error correction code), - // based on this object's version field, iff 7 <= version <= 40. - drawVersion() { - if (this.version < 7) - return; - let rem = this.version; - for (let i = 0; i < 12; i++) - rem = rem << 1 ^ (rem >>> 11) * 7973; - const bits = this.version << 12 | rem; - for (let i = 0; i < 18; i++) { - const color = getBit(bits, i); - const a = this.size - 11 + i % 3; - const b = Math.floor(i / 3); - this.setFunctionModule(a, b, color); - this.setFunctionModule(b, a, color); - } - } - // Draws a 9*9 finder pattern including the border separator, - // with the center module at (x, y). Modules can be out of bounds. - drawFinderPattern(x, y) { - for (let dy = -4; dy <= 4; dy++) { - for (let dx = -4; dx <= 4; dx++) { - const dist = Math.max(Math.abs(dx), Math.abs(dy)); - const xx = x + dx; - const yy = y + dy; - if (xx >= 0 && xx < this.size && yy >= 0 && yy < this.size) - this.setFunctionModule(xx, yy, dist !== 2 && dist !== 4, QrCodeDataType.Position); - } - } - } - // Draws a 5*5 alignment pattern, with the center module - // at (x, y). All modules must be in bounds. - drawAlignmentPattern(x, y) { - for (let dy = -2; dy <= 2; dy++) { - for (let dx = -2; dx <= 2; dx++) { - this.setFunctionModule( - x + dx, - y + dy, - Math.max(Math.abs(dx), Math.abs(dy)) !== 1, - QrCodeDataType.Alignment - ); - } - } - } - // Sets the color of a module and marks it as a function module. - // Only used by the constructor. Coordinates must be in bounds. - setFunctionModule(x, y, isDark, type = QrCodeDataType.Function) { - this.modules[y][x] = isDark; - this.types[y][x] = type; - } - /* -- Private helper methods for constructor: Codewords and masking -- */ - // Returns a new byte string representing the given data with the appropriate error correction - // codewords appended to it, based on this object's version and error correction level. - addEccAndInterleave(data) { - const ver = this.version; - const ecl = this.ecc; - if (data.length !== getNumDataCodewords(ver, ecl)) - throw new RangeError("Invalid argument"); - const numBlocks = NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver]; - const blockEccLen = ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver]; - const rawCodewords = Math.floor(getNumRawDataModules(ver) / 8); - const numShortBlocks = numBlocks - rawCodewords % numBlocks; - const shortBlockLen = Math.floor(rawCodewords / numBlocks); - const blocks = []; - const rsDiv = reedSolomonComputeDivisor(blockEccLen); - for (let i = 0, k = 0; i < numBlocks; i++) { - const dat = data.slice(k, k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)); - k += dat.length; - const ecc = reedSolomonComputeRemainder(dat, rsDiv); - if (i < numShortBlocks) - dat.push(0); - blocks.push(dat.concat(ecc)); - } - const result = []; - for (let i = 0; i < blocks[0].length; i++) { - blocks.forEach((block, j) => { - if (i !== shortBlockLen - blockEccLen || j >= numShortBlocks) - result.push(block[i]); - }); - } - return result; - } - // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire - // data area of this QR Code. Function modules need to be marked off before this is called. - drawCodewords(data) { - if (data.length !== Math.floor(getNumRawDataModules(this.version) / 8)) - throw new RangeError("Invalid argument"); - let i = 0; - for (let right = this.size - 1; right >= 1; right -= 2) { - if (right === 6) - right = 5; - for (let vert = 0; vert < this.size; vert++) { - for (let j = 0; j < 2; j++) { - const x = right - j; - const upward = (right + 1 & 2) === 0; - const y = upward ? this.size - 1 - vert : vert; - if (!this.types[y][x] && i < data.length * 8) { - this.modules[y][x] = getBit(data[i >>> 3], 7 - (i & 7)); - i++; - } - } - } - } - } - // XORs the codeword modules in this QR Code with the given mask pattern. - // The function modules must be marked and the codeword bits must be drawn - // before masking. Due to the arithmetic of XOR, calling applyMask() with - // the same mask value a second time will undo the mask. A final well-formed - // QR Code needs exactly one (not zero, two, etc.) mask applied. - applyMask(mask) { - if (mask < 0 || mask > 7) - throw new RangeError("Mask value out of range"); - for (let y = 0; y < this.size; y++) { - for (let x = 0; x < this.size; x++) { - let invert; - switch (mask) { - case 0: - invert = (x + y) % 2 === 0; - break; - case 1: - invert = y % 2 === 0; - break; - case 2: - invert = x % 3 === 0; - break; - case 3: - invert = (x + y) % 3 === 0; - break; - case 4: - invert = (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0; - break; - case 5: - invert = x * y % 2 + x * y % 3 === 0; - break; - case 6: - invert = (x * y % 2 + x * y % 3) % 2 === 0; - break; - case 7: - invert = ((x + y) % 2 + x * y % 3) % 2 === 0; - break; - default: - throw new Error("Unreachable"); - } - if (!this.types[y][x] && invert) - this.modules[y][x] = !this.modules[y][x]; - } - } - } - // Calculates and returns the penalty score based on state of this QR Code's current modules. - // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. - getPenaltyScore() { - let result = 0; - for (let y = 0; y < this.size; y++) { - let runColor = false; - let runX = 0; - const runHistory = [0, 0, 0, 0, 0, 0, 0]; - for (let x = 0; x < this.size; x++) { - if (this.modules[y][x] === runColor) { - runX++; - if (runX === 5) - result += PENALTY_N1; - else if (runX > 5) - result++; - } else { - this.finderPenaltyAddHistory(runX, runHistory); - if (!runColor) - result += this.finderPenaltyCountPatterns(runHistory) * PENALTY_N3; - runColor = this.modules[y][x]; - runX = 1; - } - } - result += this.finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3; - } - for (let x = 0; x < this.size; x++) { - let runColor = false; - let runY = 0; - const runHistory = [0, 0, 0, 0, 0, 0, 0]; - for (let y = 0; y < this.size; y++) { - if (this.modules[y][x] === runColor) { - runY++; - if (runY === 5) - result += PENALTY_N1; - else if (runY > 5) - result++; - } else { - this.finderPenaltyAddHistory(runY, runHistory); - if (!runColor) - result += this.finderPenaltyCountPatterns(runHistory) * PENALTY_N3; - runColor = this.modules[y][x]; - runY = 1; - } - } - result += this.finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3; - } - for (let y = 0; y < this.size - 1; y++) { - for (let x = 0; x < this.size - 1; x++) { - const color = this.modules[y][x]; - if (color === this.modules[y][x + 1] && color === this.modules[y + 1][x] && color === this.modules[y + 1][x + 1]) - result += PENALTY_N2; - } - } - let dark = 0; - for (const row of this.modules) - dark = row.reduce((sum, color) => sum + (color ? 1 : 0), dark); - const total = this.size * this.size; - const k = Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1; - result += k * PENALTY_N4; - return result; - } - /* -- Private helper functions -- */ - // Returns an ascending list of positions of alignment patterns for this version number. - // Each position is in the range [0,177), and are used on both the x and y axes. - // This could be implemented as lookup table of 40 variable-length lists of integers. - getAlignmentPatternPositions() { - if (this.version === 1) { - return []; - } else { - const numAlign = Math.floor(this.version / 7) + 2; - const step = this.version === 32 ? 26 : Math.ceil((this.version * 4 + 4) / (numAlign * 2 - 2)) * 2; - const result = [6]; - for (let pos = this.size - 7; result.length < numAlign; pos -= step) - result.splice(1, 0, pos); - return result; - } - } - // Can only be called immediately after a light run is added, and - // returns either 0, 1, or 2. A helper function for getPenaltyScore(). - finderPenaltyCountPatterns(runHistory) { - const n = runHistory[1]; - const core = n > 0 && runHistory[2] === n && runHistory[3] === n * 3 && runHistory[4] === n && runHistory[5] === n; - return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0); - } - // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). - finderPenaltyTerminateAndCount(currentRunColor, currentRunLength, runHistory) { - if (currentRunColor) { - this.finderPenaltyAddHistory(currentRunLength, runHistory); - currentRunLength = 0; - } - currentRunLength += this.size; - this.finderPenaltyAddHistory(currentRunLength, runHistory); - return this.finderPenaltyCountPatterns(runHistory); - } - // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). - finderPenaltyAddHistory(currentRunLength, runHistory) { - if (runHistory[0] === 0) - currentRunLength += this.size; - runHistory.pop(); - runHistory.unshift(currentRunLength); - } -} -function appendBits(val, len, bb) { - if (len < 0 || len > 31 || val >>> len !== 0) - throw new RangeError("Value out of range"); - for (let i = len - 1; i >= 0; i--) - bb.push(val >>> i & 1); -} -function getBit(x, i) { - return (x >>> i & 1) !== 0; -} -class QrSegment { - // Creates a new QR Code segment with the given attributes and data. - // The character count (numChars) must agree with the mode and the bit buffer length, - // but the constraint isn't checked. The given bit buffer is cloned and stored. - constructor(mode, numChars, bitData) { - this.mode = mode; - this.numChars = numChars; - this.bitData = bitData; - if (numChars < 0) - throw new RangeError("Invalid argument"); - this.bitData = bitData.slice(); - } - /* -- Methods -- */ - // Returns a new copy of the data bits of this segment. - getData() { - return this.bitData.slice(); - } -} -const MODE_NUMERIC = [1, 10, 12, 14]; -const MODE_ALPHANUMERIC = [2, 9, 11, 13]; -const MODE_BYTE = [4, 8, 16, 16]; -function numCharCountBits(mode, ver) { - return mode[Math.floor((ver + 7) / 17) + 1]; -} -function makeBytes(data) { - const bb = []; - for (const b of data) - appendBits(b, 8, bb); - return new QrSegment(MODE_BYTE, data.length, bb); -} -function makeNumeric(digits) { - if (!isNumeric(digits)) - throw new RangeError("String contains non-numeric characters"); - const bb = []; - for (let i = 0; i < digits.length; ) { - const n = Math.min(digits.length - i, 3); - appendBits(Number.parseInt(digits.substring(i, i + n), 10), n * 3 + 1, bb); - i += n; - } - return new QrSegment(MODE_NUMERIC, digits.length, bb); -} -function makeAlphanumeric(text) { - if (!isAlphanumeric(text)) - throw new RangeError("String contains unencodable characters in alphanumeric mode"); - const bb = []; - let i; - for (i = 0; i + 2 <= text.length; i += 2) { - let temp = ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)) * 45; - temp += ALPHANUMERIC_CHARSET.indexOf(text.charAt(i + 1)); - appendBits(temp, 11, bb); - } - if (i < text.length) - appendBits(ALPHANUMERIC_CHARSET.indexOf(text.charAt(i)), 6, bb); - return new QrSegment(MODE_ALPHANUMERIC, text.length, bb); -} -function makeSegments(text) { - if (text === "") - return []; - else if (isNumeric(text)) - return [makeNumeric(text)]; - else if (isAlphanumeric(text)) - return [makeAlphanumeric(text)]; - else - return [makeBytes(toUtf8ByteArray(text))]; -} -function isNumeric(text) { - return NUMERIC_REGEX.test(text); -} -function isAlphanumeric(text) { - return ALPHANUMERIC_REGEX.test(text); -} -function getTotalBits(segs, version) { - let result = 0; - for (const seg of segs) { - const ccbits = numCharCountBits(seg.mode, version); - if (seg.numChars >= 1 << ccbits) - return Number.POSITIVE_INFINITY; - result += 4 + ccbits + seg.bitData.length; - } - return result; -} -function toUtf8ByteArray(str) { - str = encodeURI(str); - const result = []; - for (let i = 0; i < str.length; i++) { - if (str.charAt(i) !== "%") { - result.push(str.charCodeAt(i)); - } else { - result.push(Number.parseInt(str.substring(i + 1, i + 3), 16)); - i += 2; - } - } - return result; -} -function getNumRawDataModules(ver) { - if (ver < MIN_VERSION || ver > MAX_VERSION) - throw new RangeError("Version number out of range"); - let result = (16 * ver + 128) * ver + 64; - if (ver >= 2) { - const numAlign = Math.floor(ver / 7) + 2; - result -= (25 * numAlign - 10) * numAlign - 55; - if (ver >= 7) - result -= 36; - } - return result; -} -function getNumDataCodewords(ver, ecl) { - return Math.floor(getNumRawDataModules(ver) / 8) - ECC_CODEWORDS_PER_BLOCK[ecl[0]][ver] * NUM_ERROR_CORRECTION_BLOCKS[ecl[0]][ver]; -} -function reedSolomonComputeDivisor(degree) { - if (degree < 1 || degree > 255) - throw new RangeError("Degree out of range"); - const result = []; - for (let i = 0; i < degree - 1; i++) - result.push(0); - result.push(1); - let root = 1; - for (let i = 0; i < degree; i++) { - for (let j = 0; j < result.length; j++) { - result[j] = reedSolomonMultiply(result[j], root); - if (j + 1 < result.length) - result[j] ^= result[j + 1]; - } - root = reedSolomonMultiply(root, 2); - } - return result; -} -function reedSolomonComputeRemainder(data, divisor) { - const result = divisor.map((_) => 0); - for (const b of data) { - const factor = b ^ result.shift(); - result.push(0); - divisor.forEach((coef, i) => result[i] ^= reedSolomonMultiply(coef, factor)); - } - return result; -} -function reedSolomonMultiply(x, y) { - if (x >>> 8 !== 0 || y >>> 8 !== 0) - throw new RangeError("Byte out of range"); - let z = 0; - for (let i = 7; i >= 0; i--) { - z = z << 1 ^ (z >>> 7) * 285; - z ^= (y >>> i & 1) * x; - } - return z; -} -function encodeSegments(segs, ecl, minVersion = 1, maxVersion = 40, mask = -1, boostEcl = true) { - if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) - throw new RangeError("Invalid value"); - let version; - let dataUsedBits; - for (version = minVersion; ; version++) { - const dataCapacityBits2 = getNumDataCodewords(version, ecl) * 8; - const usedBits = getTotalBits(segs, version); - if (usedBits <= dataCapacityBits2) { - dataUsedBits = usedBits; - break; - } - if (version >= maxVersion) - throw new RangeError("Data too long"); - } - for (const newEcl of [MEDIUM, QUARTILE, HIGH]) { - if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8) - ecl = newEcl; - } - const bb = []; - for (const seg of segs) { - appendBits(seg.mode[0], 4, bb); - appendBits(seg.numChars, numCharCountBits(seg.mode, version), bb); - for (const b of seg.getData()) - bb.push(b); - } - const dataCapacityBits = getNumDataCodewords(version, ecl) * 8; - appendBits(0, Math.min(4, dataCapacityBits - bb.length), bb); - appendBits(0, (8 - bb.length % 8) % 8, bb); - for (let padByte = 236; bb.length < dataCapacityBits; padByte ^= 236 ^ 17) - appendBits(padByte, 8, bb); - const dataCodewords = Array.from({ length: Math.ceil(bb.length / 8) }, () => 0); - bb.forEach((b, i) => dataCodewords[i >>> 3] |= b << 7 - (i & 7)); - return new QrCode(version, ecl, dataCodewords, mask); -} - -function encode(data, options) { - const { - ecc = "L", - boostEcc = false, - minVersion = 1, - maxVersion = 40, - maskPattern = -1, - border = 1 - } = options || {}; - const segment = typeof data === "string" ? makeSegments(data) : Array.isArray(data) ? [makeBytes(data)] : void 0; - if (!segment) - throw new Error(`uqr only supports encoding string and binary data, but got: ${typeof data}`); - const qr = encodeSegments( - segment, - EccMap[ecc], - minVersion, - maxVersion, - maskPattern, - boostEcc - ); - const result = addBorder({ - version: qr.version, - maskPattern: qr.mask, - size: qr.size, - data: qr.modules, - types: qr.types - }, border); - if (options?.invert) - result.data = result.data.map((row) => row.map((mod) => !mod)); - options?.onEncoded?.(result); - return result; -} -function addBorder(input, border = 1) { - if (!border) - return input; - const { size } = input; - const newSize = size + border * 2; - input.size = newSize; - input.data.forEach((row) => { - for (let i = 0; i < border; i++) { - row.unshift(false); - row.push(false); - } - }); - for (let i = 0; i < border; i++) { - input.data.unshift(Array.from({ length: newSize }, (_) => false)); - input.data.push(Array.from({ length: newSize }, (_) => false)); - } - const b = QrCodeDataType.Border; - input.types.forEach((row) => { - for (let i = 0; i < border; i++) { - row.unshift(b); - row.push(b); - } - }); - for (let i = 0; i < border; i++) { - input.types.unshift(Array.from({ length: newSize }, (_) => b)); - input.types.push(Array.from({ length: newSize }, (_) => b)); - } - return input; -} -function getDataAt(data, x, y, defaults = false) { - if (x < 0 || y < 0 || x >= data.length || y >= data.length) - return defaults; - return data[y][x]; -} -function renderUnicodeCompact(data, options = {}) { - const platte = { - WHITE_ALL: "\u2588", - WHITE_BLACK: "\u2580", - BLACK_WHITE: "\u2584", - BLACK_ALL: " " - }; - const result = encode(data, options); - const WHITE = false; - const BLACK = true; - const at = (x, y) => getDataAt(result.data, x, y, true); - const lines = []; - let line = ""; - for (let row = 0; row < result.size; row += 2) { - for (let col = 0; col < result.size; col++) { - if (at(col, row) === WHITE && at(col, row + 1) === WHITE) - line += platte.WHITE_ALL; - else if (at(col, row) === WHITE && at(col, row + 1) === BLACK) - line += platte.WHITE_BLACK; - else if (at(col, row) === BLACK && at(col, row + 1) === WHITE) - line += platte.BLACK_WHITE; - else - line += platte.BLACK_ALL; - } - lines.push(line); - line = ""; - } - return lines.join("\n"); -} - -/** - * Node.js module for Forge. - * - * @author Dave Longley - * - * Copyright 2011-2016 Digital Bazaar, Inc. - */ - -var forge$D = { - // default options - options: { - usePureJavaScript: false - } -}; - -/** - * Base-N/Base-X encoding/decoding functions. - * - * Original implementation from base-x: - * https://github.com/cryptocoinjs/base-x - * - * Which is MIT licensed: - * - * The MIT License (MIT) - * - * Copyright base-x contributors (c) 2016 - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -var api = {}; -var baseN$1 = api; - -// baseN alphabet indexes -var _reverseAlphabets = {}; - -/** - * BaseN-encodes a Uint8Array using the given alphabet. - * - * @param input the Uint8Array to encode. - * @param maxline the maximum number of encoded characters per line to use, - * defaults to none. - * - * @return the baseN-encoded output string. - */ -api.encode = function(input, alphabet, maxline) { - if(typeof alphabet !== 'string') { - throw new TypeError('"alphabet" must be a string.'); - } - if(maxline !== undefined && typeof maxline !== 'number') { - throw new TypeError('"maxline" must be a number.'); - } - - var output = ''; - - if(!(input instanceof Uint8Array)) { - // assume forge byte buffer - output = _encodeWithByteBuffer(input, alphabet); - } else { - var i = 0; - var base = alphabet.length; - var first = alphabet.charAt(0); - var digits = [0]; - for(i = 0; i < input.length; ++i) { - for(var j = 0, carry = input[i]; j < digits.length; ++j) { - carry += digits[j] << 8; - digits[j] = carry % base; - carry = (carry / base) | 0; - } - - while(carry > 0) { - digits.push(carry % base); - carry = (carry / base) | 0; - } - } - - // deal with leading zeros - for(i = 0; input[i] === 0 && i < input.length - 1; ++i) { - output += first; - } - // convert digits to a string - for(i = digits.length - 1; i >= 0; --i) { - output += alphabet[digits[i]]; - } - } - - if(maxline) { - var regex = new RegExp('.{1,' + maxline + '}', 'g'); - output = output.match(regex).join('\r\n'); - } - - return output; -}; - -/** - * Decodes a baseN-encoded (using the given alphabet) string to a - * Uint8Array. - * - * @param input the baseN-encoded input string. - * - * @return the Uint8Array. - */ -api.decode = function(input, alphabet) { - if(typeof input !== 'string') { - throw new TypeError('"input" must be a string.'); - } - if(typeof alphabet !== 'string') { - throw new TypeError('"alphabet" must be a string.'); - } - - var table = _reverseAlphabets[alphabet]; - if(!table) { - // compute reverse alphabet - table = _reverseAlphabets[alphabet] = []; - for(var i = 0; i < alphabet.length; ++i) { - table[alphabet.charCodeAt(i)] = i; - } - } - - // remove whitespace characters - input = input.replace(/\s/g, ''); - - var base = alphabet.length; - var first = alphabet.charAt(0); - var bytes = [0]; - for(var i = 0; i < input.length; i++) { - var value = table[input.charCodeAt(i)]; - if(value === undefined) { - return; - } - - for(var j = 0, carry = value; j < bytes.length; ++j) { - carry += bytes[j] * base; - bytes[j] = carry & 0xff; - carry >>= 8; - } - - while(carry > 0) { - bytes.push(carry & 0xff); - carry >>= 8; - } - } - - // deal with leading zeros - for(var k = 0; input[k] === first && k < input.length - 1; ++k) { - bytes.push(0); - } - - if(typeof Buffer !== 'undefined') { - return Buffer.from(bytes.reverse()); - } - - return new Uint8Array(bytes.reverse()); -}; - -function _encodeWithByteBuffer(input, alphabet) { - var i = 0; - var base = alphabet.length; - var first = alphabet.charAt(0); - var digits = [0]; - for(i = 0; i < input.length(); ++i) { - for(var j = 0, carry = input.at(i); j < digits.length; ++j) { - carry += digits[j] << 8; - digits[j] = carry % base; - carry = (carry / base) | 0; - } - - while(carry > 0) { - digits.push(carry % base); - carry = (carry / base) | 0; - } - } - - var output = ''; - - // deal with leading zeros - for(i = 0; input.at(i) === 0 && i < input.length() - 1; ++i) { - output += first; - } - // convert digits to a string - for(i = digits.length - 1; i >= 0; --i) { - output += alphabet[digits[i]]; - } - - return output; -} - -/** - * Utility functions for web applications. - * - * @author Dave Longley - * - * Copyright (c) 2010-2018 Digital Bazaar, Inc. - */ - -var forge$C = forge$D; -var baseN = baseN$1; - -/* Utilities API */ -var util$1 = forge$C.util = forge$C.util || {}; - -// define setImmediate and nextTick -(function() { - // use native nextTick (unless we're in webpack) - // webpack (or better node-libs-browser polyfill) sets process.browser. - // this way we can detect webpack properly - if(typeof process !== 'undefined' && process.nextTick && !process.browser) { - util$1.nextTick = process.nextTick; - if(typeof setImmediate === 'function') { - util$1.setImmediate = setImmediate; - } else { - // polyfill setImmediate with nextTick, older versions of node - // (those w/o setImmediate) won't totally starve IO - util$1.setImmediate = util$1.nextTick; - } - return; - } - - // polyfill nextTick with native setImmediate - if(typeof setImmediate === 'function') { - util$1.setImmediate = function() { return setImmediate.apply(undefined, arguments); }; - util$1.nextTick = function(callback) { - return setImmediate(callback); - }; - return; - } - - /* Note: A polyfill upgrade pattern is used here to allow combining - polyfills. For example, MutationObserver is fast, but blocks UI updates, - so it needs to allow UI updates periodically, so it falls back on - postMessage or setTimeout. */ - - // polyfill with setTimeout - util$1.setImmediate = function(callback) { - setTimeout(callback, 0); - }; - - // upgrade polyfill to use postMessage - if(typeof window !== 'undefined' && - typeof window.postMessage === 'function') { - var msg = 'forge.setImmediate'; - var callbacks = []; - util$1.setImmediate = function(callback) { - callbacks.push(callback); - // only send message when one hasn't been sent in - // the current turn of the event loop - if(callbacks.length === 1) { - window.postMessage(msg, '*'); - } - }; - function handler(event) { - if(event.source === window && event.data === msg) { - event.stopPropagation(); - var copy = callbacks.slice(); - callbacks.length = 0; - copy.forEach(function(callback) { - callback(); - }); - } - } - window.addEventListener('message', handler, true); - } - - // upgrade polyfill to use MutationObserver - if(typeof MutationObserver !== 'undefined') { - // polyfill with MutationObserver - var now = Date.now(); - var attr = true; - var div = document.createElement('div'); - var callbacks = []; - new MutationObserver(function() { - var copy = callbacks.slice(); - callbacks.length = 0; - copy.forEach(function(callback) { - callback(); - }); - }).observe(div, {attributes: true}); - var oldSetImmediate = util$1.setImmediate; - util$1.setImmediate = function(callback) { - if(Date.now() - now > 15) { - now = Date.now(); - oldSetImmediate(callback); - } else { - callbacks.push(callback); - // only trigger observer when it hasn't been triggered in - // the current turn of the event loop - if(callbacks.length === 1) { - div.setAttribute('a', attr = !attr); - } - } - }; - } - - util$1.nextTick = util$1.setImmediate; -})(); - -// check if running under Node.js -util$1.isNodejs = - typeof process !== 'undefined' && process.versions && process.versions.node; - - -// 'self' will also work in Web Workers (instance of WorkerGlobalScope) while -// it will point to `window` in the main thread. -// To remain compatible with older browsers, we fall back to 'window' if 'self' -// is not available. -util$1.globalScope = (function() { - if(util$1.isNodejs) { - return commonjsGlobal; - } - - return typeof self === 'undefined' ? window : self; -})(); - -// define isArray -util$1.isArray = Array.isArray || function(x) { - return Object.prototype.toString.call(x) === '[object Array]'; -}; - -// define isArrayBuffer -util$1.isArrayBuffer = function(x) { - return typeof ArrayBuffer !== 'undefined' && x instanceof ArrayBuffer; -}; - -// define isArrayBufferView -util$1.isArrayBufferView = function(x) { - return x && util$1.isArrayBuffer(x.buffer) && x.byteLength !== undefined; -}; - -/** - * Ensure a bits param is 8, 16, 24, or 32. Used to validate input for - * algorithms where bit manipulation, JavaScript limitations, and/or algorithm - * design only allow for byte operations of a limited size. - * - * @param n number of bits. - * - * Throw Error if n invalid. - */ -function _checkBitsParam(n) { - if(!(n === 8 || n === 16 || n === 24 || n === 32)) { - throw new Error('Only 8, 16, 24, or 32 bits supported: ' + n); - } -} - -// TODO: set ByteBuffer to best available backing -util$1.ByteBuffer = ByteStringBuffer; - -/** Buffer w/BinaryString backing */ - -/** - * Constructor for a binary string backed byte buffer. - * - * @param [b] the bytes to wrap (either encoded as string, one byte per - * character, or as an ArrayBuffer or Typed Array). - */ -function ByteStringBuffer(b) { - // TODO: update to match DataBuffer API - - // the data in this buffer - this.data = ''; - // the pointer for reading from this buffer - this.read = 0; - - if(typeof b === 'string') { - this.data = b; - } else if(util$1.isArrayBuffer(b) || util$1.isArrayBufferView(b)) { - if(typeof Buffer !== 'undefined' && b instanceof Buffer) { - this.data = b.toString('binary'); - } else { - // convert native buffer to forge buffer - // FIXME: support native buffers internally instead - var arr = new Uint8Array(b); - try { - this.data = String.fromCharCode.apply(null, arr); - } catch(e) { - for(var i = 0; i < arr.length; ++i) { - this.putByte(arr[i]); - } - } - } - } else if(b instanceof ByteStringBuffer || - (typeof b === 'object' && typeof b.data === 'string' && - typeof b.read === 'number')) { - // copy existing buffer - this.data = b.data; - this.read = b.read; - } - - // used for v8 optimization - this._constructedStringLength = 0; -} -util$1.ByteStringBuffer = ByteStringBuffer; - -/* Note: This is an optimization for V8-based browsers. When V8 concatenates - a string, the strings are only joined logically using a "cons string" or - "constructed/concatenated string". These containers keep references to one - another and can result in very large memory usage. For example, if a 2MB - string is constructed by concatenating 4 bytes together at a time, the - memory usage will be ~44MB; so ~22x increase. The strings are only joined - together when an operation requiring their joining takes place, such as - substr(). This function is called when adding data to this buffer to ensure - these types of strings are periodically joined to reduce the memory - footprint. */ -var _MAX_CONSTRUCTED_STRING_LENGTH = 4096; -util$1.ByteStringBuffer.prototype._optimizeConstructedString = function(x) { - this._constructedStringLength += x; - if(this._constructedStringLength > _MAX_CONSTRUCTED_STRING_LENGTH) { - // this substr() should cause the constructed string to join - this.data.substr(0, 1); - this._constructedStringLength = 0; - } -}; - -/** - * Gets the number of bytes in this buffer. - * - * @return the number of bytes in this buffer. - */ -util$1.ByteStringBuffer.prototype.length = function() { - return this.data.length - this.read; -}; - -/** - * Gets whether or not this buffer is empty. - * - * @return true if this buffer is empty, false if not. - */ -util$1.ByteStringBuffer.prototype.isEmpty = function() { - return this.length() <= 0; -}; - -/** - * Puts a byte in this buffer. - * - * @param b the byte to put. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putByte = function(b) { - return this.putBytes(String.fromCharCode(b)); -}; - -/** - * Puts a byte in this buffer N times. - * - * @param b the byte to put. - * @param n the number of bytes of value b to put. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.fillWithByte = function(b, n) { - b = String.fromCharCode(b); - var d = this.data; - while(n > 0) { - if(n & 1) { - d += b; - } - n >>>= 1; - if(n > 0) { - b += b; - } - } - this.data = d; - this._optimizeConstructedString(n); - return this; -}; - -/** - * Puts bytes in this buffer. - * - * @param bytes the bytes (as a binary encoded string) to put. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putBytes = function(bytes) { - this.data += bytes; - this._optimizeConstructedString(bytes.length); - return this; -}; - -/** - * Puts a UTF-16 encoded string into this buffer. - * - * @param str the string to put. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putString = function(str) { - return this.putBytes(util$1.encodeUtf8(str)); -}; - -/** - * Puts a 16-bit integer in this buffer in big-endian order. - * - * @param i the 16-bit integer. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putInt16 = function(i) { - return this.putBytes( - String.fromCharCode(i >> 8 & 0xFF) + - String.fromCharCode(i & 0xFF)); -}; - -/** - * Puts a 24-bit integer in this buffer in big-endian order. - * - * @param i the 24-bit integer. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putInt24 = function(i) { - return this.putBytes( - String.fromCharCode(i >> 16 & 0xFF) + - String.fromCharCode(i >> 8 & 0xFF) + - String.fromCharCode(i & 0xFF)); -}; - -/** - * Puts a 32-bit integer in this buffer in big-endian order. - * - * @param i the 32-bit integer. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putInt32 = function(i) { - return this.putBytes( - String.fromCharCode(i >> 24 & 0xFF) + - String.fromCharCode(i >> 16 & 0xFF) + - String.fromCharCode(i >> 8 & 0xFF) + - String.fromCharCode(i & 0xFF)); -}; - -/** - * Puts a 16-bit integer in this buffer in little-endian order. - * - * @param i the 16-bit integer. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putInt16Le = function(i) { - return this.putBytes( - String.fromCharCode(i & 0xFF) + - String.fromCharCode(i >> 8 & 0xFF)); -}; - -/** - * Puts a 24-bit integer in this buffer in little-endian order. - * - * @param i the 24-bit integer. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putInt24Le = function(i) { - return this.putBytes( - String.fromCharCode(i & 0xFF) + - String.fromCharCode(i >> 8 & 0xFF) + - String.fromCharCode(i >> 16 & 0xFF)); -}; - -/** - * Puts a 32-bit integer in this buffer in little-endian order. - * - * @param i the 32-bit integer. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putInt32Le = function(i) { - return this.putBytes( - String.fromCharCode(i & 0xFF) + - String.fromCharCode(i >> 8 & 0xFF) + - String.fromCharCode(i >> 16 & 0xFF) + - String.fromCharCode(i >> 24 & 0xFF)); -}; - -/** - * Puts an n-bit integer in this buffer in big-endian order. - * - * @param i the n-bit integer. - * @param n the number of bits in the integer (8, 16, 24, or 32). - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putInt = function(i, n) { - _checkBitsParam(n); - var bytes = ''; - do { - n -= 8; - bytes += String.fromCharCode((i >> n) & 0xFF); - } while(n > 0); - return this.putBytes(bytes); -}; - -/** - * Puts a signed n-bit integer in this buffer in big-endian order. Two's - * complement representation is used. - * - * @param i the n-bit integer. - * @param n the number of bits in the integer (8, 16, 24, or 32). - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putSignedInt = function(i, n) { - // putInt checks n - if(i < 0) { - i += 2 << (n - 1); - } - return this.putInt(i, n); -}; - -/** - * Puts the given buffer into this buffer. - * - * @param buffer the buffer to put into this one. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.putBuffer = function(buffer) { - return this.putBytes(buffer.getBytes()); -}; - -/** - * Gets a byte from this buffer and advances the read pointer by 1. - * - * @return the byte. - */ -util$1.ByteStringBuffer.prototype.getByte = function() { - return this.data.charCodeAt(this.read++); -}; - -/** - * Gets a uint16 from this buffer in big-endian order and advances the read - * pointer by 2. - * - * @return the uint16. - */ -util$1.ByteStringBuffer.prototype.getInt16 = function() { - var rval = ( - this.data.charCodeAt(this.read) << 8 ^ - this.data.charCodeAt(this.read + 1)); - this.read += 2; - return rval; -}; - -/** - * Gets a uint24 from this buffer in big-endian order and advances the read - * pointer by 3. - * - * @return the uint24. - */ -util$1.ByteStringBuffer.prototype.getInt24 = function() { - var rval = ( - this.data.charCodeAt(this.read) << 16 ^ - this.data.charCodeAt(this.read + 1) << 8 ^ - this.data.charCodeAt(this.read + 2)); - this.read += 3; - return rval; -}; - -/** - * Gets a uint32 from this buffer in big-endian order and advances the read - * pointer by 4. - * - * @return the word. - */ -util$1.ByteStringBuffer.prototype.getInt32 = function() { - var rval = ( - this.data.charCodeAt(this.read) << 24 ^ - this.data.charCodeAt(this.read + 1) << 16 ^ - this.data.charCodeAt(this.read + 2) << 8 ^ - this.data.charCodeAt(this.read + 3)); - this.read += 4; - return rval; -}; - -/** - * Gets a uint16 from this buffer in little-endian order and advances the read - * pointer by 2. - * - * @return the uint16. - */ -util$1.ByteStringBuffer.prototype.getInt16Le = function() { - var rval = ( - this.data.charCodeAt(this.read) ^ - this.data.charCodeAt(this.read + 1) << 8); - this.read += 2; - return rval; -}; - -/** - * Gets a uint24 from this buffer in little-endian order and advances the read - * pointer by 3. - * - * @return the uint24. - */ -util$1.ByteStringBuffer.prototype.getInt24Le = function() { - var rval = ( - this.data.charCodeAt(this.read) ^ - this.data.charCodeAt(this.read + 1) << 8 ^ - this.data.charCodeAt(this.read + 2) << 16); - this.read += 3; - return rval; -}; - -/** - * Gets a uint32 from this buffer in little-endian order and advances the read - * pointer by 4. - * - * @return the word. - */ -util$1.ByteStringBuffer.prototype.getInt32Le = function() { - var rval = ( - this.data.charCodeAt(this.read) ^ - this.data.charCodeAt(this.read + 1) << 8 ^ - this.data.charCodeAt(this.read + 2) << 16 ^ - this.data.charCodeAt(this.read + 3) << 24); - this.read += 4; - return rval; -}; - -/** - * Gets an n-bit integer from this buffer in big-endian order and advances the - * read pointer by ceil(n/8). - * - * @param n the number of bits in the integer (8, 16, 24, or 32). - * - * @return the integer. - */ -util$1.ByteStringBuffer.prototype.getInt = function(n) { - _checkBitsParam(n); - var rval = 0; - do { - // TODO: Use (rval * 0x100) if adding support for 33 to 53 bits. - rval = (rval << 8) + this.data.charCodeAt(this.read++); - n -= 8; - } while(n > 0); - return rval; -}; - -/** - * Gets a signed n-bit integer from this buffer in big-endian order, using - * two's complement, and advances the read pointer by n/8. - * - * @param n the number of bits in the integer (8, 16, 24, or 32). - * - * @return the integer. - */ -util$1.ByteStringBuffer.prototype.getSignedInt = function(n) { - // getInt checks n - var x = this.getInt(n); - var max = 2 << (n - 2); - if(x >= max) { - x -= max << 1; - } - return x; -}; - -/** - * Reads bytes out as a binary encoded string and clears them from the - * buffer. Note that the resulting string is binary encoded (in node.js this - * encoding is referred to as `binary`, it is *not* `utf8`). - * - * @param count the number of bytes to read, undefined or null for all. - * - * @return a binary encoded string of bytes. - */ -util$1.ByteStringBuffer.prototype.getBytes = function(count) { - var rval; - if(count) { - // read count bytes - count = Math.min(this.length(), count); - rval = this.data.slice(this.read, this.read + count); - this.read += count; - } else if(count === 0) { - rval = ''; - } else { - // read all bytes, optimize to only copy when needed - rval = (this.read === 0) ? this.data : this.data.slice(this.read); - this.clear(); - } - return rval; -}; - -/** - * Gets a binary encoded string of the bytes from this buffer without - * modifying the read pointer. - * - * @param count the number of bytes to get, omit to get all. - * - * @return a string full of binary encoded characters. - */ -util$1.ByteStringBuffer.prototype.bytes = function(count) { - return (typeof(count) === 'undefined' ? - this.data.slice(this.read) : - this.data.slice(this.read, this.read + count)); -}; - -/** - * Gets a byte at the given index without modifying the read pointer. - * - * @param i the byte index. - * - * @return the byte. - */ -util$1.ByteStringBuffer.prototype.at = function(i) { - return this.data.charCodeAt(this.read + i); -}; - -/** - * Puts a byte at the given index without modifying the read pointer. - * - * @param i the byte index. - * @param b the byte to put. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.setAt = function(i, b) { - this.data = this.data.substr(0, this.read + i) + - String.fromCharCode(b) + - this.data.substr(this.read + i + 1); - return this; -}; - -/** - * Gets the last byte without modifying the read pointer. - * - * @return the last byte. - */ -util$1.ByteStringBuffer.prototype.last = function() { - return this.data.charCodeAt(this.data.length - 1); -}; - -/** - * Creates a copy of this buffer. - * - * @return the copy. - */ -util$1.ByteStringBuffer.prototype.copy = function() { - var c = util$1.createBuffer(this.data); - c.read = this.read; - return c; -}; - -/** - * Compacts this buffer. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.compact = function() { - if(this.read > 0) { - this.data = this.data.slice(this.read); - this.read = 0; - } - return this; -}; - -/** - * Clears this buffer. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.clear = function() { - this.data = ''; - this.read = 0; - return this; -}; - -/** - * Shortens this buffer by triming bytes off of the end of this buffer. - * - * @param count the number of bytes to trim off. - * - * @return this buffer. - */ -util$1.ByteStringBuffer.prototype.truncate = function(count) { - var len = Math.max(0, this.length() - count); - this.data = this.data.substr(this.read, len); - this.read = 0; - return this; -}; - -/** - * Converts this buffer to a hexadecimal string. - * - * @return a hexadecimal string. - */ -util$1.ByteStringBuffer.prototype.toHex = function() { - var rval = ''; - for(var i = this.read; i < this.data.length; ++i) { - var b = this.data.charCodeAt(i); - if(b < 16) { - rval += '0'; - } - rval += b.toString(16); - } - return rval; -}; - -/** - * Converts this buffer to a UTF-16 string (standard JavaScript string). - * - * @return a UTF-16 string. - */ -util$1.ByteStringBuffer.prototype.toString = function() { - return util$1.decodeUtf8(this.bytes()); -}; - -/** End Buffer w/BinaryString backing */ - -/** Buffer w/UInt8Array backing */ - -/** - * FIXME: Experimental. Do not use yet. - * - * Constructor for an ArrayBuffer-backed byte buffer. - * - * The buffer may be constructed from a string, an ArrayBuffer, DataView, or a - * TypedArray. - * - * If a string is given, its encoding should be provided as an option, - * otherwise it will default to 'binary'. A 'binary' string is encoded such - * that each character is one byte in length and size. - * - * If an ArrayBuffer, DataView, or TypedArray is given, it will be used - * *directly* without any copying. Note that, if a write to the buffer requires - * more space, the buffer will allocate a new backing ArrayBuffer to - * accommodate. The starting read and write offsets for the buffer may be - * given as options. - * - * @param [b] the initial bytes for this buffer. - * @param options the options to use: - * [readOffset] the starting read offset to use (default: 0). - * [writeOffset] the starting write offset to use (default: the - * length of the first parameter). - * [growSize] the minimum amount, in bytes, to grow the buffer by to - * accommodate writes (default: 1024). - * [encoding] the encoding ('binary', 'utf8', 'utf16', 'hex') for the - * first parameter, if it is a string (default: 'binary'). - */ -function DataBuffer(b, options) { - // default options - options = options || {}; - - // pointers for read from/write to buffer - this.read = options.readOffset || 0; - this.growSize = options.growSize || 1024; - - var isArrayBuffer = util$1.isArrayBuffer(b); - var isArrayBufferView = util$1.isArrayBufferView(b); - if(isArrayBuffer || isArrayBufferView) { - // use ArrayBuffer directly - if(isArrayBuffer) { - this.data = new DataView(b); - } else { - // TODO: adjust read/write offset based on the type of view - // or specify that this must be done in the options ... that the - // offsets are byte-based - this.data = new DataView(b.buffer, b.byteOffset, b.byteLength); - } - this.write = ('writeOffset' in options ? - options.writeOffset : this.data.byteLength); - return; - } - - // initialize to empty array buffer and add any given bytes using putBytes - this.data = new DataView(new ArrayBuffer(0)); - this.write = 0; - - if(b !== null && b !== undefined) { - this.putBytes(b); - } - - if('writeOffset' in options) { - this.write = options.writeOffset; - } -} -util$1.DataBuffer = DataBuffer; - -/** - * Gets the number of bytes in this buffer. - * - * @return the number of bytes in this buffer. - */ -util$1.DataBuffer.prototype.length = function() { - return this.write - this.read; -}; - -/** - * Gets whether or not this buffer is empty. - * - * @return true if this buffer is empty, false if not. - */ -util$1.DataBuffer.prototype.isEmpty = function() { - return this.length() <= 0; -}; - -/** - * Ensures this buffer has enough empty space to accommodate the given number - * of bytes. An optional parameter may be given that indicates a minimum - * amount to grow the buffer if necessary. If the parameter is not given, - * the buffer will be grown by some previously-specified default amount - * or heuristic. - * - * @param amount the number of bytes to accommodate. - * @param [growSize] the minimum amount, in bytes, to grow the buffer by if - * necessary. - */ -util$1.DataBuffer.prototype.accommodate = function(amount, growSize) { - if(this.length() >= amount) { - return this; - } - growSize = Math.max(growSize || this.growSize, amount); - - // grow buffer - var src = new Uint8Array( - this.data.buffer, this.data.byteOffset, this.data.byteLength); - var dst = new Uint8Array(this.length() + growSize); - dst.set(src); - this.data = new DataView(dst.buffer); - - return this; -}; - -/** - * Puts a byte in this buffer. - * - * @param b the byte to put. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putByte = function(b) { - this.accommodate(1); - this.data.setUint8(this.write++, b); - return this; -}; - -/** - * Puts a byte in this buffer N times. - * - * @param b the byte to put. - * @param n the number of bytes of value b to put. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.fillWithByte = function(b, n) { - this.accommodate(n); - for(var i = 0; i < n; ++i) { - this.data.setUint8(b); - } - return this; -}; - -/** - * Puts bytes in this buffer. The bytes may be given as a string, an - * ArrayBuffer, a DataView, or a TypedArray. - * - * @param bytes the bytes to put. - * @param [encoding] the encoding for the first parameter ('binary', 'utf8', - * 'utf16', 'hex'), if it is a string (default: 'binary'). - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putBytes = function(bytes, encoding) { - if(util$1.isArrayBufferView(bytes)) { - var src = new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength); - var len = src.byteLength - src.byteOffset; - this.accommodate(len); - var dst = new Uint8Array(this.data.buffer, this.write); - dst.set(src); - this.write += len; - return this; - } - - if(util$1.isArrayBuffer(bytes)) { - var src = new Uint8Array(bytes); - this.accommodate(src.byteLength); - var dst = new Uint8Array(this.data.buffer); - dst.set(src, this.write); - this.write += src.byteLength; - return this; - } - - // bytes is a util.DataBuffer or equivalent - if(bytes instanceof util$1.DataBuffer || - (typeof bytes === 'object' && - typeof bytes.read === 'number' && typeof bytes.write === 'number' && - util$1.isArrayBufferView(bytes.data))) { - var src = new Uint8Array(bytes.data.byteLength, bytes.read, bytes.length()); - this.accommodate(src.byteLength); - var dst = new Uint8Array(bytes.data.byteLength, this.write); - dst.set(src); - this.write += src.byteLength; - return this; - } - - if(bytes instanceof util$1.ByteStringBuffer) { - // copy binary string and process as the same as a string parameter below - bytes = bytes.data; - encoding = 'binary'; - } - - // string conversion - encoding = encoding || 'binary'; - if(typeof bytes === 'string') { - var view; - - // decode from string - if(encoding === 'hex') { - this.accommodate(Math.ceil(bytes.length / 2)); - view = new Uint8Array(this.data.buffer, this.write); - this.write += util$1.binary.hex.decode(bytes, view, this.write); - return this; - } - if(encoding === 'base64') { - this.accommodate(Math.ceil(bytes.length / 4) * 3); - view = new Uint8Array(this.data.buffer, this.write); - this.write += util$1.binary.base64.decode(bytes, view, this.write); - return this; - } - - // encode text as UTF-8 bytes - if(encoding === 'utf8') { - // encode as UTF-8 then decode string as raw binary - bytes = util$1.encodeUtf8(bytes); - encoding = 'binary'; - } - - // decode string as raw binary - if(encoding === 'binary' || encoding === 'raw') { - // one byte per character - this.accommodate(bytes.length); - view = new Uint8Array(this.data.buffer, this.write); - this.write += util$1.binary.raw.decode(view); - return this; - } - - // encode text as UTF-16 bytes - if(encoding === 'utf16') { - // two bytes per character - this.accommodate(bytes.length * 2); - view = new Uint16Array(this.data.buffer, this.write); - this.write += util$1.text.utf16.encode(view); - return this; - } - - throw new Error('Invalid encoding: ' + encoding); - } - - throw Error('Invalid parameter: ' + bytes); -}; - -/** - * Puts the given buffer into this buffer. - * - * @param buffer the buffer to put into this one. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putBuffer = function(buffer) { - this.putBytes(buffer); - buffer.clear(); - return this; -}; - -/** - * Puts a string into this buffer. - * - * @param str the string to put. - * @param [encoding] the encoding for the string (default: 'utf16'). - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putString = function(str) { - return this.putBytes(str, 'utf16'); -}; - -/** - * Puts a 16-bit integer in this buffer in big-endian order. - * - * @param i the 16-bit integer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putInt16 = function(i) { - this.accommodate(2); - this.data.setInt16(this.write, i); - this.write += 2; - return this; -}; - -/** - * Puts a 24-bit integer in this buffer in big-endian order. - * - * @param i the 24-bit integer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putInt24 = function(i) { - this.accommodate(3); - this.data.setInt16(this.write, i >> 8 & 0xFFFF); - this.data.setInt8(this.write, i >> 16 & 0xFF); - this.write += 3; - return this; -}; - -/** - * Puts a 32-bit integer in this buffer in big-endian order. - * - * @param i the 32-bit integer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putInt32 = function(i) { - this.accommodate(4); - this.data.setInt32(this.write, i); - this.write += 4; - return this; -}; - -/** - * Puts a 16-bit integer in this buffer in little-endian order. - * - * @param i the 16-bit integer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putInt16Le = function(i) { - this.accommodate(2); - this.data.setInt16(this.write, i, true); - this.write += 2; - return this; -}; - -/** - * Puts a 24-bit integer in this buffer in little-endian order. - * - * @param i the 24-bit integer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putInt24Le = function(i) { - this.accommodate(3); - this.data.setInt8(this.write, i >> 16 & 0xFF); - this.data.setInt16(this.write, i >> 8 & 0xFFFF, true); - this.write += 3; - return this; -}; - -/** - * Puts a 32-bit integer in this buffer in little-endian order. - * - * @param i the 32-bit integer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putInt32Le = function(i) { - this.accommodate(4); - this.data.setInt32(this.write, i, true); - this.write += 4; - return this; -}; - -/** - * Puts an n-bit integer in this buffer in big-endian order. - * - * @param i the n-bit integer. - * @param n the number of bits in the integer (8, 16, 24, or 32). - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putInt = function(i, n) { - _checkBitsParam(n); - this.accommodate(n / 8); - do { - n -= 8; - this.data.setInt8(this.write++, (i >> n) & 0xFF); - } while(n > 0); - return this; -}; - -/** - * Puts a signed n-bit integer in this buffer in big-endian order. Two's - * complement representation is used. - * - * @param i the n-bit integer. - * @param n the number of bits in the integer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.putSignedInt = function(i, n) { - _checkBitsParam(n); - this.accommodate(n / 8); - if(i < 0) { - i += 2 << (n - 1); - } - return this.putInt(i, n); -}; - -/** - * Gets a byte from this buffer and advances the read pointer by 1. - * - * @return the byte. - */ -util$1.DataBuffer.prototype.getByte = function() { - return this.data.getInt8(this.read++); -}; - -/** - * Gets a uint16 from this buffer in big-endian order and advances the read - * pointer by 2. - * - * @return the uint16. - */ -util$1.DataBuffer.prototype.getInt16 = function() { - var rval = this.data.getInt16(this.read); - this.read += 2; - return rval; -}; - -/** - * Gets a uint24 from this buffer in big-endian order and advances the read - * pointer by 3. - * - * @return the uint24. - */ -util$1.DataBuffer.prototype.getInt24 = function() { - var rval = ( - this.data.getInt16(this.read) << 8 ^ - this.data.getInt8(this.read + 2)); - this.read += 3; - return rval; -}; - -/** - * Gets a uint32 from this buffer in big-endian order and advances the read - * pointer by 4. - * - * @return the word. - */ -util$1.DataBuffer.prototype.getInt32 = function() { - var rval = this.data.getInt32(this.read); - this.read += 4; - return rval; -}; - -/** - * Gets a uint16 from this buffer in little-endian order and advances the read - * pointer by 2. - * - * @return the uint16. - */ -util$1.DataBuffer.prototype.getInt16Le = function() { - var rval = this.data.getInt16(this.read, true); - this.read += 2; - return rval; -}; - -/** - * Gets a uint24 from this buffer in little-endian order and advances the read - * pointer by 3. - * - * @return the uint24. - */ -util$1.DataBuffer.prototype.getInt24Le = function() { - var rval = ( - this.data.getInt8(this.read) ^ - this.data.getInt16(this.read + 1, true) << 8); - this.read += 3; - return rval; -}; - -/** - * Gets a uint32 from this buffer in little-endian order and advances the read - * pointer by 4. - * - * @return the word. - */ -util$1.DataBuffer.prototype.getInt32Le = function() { - var rval = this.data.getInt32(this.read, true); - this.read += 4; - return rval; -}; - -/** - * Gets an n-bit integer from this buffer in big-endian order and advances the - * read pointer by n/8. - * - * @param n the number of bits in the integer (8, 16, 24, or 32). - * - * @return the integer. - */ -util$1.DataBuffer.prototype.getInt = function(n) { - _checkBitsParam(n); - var rval = 0; - do { - // TODO: Use (rval * 0x100) if adding support for 33 to 53 bits. - rval = (rval << 8) + this.data.getInt8(this.read++); - n -= 8; - } while(n > 0); - return rval; -}; - -/** - * Gets a signed n-bit integer from this buffer in big-endian order, using - * two's complement, and advances the read pointer by n/8. - * - * @param n the number of bits in the integer (8, 16, 24, or 32). - * - * @return the integer. - */ -util$1.DataBuffer.prototype.getSignedInt = function(n) { - // getInt checks n - var x = this.getInt(n); - var max = 2 << (n - 2); - if(x >= max) { - x -= max << 1; - } - return x; -}; - -/** - * Reads bytes out as a binary encoded string and clears them from the - * buffer. - * - * @param count the number of bytes to read, undefined or null for all. - * - * @return a binary encoded string of bytes. - */ -util$1.DataBuffer.prototype.getBytes = function(count) { - // TODO: deprecate this method, it is poorly named and - // this.toString('binary') replaces it - // add a toTypedArray()/toArrayBuffer() function - var rval; - if(count) { - // read count bytes - count = Math.min(this.length(), count); - rval = this.data.slice(this.read, this.read + count); - this.read += count; - } else if(count === 0) { - rval = ''; - } else { - // read all bytes, optimize to only copy when needed - rval = (this.read === 0) ? this.data : this.data.slice(this.read); - this.clear(); - } - return rval; -}; - -/** - * Gets a binary encoded string of the bytes from this buffer without - * modifying the read pointer. - * - * @param count the number of bytes to get, omit to get all. - * - * @return a string full of binary encoded characters. - */ -util$1.DataBuffer.prototype.bytes = function(count) { - // TODO: deprecate this method, it is poorly named, add "getString()" - return (typeof(count) === 'undefined' ? - this.data.slice(this.read) : - this.data.slice(this.read, this.read + count)); -}; - -/** - * Gets a byte at the given index without modifying the read pointer. - * - * @param i the byte index. - * - * @return the byte. - */ -util$1.DataBuffer.prototype.at = function(i) { - return this.data.getUint8(this.read + i); -}; - -/** - * Puts a byte at the given index without modifying the read pointer. - * - * @param i the byte index. - * @param b the byte to put. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.setAt = function(i, b) { - this.data.setUint8(i, b); - return this; -}; - -/** - * Gets the last byte without modifying the read pointer. - * - * @return the last byte. - */ -util$1.DataBuffer.prototype.last = function() { - return this.data.getUint8(this.write - 1); -}; - -/** - * Creates a copy of this buffer. - * - * @return the copy. - */ -util$1.DataBuffer.prototype.copy = function() { - return new util$1.DataBuffer(this); -}; - -/** - * Compacts this buffer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.compact = function() { - if(this.read > 0) { - var src = new Uint8Array(this.data.buffer, this.read); - var dst = new Uint8Array(src.byteLength); - dst.set(src); - this.data = new DataView(dst); - this.write -= this.read; - this.read = 0; - } - return this; -}; - -/** - * Clears this buffer. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.clear = function() { - this.data = new DataView(new ArrayBuffer(0)); - this.read = this.write = 0; - return this; -}; - -/** - * Shortens this buffer by triming bytes off of the end of this buffer. - * - * @param count the number of bytes to trim off. - * - * @return this buffer. - */ -util$1.DataBuffer.prototype.truncate = function(count) { - this.write = Math.max(0, this.length() - count); - this.read = Math.min(this.read, this.write); - return this; -}; - -/** - * Converts this buffer to a hexadecimal string. - * - * @return a hexadecimal string. - */ -util$1.DataBuffer.prototype.toHex = function() { - var rval = ''; - for(var i = this.read; i < this.data.byteLength; ++i) { - var b = this.data.getUint8(i); - if(b < 16) { - rval += '0'; - } - rval += b.toString(16); - } - return rval; -}; - -/** - * Converts this buffer to a string, using the given encoding. If no - * encoding is given, 'utf8' (UTF-8) is used. - * - * @param [encoding] the encoding to use: 'binary', 'utf8', 'utf16', 'hex', - * 'base64' (default: 'utf8'). - * - * @return a string representation of the bytes in this buffer. - */ -util$1.DataBuffer.prototype.toString = function(encoding) { - var view = new Uint8Array(this.data, this.read, this.length()); - encoding = encoding || 'utf8'; - - // encode to string - if(encoding === 'binary' || encoding === 'raw') { - return util$1.binary.raw.encode(view); - } - if(encoding === 'hex') { - return util$1.binary.hex.encode(view); - } - if(encoding === 'base64') { - return util$1.binary.base64.encode(view); - } - - // decode to text - if(encoding === 'utf8') { - return util$1.text.utf8.decode(view); - } - if(encoding === 'utf16') { - return util$1.text.utf16.decode(view); - } - - throw new Error('Invalid encoding: ' + encoding); -}; - -/** End Buffer w/UInt8Array backing */ - -/** - * Creates a buffer that stores bytes. A value may be given to populate the - * buffer with data. This value can either be string of encoded bytes or a - * regular string of characters. When passing a string of binary encoded - * bytes, the encoding `raw` should be given. This is also the default. When - * passing a string of characters, the encoding `utf8` should be given. - * - * @param [input] a string with encoded bytes to store in the buffer. - * @param [encoding] (default: 'raw', other: 'utf8'). - */ -util$1.createBuffer = function(input, encoding) { - // TODO: deprecate, use new ByteBuffer() instead - encoding = encoding || 'raw'; - if(input !== undefined && encoding === 'utf8') { - input = util$1.encodeUtf8(input); - } - return new util$1.ByteBuffer(input); -}; - -/** - * Fills a string with a particular value. If you want the string to be a byte - * string, pass in String.fromCharCode(theByte). - * - * @param c the character to fill the string with, use String.fromCharCode - * to fill the string with a byte value. - * @param n the number of characters of value c to fill with. - * - * @return the filled string. - */ -util$1.fillString = function(c, n) { - var s = ''; - while(n > 0) { - if(n & 1) { - s += c; - } - n >>>= 1; - if(n > 0) { - c += c; - } - } - return s; -}; - -/** - * Performs a per byte XOR between two byte strings and returns the result as a - * string of bytes. - * - * @param s1 first string of bytes. - * @param s2 second string of bytes. - * @param n the number of bytes to XOR. - * - * @return the XOR'd result. - */ -util$1.xorBytes = function(s1, s2, n) { - var s3 = ''; - var b = ''; - var t = ''; - var i = 0; - var c = 0; - for(; n > 0; --n, ++i) { - b = s1.charCodeAt(i) ^ s2.charCodeAt(i); - if(c >= 10) { - s3 += t; - t = ''; - c = 0; - } - t += String.fromCharCode(b); - ++c; - } - s3 += t; - return s3; -}; - -/** - * Converts a hex string into a 'binary' encoded string of bytes. - * - * @param hex the hexadecimal string to convert. - * - * @return the binary-encoded string of bytes. - */ -util$1.hexToBytes = function(hex) { - // TODO: deprecate: "Deprecated. Use util.binary.hex.decode instead." - var rval = ''; - var i = 0; - if(hex.length & 1 == 1) { - // odd number of characters, convert first character alone - i = 1; - rval += String.fromCharCode(parseInt(hex[0], 16)); - } - // convert 2 characters (1 byte) at a time - for(; i < hex.length; i += 2) { - rval += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); - } - return rval; -}; - -/** - * Converts a 'binary' encoded string of bytes to hex. - * - * @param bytes the byte string to convert. - * - * @return the string of hexadecimal characters. - */ -util$1.bytesToHex = function(bytes) { - // TODO: deprecate: "Deprecated. Use util.binary.hex.encode instead." - return util$1.createBuffer(bytes).toHex(); -}; - -/** - * Converts an 32-bit integer to 4-big-endian byte string. - * - * @param i the integer. - * - * @return the byte string. - */ -util$1.int32ToBytes = function(i) { - return ( - String.fromCharCode(i >> 24 & 0xFF) + - String.fromCharCode(i >> 16 & 0xFF) + - String.fromCharCode(i >> 8 & 0xFF) + - String.fromCharCode(i & 0xFF)); -}; - -// base64 characters, reverse mapping -var _base64 = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; -var _base64Idx = [ -/*43 -43 = 0*/ -/*'+', 1, 2, 3,'/' */ - 62, -1, -1, -1, 63, - -/*'0','1','2','3','4','5','6','7','8','9' */ - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - -/*15, 16, 17,'=', 19, 20, 21 */ - -1, -1, -1, 64, -1, -1, -1, - -/*65 - 43 = 22*/ -/*'A','B','C','D','E','F','G','H','I','J','K','L','M', */ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - -/*'N','O','P','Q','R','S','T','U','V','W','X','Y','Z' */ - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - -/*91 - 43 = 48 */ -/*48, 49, 50, 51, 52, 53 */ - -1, -1, -1, -1, -1, -1, - -/*97 - 43 = 54*/ -/*'a','b','c','d','e','f','g','h','i','j','k','l','m' */ - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - -/*'n','o','p','q','r','s','t','u','v','w','x','y','z' */ - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 -]; - -// base58 characters (Bitcoin alphabet) -var _base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; - -/** - * Base64 encodes a 'binary' encoded string of bytes. - * - * @param input the binary encoded string of bytes to base64-encode. - * @param maxline the maximum number of encoded characters per line to use, - * defaults to none. - * - * @return the base64-encoded output. - */ -util$1.encode64 = function(input, maxline) { - // TODO: deprecate: "Deprecated. Use util.binary.base64.encode instead." - var line = ''; - var output = ''; - var chr1, chr2, chr3; - var i = 0; - while(i < input.length) { - chr1 = input.charCodeAt(i++); - chr2 = input.charCodeAt(i++); - chr3 = input.charCodeAt(i++); - - // encode 4 character group - line += _base64.charAt(chr1 >> 2); - line += _base64.charAt(((chr1 & 3) << 4) | (chr2 >> 4)); - if(isNaN(chr2)) { - line += '=='; - } else { - line += _base64.charAt(((chr2 & 15) << 2) | (chr3 >> 6)); - line += isNaN(chr3) ? '=' : _base64.charAt(chr3 & 63); - } - - if(maxline && line.length > maxline) { - output += line.substr(0, maxline) + '\r\n'; - line = line.substr(maxline); - } - } - output += line; - return output; -}; - -/** - * Base64 decodes a string into a 'binary' encoded string of bytes. - * - * @param input the base64-encoded input. - * - * @return the binary encoded string. - */ -util$1.decode64 = function(input) { - // TODO: deprecate: "Deprecated. Use util.binary.base64.decode instead." - - // remove all non-base64 characters - input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); - - var output = ''; - var enc1, enc2, enc3, enc4; - var i = 0; - - while(i < input.length) { - enc1 = _base64Idx[input.charCodeAt(i++) - 43]; - enc2 = _base64Idx[input.charCodeAt(i++) - 43]; - enc3 = _base64Idx[input.charCodeAt(i++) - 43]; - enc4 = _base64Idx[input.charCodeAt(i++) - 43]; - - output += String.fromCharCode((enc1 << 2) | (enc2 >> 4)); - if(enc3 !== 64) { - // decoded at least 2 bytes - output += String.fromCharCode(((enc2 & 15) << 4) | (enc3 >> 2)); - if(enc4 !== 64) { - // decoded 3 bytes - output += String.fromCharCode(((enc3 & 3) << 6) | enc4); - } - } - } - - return output; -}; - -/** - * Encodes the given string of characters (a standard JavaScript - * string) as a binary encoded string where the bytes represent - * a UTF-8 encoded string of characters. Non-ASCII characters will be - * encoded as multiple bytes according to UTF-8. - * - * @param str a standard string of characters to encode. - * - * @return the binary encoded string. - */ -util$1.encodeUtf8 = function(str) { - return unescape(encodeURIComponent(str)); -}; - -/** - * Decodes a binary encoded string that contains bytes that - * represent a UTF-8 encoded string of characters -- into a - * string of characters (a standard JavaScript string). - * - * @param str the binary encoded string to decode. - * - * @return the resulting standard string of characters. - */ -util$1.decodeUtf8 = function(str) { - return decodeURIComponent(escape(str)); -}; - -// binary encoding/decoding tools -// FIXME: Experimental. Do not use yet. -util$1.binary = { - raw: {}, - hex: {}, - base64: {}, - base58: {}, - baseN : { - encode: baseN.encode, - decode: baseN.decode - } -}; - -/** - * Encodes a Uint8Array as a binary-encoded string. This encoding uses - * a value between 0 and 255 for each character. - * - * @param bytes the Uint8Array to encode. - * - * @return the binary-encoded string. - */ -util$1.binary.raw.encode = function(bytes) { - return String.fromCharCode.apply(null, bytes); -}; - -/** - * Decodes a binary-encoded string to a Uint8Array. This encoding uses - * a value between 0 and 255 for each character. - * - * @param str the binary-encoded string to decode. - * @param [output] an optional Uint8Array to write the output to; if it - * is too small, an exception will be thrown. - * @param [offset] the start offset for writing to the output (default: 0). - * - * @return the Uint8Array or the number of bytes written if output was given. - */ -util$1.binary.raw.decode = function(str, output, offset) { - var out = output; - if(!out) { - out = new Uint8Array(str.length); - } - offset = offset || 0; - var j = offset; - for(var i = 0; i < str.length; ++i) { - out[j++] = str.charCodeAt(i); - } - return output ? (j - offset) : out; -}; - -/** - * Encodes a 'binary' string, ArrayBuffer, DataView, TypedArray, or - * ByteBuffer as a string of hexadecimal characters. - * - * @param bytes the bytes to convert. - * - * @return the string of hexadecimal characters. - */ -util$1.binary.hex.encode = util$1.bytesToHex; - -/** - * Decodes a hex-encoded string to a Uint8Array. - * - * @param hex the hexadecimal string to convert. - * @param [output] an optional Uint8Array to write the output to; if it - * is too small, an exception will be thrown. - * @param [offset] the start offset for writing to the output (default: 0). - * - * @return the Uint8Array or the number of bytes written if output was given. - */ -util$1.binary.hex.decode = function(hex, output, offset) { - var out = output; - if(!out) { - out = new Uint8Array(Math.ceil(hex.length / 2)); - } - offset = offset || 0; - var i = 0, j = offset; - if(hex.length & 1) { - // odd number of characters, convert first character alone - i = 1; - out[j++] = parseInt(hex[0], 16); - } - // convert 2 characters (1 byte) at a time - for(; i < hex.length; i += 2) { - out[j++] = parseInt(hex.substr(i, 2), 16); - } - return output ? (j - offset) : out; -}; - -/** - * Base64-encodes a Uint8Array. - * - * @param input the Uint8Array to encode. - * @param maxline the maximum number of encoded characters per line to use, - * defaults to none. - * - * @return the base64-encoded output string. - */ -util$1.binary.base64.encode = function(input, maxline) { - var line = ''; - var output = ''; - var chr1, chr2, chr3; - var i = 0; - while(i < input.byteLength) { - chr1 = input[i++]; - chr2 = input[i++]; - chr3 = input[i++]; - - // encode 4 character group - line += _base64.charAt(chr1 >> 2); - line += _base64.charAt(((chr1 & 3) << 4) | (chr2 >> 4)); - if(isNaN(chr2)) { - line += '=='; - } else { - line += _base64.charAt(((chr2 & 15) << 2) | (chr3 >> 6)); - line += isNaN(chr3) ? '=' : _base64.charAt(chr3 & 63); - } - - if(maxline && line.length > maxline) { - output += line.substr(0, maxline) + '\r\n'; - line = line.substr(maxline); - } - } - output += line; - return output; -}; - -/** - * Decodes a base64-encoded string to a Uint8Array. - * - * @param input the base64-encoded input string. - * @param [output] an optional Uint8Array to write the output to; if it - * is too small, an exception will be thrown. - * @param [offset] the start offset for writing to the output (default: 0). - * - * @return the Uint8Array or the number of bytes written if output was given. - */ -util$1.binary.base64.decode = function(input, output, offset) { - var out = output; - if(!out) { - out = new Uint8Array(Math.ceil(input.length / 4) * 3); - } - - // remove all non-base64 characters - input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); - - offset = offset || 0; - var enc1, enc2, enc3, enc4; - var i = 0, j = offset; - - while(i < input.length) { - enc1 = _base64Idx[input.charCodeAt(i++) - 43]; - enc2 = _base64Idx[input.charCodeAt(i++) - 43]; - enc3 = _base64Idx[input.charCodeAt(i++) - 43]; - enc4 = _base64Idx[input.charCodeAt(i++) - 43]; - - out[j++] = (enc1 << 2) | (enc2 >> 4); - if(enc3 !== 64) { - // decoded at least 2 bytes - out[j++] = ((enc2 & 15) << 4) | (enc3 >> 2); - if(enc4 !== 64) { - // decoded 3 bytes - out[j++] = ((enc3 & 3) << 6) | enc4; - } - } - } - - // make sure result is the exact decoded length - return output ? (j - offset) : out.subarray(0, j); -}; - -// add support for base58 encoding/decoding with Bitcoin alphabet -util$1.binary.base58.encode = function(input, maxline) { - return util$1.binary.baseN.encode(input, _base58, maxline); -}; -util$1.binary.base58.decode = function(input, maxline) { - return util$1.binary.baseN.decode(input, _base58, maxline); -}; - -// text encoding/decoding tools -// FIXME: Experimental. Do not use yet. -util$1.text = { - utf8: {}, - utf16: {} -}; - -/** - * Encodes the given string as UTF-8 in a Uint8Array. - * - * @param str the string to encode. - * @param [output] an optional Uint8Array to write the output to; if it - * is too small, an exception will be thrown. - * @param [offset] the start offset for writing to the output (default: 0). - * - * @return the Uint8Array or the number of bytes written if output was given. - */ -util$1.text.utf8.encode = function(str, output, offset) { - str = util$1.encodeUtf8(str); - var out = output; - if(!out) { - out = new Uint8Array(str.length); - } - offset = offset || 0; - var j = offset; - for(var i = 0; i < str.length; ++i) { - out[j++] = str.charCodeAt(i); - } - return output ? (j - offset) : out; -}; - -/** - * Decodes the UTF-8 contents from a Uint8Array. - * - * @param bytes the Uint8Array to decode. - * - * @return the resulting string. - */ -util$1.text.utf8.decode = function(bytes) { - return util$1.decodeUtf8(String.fromCharCode.apply(null, bytes)); -}; - -/** - * Encodes the given string as UTF-16 in a Uint8Array. - * - * @param str the string to encode. - * @param [output] an optional Uint8Array to write the output to; if it - * is too small, an exception will be thrown. - * @param [offset] the start offset for writing to the output (default: 0). - * - * @return the Uint8Array or the number of bytes written if output was given. - */ -util$1.text.utf16.encode = function(str, output, offset) { - var out = output; - if(!out) { - out = new Uint8Array(str.length * 2); - } - var view = new Uint16Array(out.buffer); - offset = offset || 0; - var j = offset; - var k = offset; - for(var i = 0; i < str.length; ++i) { - view[k++] = str.charCodeAt(i); - j += 2; - } - return output ? (j - offset) : out; -}; - -/** - * Decodes the UTF-16 contents from a Uint8Array. - * - * @param bytes the Uint8Array to decode. - * - * @return the resulting string. - */ -util$1.text.utf16.decode = function(bytes) { - return String.fromCharCode.apply(null, new Uint16Array(bytes.buffer)); -}; - -/** - * Deflates the given data using a flash interface. - * - * @param api the flash interface. - * @param bytes the data. - * @param raw true to return only raw deflate data, false to include zlib - * header and trailer. - * - * @return the deflated data as a string. - */ -util$1.deflate = function(api, bytes, raw) { - bytes = util$1.decode64(api.deflate(util$1.encode64(bytes)).rval); - - // strip zlib header and trailer if necessary - if(raw) { - // zlib header is 2 bytes (CMF,FLG) where FLG indicates that - // there is a 4-byte DICT (alder-32) block before the data if - // its 5th bit is set - var start = 2; - var flg = bytes.charCodeAt(1); - if(flg & 0x20) { - start = 6; - } - // zlib trailer is 4 bytes of adler-32 - bytes = bytes.substring(start, bytes.length - 4); - } - - return bytes; -}; - -/** - * Inflates the given data using a flash interface. - * - * @param api the flash interface. - * @param bytes the data. - * @param raw true if the incoming data has no zlib header or trailer and is - * raw DEFLATE data. - * - * @return the inflated data as a string, null on error. - */ -util$1.inflate = function(api, bytes, raw) { - // TODO: add zlib header and trailer if necessary/possible - var rval = api.inflate(util$1.encode64(bytes)).rval; - return (rval === null) ? null : util$1.decode64(rval); -}; - -/** - * Sets a storage object. - * - * @param api the storage interface. - * @param id the storage ID to use. - * @param obj the storage object, null to remove. - */ -var _setStorageObject = function(api, id, obj) { - if(!api) { - throw new Error('WebStorage not available.'); - } - - var rval; - if(obj === null) { - rval = api.removeItem(id); - } else { - // json-encode and base64-encode object - obj = util$1.encode64(JSON.stringify(obj)); - rval = api.setItem(id, obj); - } - - // handle potential flash error - if(typeof(rval) !== 'undefined' && rval.rval !== true) { - var error = new Error(rval.error.message); - error.id = rval.error.id; - error.name = rval.error.name; - throw error; - } -}; - -/** - * Gets a storage object. - * - * @param api the storage interface. - * @param id the storage ID to use. - * - * @return the storage object entry or null if none exists. - */ -var _getStorageObject = function(api, id) { - if(!api) { - throw new Error('WebStorage not available.'); - } - - // get the existing entry - var rval = api.getItem(id); - - /* Note: We check api.init because we can't do (api == localStorage) - on IE because of "Class doesn't support Automation" exception. Only - the flash api has an init method so this works too, but we need a - better solution in the future. */ - - // flash returns item wrapped in an object, handle special case - if(api.init) { - if(rval.rval === null) { - if(rval.error) { - var error = new Error(rval.error.message); - error.id = rval.error.id; - error.name = rval.error.name; - throw error; - } - // no error, but also no item - rval = null; - } else { - rval = rval.rval; - } - } - - // handle decoding - if(rval !== null) { - // base64-decode and json-decode data - rval = JSON.parse(util$1.decode64(rval)); - } - - return rval; -}; - -/** - * Stores an item in local storage. - * - * @param api the storage interface. - * @param id the storage ID to use. - * @param key the key for the item. - * @param data the data for the item (any javascript object/primitive). - */ -var _setItem = function(api, id, key, data) { - // get storage object - var obj = _getStorageObject(api, id); - if(obj === null) { - // create a new storage object - obj = {}; - } - // update key - obj[key] = data; - - // set storage object - _setStorageObject(api, id, obj); -}; - -/** - * Gets an item from local storage. - * - * @param api the storage interface. - * @param id the storage ID to use. - * @param key the key for the item. - * - * @return the item. - */ -var _getItem = function(api, id, key) { - // get storage object - var rval = _getStorageObject(api, id); - if(rval !== null) { - // return data at key - rval = (key in rval) ? rval[key] : null; - } - - return rval; -}; - -/** - * Removes an item from local storage. - * - * @param api the storage interface. - * @param id the storage ID to use. - * @param key the key for the item. - */ -var _removeItem = function(api, id, key) { - // get storage object - var obj = _getStorageObject(api, id); - if(obj !== null && key in obj) { - // remove key - delete obj[key]; - - // see if entry has no keys remaining - var empty = true; - for(var prop in obj) { - empty = false; - break; - } - if(empty) { - // remove entry entirely if no keys are left - obj = null; - } - - // set storage object - _setStorageObject(api, id, obj); - } -}; - -/** - * Clears the local disk storage identified by the given ID. - * - * @param api the storage interface. - * @param id the storage ID to use. - */ -var _clearItems = function(api, id) { - _setStorageObject(api, id, null); -}; - -/** - * Calls a storage function. - * - * @param func the function to call. - * @param args the arguments for the function. - * @param location the location argument. - * - * @return the return value from the function. - */ -var _callStorageFunction = function(func, args, location) { - var rval = null; - - // default storage types - if(typeof(location) === 'undefined') { - location = ['web', 'flash']; - } - - // apply storage types in order of preference - var type; - var done = false; - var exception = null; - for(var idx in location) { - type = location[idx]; - try { - if(type === 'flash' || type === 'both') { - if(args[0] === null) { - throw new Error('Flash local storage not available.'); - } - rval = func.apply(this, args); - done = (type === 'flash'); - } - if(type === 'web' || type === 'both') { - args[0] = localStorage; - rval = func.apply(this, args); - done = true; - } - } catch(ex) { - exception = ex; - } - if(done) { - break; - } - } - - if(!done) { - throw exception; - } - - return rval; -}; - -/** - * Stores an item on local disk. - * - * The available types of local storage include 'flash', 'web', and 'both'. - * - * The type 'flash' refers to flash local storage (SharedObject). In order - * to use flash local storage, the 'api' parameter must be valid. The type - * 'web' refers to WebStorage, if supported by the browser. The type 'both' - * refers to storing using both 'flash' and 'web', not just one or the - * other. - * - * The location array should list the storage types to use in order of - * preference: - * - * ['flash']: flash only storage - * ['web']: web only storage - * ['both']: try to store in both - * ['flash','web']: store in flash first, but if not available, 'web' - * ['web','flash']: store in web first, but if not available, 'flash' - * - * The location array defaults to: ['web', 'flash'] - * - * @param api the flash interface, null to use only WebStorage. - * @param id the storage ID to use. - * @param key the key for the item. - * @param data the data for the item (any javascript object/primitive). - * @param location an array with the preferred types of storage to use. - */ -util$1.setItem = function(api, id, key, data, location) { - _callStorageFunction(_setItem, arguments, location); -}; - -/** - * Gets an item on local disk. - * - * Set setItem() for details on storage types. - * - * @param api the flash interface, null to use only WebStorage. - * @param id the storage ID to use. - * @param key the key for the item. - * @param location an array with the preferred types of storage to use. - * - * @return the item. - */ -util$1.getItem = function(api, id, key, location) { - return _callStorageFunction(_getItem, arguments, location); -}; - -/** - * Removes an item on local disk. - * - * Set setItem() for details on storage types. - * - * @param api the flash interface. - * @param id the storage ID to use. - * @param key the key for the item. - * @param location an array with the preferred types of storage to use. - */ -util$1.removeItem = function(api, id, key, location) { - _callStorageFunction(_removeItem, arguments, location); -}; - -/** - * Clears the local disk storage identified by the given ID. - * - * Set setItem() for details on storage types. - * - * @param api the flash interface if flash is available. - * @param id the storage ID to use. - * @param location an array with the preferred types of storage to use. - */ -util$1.clearItems = function(api, id, location) { - _callStorageFunction(_clearItems, arguments, location); -}; - -/** - * Check if an object is empty. - * - * Taken from: - * http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object-from-json/679937#679937 - * - * @param object the object to check. - */ -util$1.isEmpty = function(obj) { - for(var prop in obj) { - if(obj.hasOwnProperty(prop)) { - return false; - } - } - return true; -}; - -/** - * Format with simple printf-style interpolation. - * - * %%: literal '%' - * %s,%o: convert next argument into a string. - * - * @param format the string to format. - * @param ... arguments to interpolate into the format string. - */ -util$1.format = function(format) { - var re = /%./g; - // current match - var match; - // current part - var part; - // current arg index - var argi = 0; - // collected parts to recombine later - var parts = []; - // last index found - var last = 0; - // loop while matches remain - while((match = re.exec(format))) { - part = format.substring(last, re.lastIndex - 2); - // don't add empty strings (ie, parts between %s%s) - if(part.length > 0) { - parts.push(part); - } - last = re.lastIndex; - // switch on % code - var code = match[0][1]; - switch(code) { - case 's': - case 'o': - // check if enough arguments were given - if(argi < arguments.length) { - parts.push(arguments[argi++ + 1]); - } else { - parts.push(''); - } - break; - // FIXME: do proper formating for numbers, etc - //case 'f': - //case 'd': - case '%': - parts.push('%'); - break; - default: - parts.push('<%' + code + '?>'); - } - } - // add trailing part of format string - parts.push(format.substring(last)); - return parts.join(''); -}; - -/** - * Formats a number. - * - * http://snipplr.com/view/5945/javascript-numberformat--ported-from-php/ - */ -util$1.formatNumber = function(number, decimals, dec_point, thousands_sep) { - // http://kevin.vanzonneveld.net - // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) - // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - // + bugfix by: Michael White (http://crestidg.com) - // + bugfix by: Benjamin Lupton - // + bugfix by: Allan Jensen (http://www.winternet.no) - // + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) - // * example 1: number_format(1234.5678, 2, '.', ''); - // * returns 1: 1234.57 - - var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals; - var d = dec_point === undefined ? ',' : dec_point; - var t = thousands_sep === undefined ? - '.' : thousands_sep, s = n < 0 ? '-' : ''; - var i = parseInt((n = Math.abs(+n || 0).toFixed(c)), 10) + ''; - var j = (i.length > 3) ? i.length % 3 : 0; - return s + (j ? i.substr(0, j) + t : '') + - i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + t) + - (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ''); -}; - -/** - * Formats a byte size. - * - * http://snipplr.com/view/5949/format-humanize-file-byte-size-presentation-in-javascript/ - */ -util$1.formatSize = function(size) { - if(size >= 1073741824) { - size = util$1.formatNumber(size / 1073741824, 2, '.', '') + ' GiB'; - } else if(size >= 1048576) { - size = util$1.formatNumber(size / 1048576, 2, '.', '') + ' MiB'; - } else if(size >= 1024) { - size = util$1.formatNumber(size / 1024, 0) + ' KiB'; - } else { - size = util$1.formatNumber(size, 0) + ' bytes'; - } - return size; -}; - -/** - * Converts an IPv4 or IPv6 string representation into bytes (in network order). - * - * @param ip the IPv4 or IPv6 address to convert. - * - * @return the 4-byte IPv6 or 16-byte IPv6 address or null if the address can't - * be parsed. - */ -util$1.bytesFromIP = function(ip) { - if(ip.indexOf('.') !== -1) { - return util$1.bytesFromIPv4(ip); - } - if(ip.indexOf(':') !== -1) { - return util$1.bytesFromIPv6(ip); - } - return null; -}; - -/** - * Converts an IPv4 string representation into bytes (in network order). - * - * @param ip the IPv4 address to convert. - * - * @return the 4-byte address or null if the address can't be parsed. - */ -util$1.bytesFromIPv4 = function(ip) { - ip = ip.split('.'); - if(ip.length !== 4) { - return null; - } - var b = util$1.createBuffer(); - for(var i = 0; i < ip.length; ++i) { - var num = parseInt(ip[i], 10); - if(isNaN(num)) { - return null; - } - b.putByte(num); - } - return b.getBytes(); -}; - -/** - * Converts an IPv6 string representation into bytes (in network order). - * - * @param ip the IPv6 address to convert. - * - * @return the 16-byte address or null if the address can't be parsed. - */ -util$1.bytesFromIPv6 = function(ip) { - var blanks = 0; - ip = ip.split(':').filter(function(e) { - if(e.length === 0) ++blanks; - return true; - }); - var zeros = (8 - ip.length + blanks) * 2; - var b = util$1.createBuffer(); - for(var i = 0; i < 8; ++i) { - if(!ip[i] || ip[i].length === 0) { - b.fillWithByte(0, zeros); - zeros = 0; - continue; - } - var bytes = util$1.hexToBytes(ip[i]); - if(bytes.length < 2) { - b.putByte(0); - } - b.putBytes(bytes); - } - return b.getBytes(); -}; - -/** - * Converts 4-bytes into an IPv4 string representation or 16-bytes into - * an IPv6 string representation. The bytes must be in network order. - * - * @param bytes the bytes to convert. - * - * @return the IPv4 or IPv6 string representation if 4 or 16 bytes, - * respectively, are given, otherwise null. - */ -util$1.bytesToIP = function(bytes) { - if(bytes.length === 4) { - return util$1.bytesToIPv4(bytes); - } - if(bytes.length === 16) { - return util$1.bytesToIPv6(bytes); - } - return null; -}; - -/** - * Converts 4-bytes into an IPv4 string representation. The bytes must be - * in network order. - * - * @param bytes the bytes to convert. - * - * @return the IPv4 string representation or null for an invalid # of bytes. - */ -util$1.bytesToIPv4 = function(bytes) { - if(bytes.length !== 4) { - return null; - } - var ip = []; - for(var i = 0; i < bytes.length; ++i) { - ip.push(bytes.charCodeAt(i)); - } - return ip.join('.'); -}; - -/** - * Converts 16-bytes into an IPv16 string representation. The bytes must be - * in network order. - * - * @param bytes the bytes to convert. - * - * @return the IPv16 string representation or null for an invalid # of bytes. - */ -util$1.bytesToIPv6 = function(bytes) { - if(bytes.length !== 16) { - return null; - } - var ip = []; - var zeroGroups = []; - var zeroMaxGroup = 0; - for(var i = 0; i < bytes.length; i += 2) { - var hex = util$1.bytesToHex(bytes[i] + bytes[i + 1]); - // canonicalize zero representation - while(hex[0] === '0' && hex !== '0') { - hex = hex.substr(1); - } - if(hex === '0') { - var last = zeroGroups[zeroGroups.length - 1]; - var idx = ip.length; - if(!last || idx !== last.end + 1) { - zeroGroups.push({start: idx, end: idx}); - } else { - last.end = idx; - if((last.end - last.start) > - (zeroGroups[zeroMaxGroup].end - zeroGroups[zeroMaxGroup].start)) { - zeroMaxGroup = zeroGroups.length - 1; - } - } - } - ip.push(hex); - } - if(zeroGroups.length > 0) { - var group = zeroGroups[zeroMaxGroup]; - // only shorten group of length > 0 - if(group.end - group.start > 0) { - ip.splice(group.start, group.end - group.start + 1, ''); - if(group.start === 0) { - ip.unshift(''); - } - if(group.end === 7) { - ip.push(''); - } - } - } - return ip.join(':'); -}; - -/** - * Estimates the number of processes that can be run concurrently. If - * creating Web Workers, keep in mind that the main JavaScript process needs - * its own core. - * - * @param options the options to use: - * update true to force an update (not use the cached value). - * @param callback(err, max) called once the operation completes. - */ -util$1.estimateCores = function(options, callback) { - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - if('cores' in util$1 && !options.update) { - return callback(null, util$1.cores); - } - if(typeof navigator !== 'undefined' && - 'hardwareConcurrency' in navigator && - navigator.hardwareConcurrency > 0) { - util$1.cores = navigator.hardwareConcurrency; - return callback(null, util$1.cores); - } - if(typeof Worker === 'undefined') { - // workers not available - util$1.cores = 1; - return callback(null, util$1.cores); - } - if(typeof Blob === 'undefined') { - // can't estimate, default to 2 - util$1.cores = 2; - return callback(null, util$1.cores); - } - - // create worker concurrency estimation code as blob - var blobUrl = URL.createObjectURL(new Blob(['(', - function() { - self.addEventListener('message', function(e) { - // run worker for 4 ms - var st = Date.now(); - var et = st + 4; - self.postMessage({st: st, et: et}); - }); - }.toString(), - ')()'], {type: 'application/javascript'})); - - // take 5 samples using 16 workers - sample([], 5, 16); - - function sample(max, samples, numWorkers) { - if(samples === 0) { - // get overlap average - var avg = Math.floor(max.reduce(function(avg, x) { - return avg + x; - }, 0) / max.length); - util$1.cores = Math.max(1, avg); - URL.revokeObjectURL(blobUrl); - return callback(null, util$1.cores); - } - map(numWorkers, function(err, results) { - max.push(reduce(numWorkers, results)); - sample(max, samples - 1, numWorkers); - }); - } - - function map(numWorkers, callback) { - var workers = []; - var results = []; - for(var i = 0; i < numWorkers; ++i) { - var worker = new Worker(blobUrl); - worker.addEventListener('message', function(e) { - results.push(e.data); - if(results.length === numWorkers) { - for(var i = 0; i < numWorkers; ++i) { - workers[i].terminate(); - } - callback(null, results); - } - }); - workers.push(worker); - } - for(var i = 0; i < numWorkers; ++i) { - workers[i].postMessage(i); - } - } - - function reduce(numWorkers, results) { - // find overlapping time windows - var overlaps = []; - for(var n = 0; n < numWorkers; ++n) { - var r1 = results[n]; - var overlap = overlaps[n] = []; - for(var i = 0; i < numWorkers; ++i) { - if(n === i) { - continue; - } - var r2 = results[i]; - if((r1.st > r2.st && r1.st < r2.et) || - (r2.st > r1.st && r2.st < r1.et)) { - overlap.push(i); - } - } - } - // get maximum overlaps ... don't include overlapping worker itself - // as the main JS process was also being scheduled during the work and - // would have to be subtracted from the estimate anyway - return overlaps.reduce(function(max, overlap) { - return Math.max(max, overlap.length); - }, 0); - } -}; - -/** - * Cipher base API. - * - * @author Dave Longley - * - * Copyright (c) 2010-2014 Digital Bazaar, Inc. - */ - -var forge$B = forge$D; - - -forge$B.cipher = forge$B.cipher || {}; - -// registered algorithms -forge$B.cipher.algorithms = forge$B.cipher.algorithms || {}; - -/** - * Creates a cipher object that can be used to encrypt data using the given - * algorithm and key. The algorithm may be provided as a string value for a - * previously registered algorithm or it may be given as a cipher algorithm - * API object. - * - * @param algorithm the algorithm to use, either a string or an algorithm API - * object. - * @param key the key to use, as a binary-encoded string of bytes or a - * byte buffer. - * - * @return the cipher. - */ -forge$B.cipher.createCipher = function(algorithm, key) { - var api = algorithm; - if(typeof api === 'string') { - api = forge$B.cipher.getAlgorithm(api); - if(api) { - api = api(); - } - } - if(!api) { - throw new Error('Unsupported algorithm: ' + algorithm); - } - - // assume block cipher - return new forge$B.cipher.BlockCipher({ - algorithm: api, - key: key, - decrypt: false - }); -}; - -/** - * Creates a decipher object that can be used to decrypt data using the given - * algorithm and key. The algorithm may be provided as a string value for a - * previously registered algorithm or it may be given as a cipher algorithm - * API object. - * - * @param algorithm the algorithm to use, either a string or an algorithm API - * object. - * @param key the key to use, as a binary-encoded string of bytes or a - * byte buffer. - * - * @return the cipher. - */ -forge$B.cipher.createDecipher = function(algorithm, key) { - var api = algorithm; - if(typeof api === 'string') { - api = forge$B.cipher.getAlgorithm(api); - if(api) { - api = api(); - } - } - if(!api) { - throw new Error('Unsupported algorithm: ' + algorithm); - } - - // assume block cipher - return new forge$B.cipher.BlockCipher({ - algorithm: api, - key: key, - decrypt: true - }); -}; - -/** - * Registers an algorithm by name. If the name was already registered, the - * algorithm API object will be overwritten. - * - * @param name the name of the algorithm. - * @param algorithm the algorithm API object. - */ -forge$B.cipher.registerAlgorithm = function(name, algorithm) { - name = name.toUpperCase(); - forge$B.cipher.algorithms[name] = algorithm; -}; - -/** - * Gets a registered algorithm by name. - * - * @param name the name of the algorithm. - * - * @return the algorithm, if found, null if not. - */ -forge$B.cipher.getAlgorithm = function(name) { - name = name.toUpperCase(); - if(name in forge$B.cipher.algorithms) { - return forge$B.cipher.algorithms[name]; - } - return null; -}; - -var BlockCipher = forge$B.cipher.BlockCipher = function(options) { - this.algorithm = options.algorithm; - this.mode = this.algorithm.mode; - this.blockSize = this.mode.blockSize; - this._finish = false; - this._input = null; - this.output = null; - this._op = options.decrypt ? this.mode.decrypt : this.mode.encrypt; - this._decrypt = options.decrypt; - this.algorithm.initialize(options); -}; - -/** - * Starts or restarts the encryption or decryption process, whichever - * was previously configured. - * - * For non-GCM mode, the IV may be a binary-encoded string of bytes, an array - * of bytes, a byte buffer, or an array of 32-bit integers. If the IV is in - * bytes, then it must be Nb (16) bytes in length. If the IV is given in as - * 32-bit integers, then it must be 4 integers long. - * - * Note: an IV is not required or used in ECB mode. - * - * For GCM-mode, the IV must be given as a binary-encoded string of bytes or - * a byte buffer. The number of bytes should be 12 (96 bits) as recommended - * by NIST SP-800-38D but another length may be given. - * - * @param options the options to use: - * iv the initialization vector to use as a binary-encoded string of - * bytes, null to reuse the last ciphered block from a previous - * update() (this "residue" method is for legacy support only). - * additionalData additional authentication data as a binary-encoded - * string of bytes, for 'GCM' mode, (default: none). - * tagLength desired length of authentication tag, in bits, for - * 'GCM' mode (0-128, default: 128). - * tag the authentication tag to check if decrypting, as a - * binary-encoded string of bytes. - * output the output the buffer to write to, null to create one. - */ -BlockCipher.prototype.start = function(options) { - options = options || {}; - var opts = {}; - for(var key in options) { - opts[key] = options[key]; - } - opts.decrypt = this._decrypt; - this._finish = false; - this._input = forge$B.util.createBuffer(); - this.output = options.output || forge$B.util.createBuffer(); - this.mode.start(opts); -}; - -/** - * Updates the next block according to the cipher mode. - * - * @param input the buffer to read from. - */ -BlockCipher.prototype.update = function(input) { - if(input) { - // input given, so empty it into the input buffer - this._input.putBuffer(input); - } - - // do cipher operation until it needs more input and not finished - while(!this._op.call(this.mode, this._input, this.output, this._finish) && - !this._finish) {} - - // free consumed memory from input buffer - this._input.compact(); -}; - -/** - * Finishes encrypting or decrypting. - * - * @param pad a padding function to use in CBC mode, null for default, - * signature(blockSize, buffer, decrypt). - * - * @return true if successful, false on error. - */ -BlockCipher.prototype.finish = function(pad) { - // backwards-compatibility w/deprecated padding API - // Note: will overwrite padding functions even after another start() call - if(pad && (this.mode.name === 'ECB' || this.mode.name === 'CBC')) { - this.mode.pad = function(input) { - return pad(this.blockSize, input, false); - }; - this.mode.unpad = function(output) { - return pad(this.blockSize, output, true); - }; - } - - // build options for padding and afterFinish functions - var options = {}; - options.decrypt = this._decrypt; - - // get # of bytes that won't fill a block - options.overflow = this._input.length() % this.blockSize; - - if(!this._decrypt && this.mode.pad) { - if(!this.mode.pad(this._input, options)) { - return false; - } - } - - // do final update - this._finish = true; - this.update(); - - if(this._decrypt && this.mode.unpad) { - if(!this.mode.unpad(this.output, options)) { - return false; - } - } - - if(this.mode.afterFinish) { - if(!this.mode.afterFinish(this.output, options)) { - return false; - } - } - - return true; -}; - -/** - * Supported cipher modes. - * - * @author Dave Longley - * - * Copyright (c) 2010-2014 Digital Bazaar, Inc. - */ - -var forge$A = forge$D; - - -forge$A.cipher = forge$A.cipher || {}; - -// supported cipher modes -var modes = forge$A.cipher.modes = forge$A.cipher.modes || {}; - -/** Electronic codebook (ECB) (Don't use this; it's not secure) **/ - -modes.ecb = function(options) { - options = options || {}; - this.name = 'ECB'; - this.cipher = options.cipher; - this.blockSize = options.blockSize || 16; - this._ints = this.blockSize / 4; - this._inBlock = new Array(this._ints); - this._outBlock = new Array(this._ints); -}; - -modes.ecb.prototype.start = function(options) {}; - -modes.ecb.prototype.encrypt = function(input, output, finish) { - // not enough input to encrypt - if(input.length() < this.blockSize && !(finish && input.length() > 0)) { - return true; - } - - // get next block - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = input.getInt32(); - } - - // encrypt block - this.cipher.encrypt(this._inBlock, this._outBlock); - - // write output - for(var i = 0; i < this._ints; ++i) { - output.putInt32(this._outBlock[i]); - } -}; - -modes.ecb.prototype.decrypt = function(input, output, finish) { - // not enough input to decrypt - if(input.length() < this.blockSize && !(finish && input.length() > 0)) { - return true; - } - - // get next block - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = input.getInt32(); - } - - // decrypt block - this.cipher.decrypt(this._inBlock, this._outBlock); - - // write output - for(var i = 0; i < this._ints; ++i) { - output.putInt32(this._outBlock[i]); - } -}; - -modes.ecb.prototype.pad = function(input, options) { - // add PKCS#7 padding to block (each pad byte is the - // value of the number of pad bytes) - var padding = (input.length() === this.blockSize ? - this.blockSize : (this.blockSize - input.length())); - input.fillWithByte(padding, padding); - return true; -}; - -modes.ecb.prototype.unpad = function(output, options) { - // check for error: input data not a multiple of blockSize - if(options.overflow > 0) { - return false; - } - - // ensure padding byte count is valid - var len = output.length(); - var count = output.at(len - 1); - if(count > (this.blockSize << 2)) { - return false; - } - - // trim off padding bytes - output.truncate(count); - return true; -}; - -/** Cipher-block Chaining (CBC) **/ - -modes.cbc = function(options) { - options = options || {}; - this.name = 'CBC'; - this.cipher = options.cipher; - this.blockSize = options.blockSize || 16; - this._ints = this.blockSize / 4; - this._inBlock = new Array(this._ints); - this._outBlock = new Array(this._ints); -}; - -modes.cbc.prototype.start = function(options) { - // Note: legacy support for using IV residue (has security flaws) - // if IV is null, reuse block from previous processing - if(options.iv === null) { - // must have a previous block - if(!this._prev) { - throw new Error('Invalid IV parameter.'); - } - this._iv = this._prev.slice(0); - } else if(!('iv' in options)) { - throw new Error('Invalid IV parameter.'); - } else { - // save IV as "previous" block - this._iv = transformIV(options.iv, this.blockSize); - this._prev = this._iv.slice(0); - } -}; - -modes.cbc.prototype.encrypt = function(input, output, finish) { - // not enough input to encrypt - if(input.length() < this.blockSize && !(finish && input.length() > 0)) { - return true; - } - - // get next block - // CBC XOR's IV (or previous block) with plaintext - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = this._prev[i] ^ input.getInt32(); - } - - // encrypt block - this.cipher.encrypt(this._inBlock, this._outBlock); - - // write output, save previous block - for(var i = 0; i < this._ints; ++i) { - output.putInt32(this._outBlock[i]); - } - this._prev = this._outBlock; -}; - -modes.cbc.prototype.decrypt = function(input, output, finish) { - // not enough input to decrypt - if(input.length() < this.blockSize && !(finish && input.length() > 0)) { - return true; - } - - // get next block - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = input.getInt32(); - } - - // decrypt block - this.cipher.decrypt(this._inBlock, this._outBlock); - - // write output, save previous ciphered block - // CBC XOR's IV (or previous block) with ciphertext - for(var i = 0; i < this._ints; ++i) { - output.putInt32(this._prev[i] ^ this._outBlock[i]); - } - this._prev = this._inBlock.slice(0); -}; - -modes.cbc.prototype.pad = function(input, options) { - // add PKCS#7 padding to block (each pad byte is the - // value of the number of pad bytes) - var padding = (input.length() === this.blockSize ? - this.blockSize : (this.blockSize - input.length())); - input.fillWithByte(padding, padding); - return true; -}; - -modes.cbc.prototype.unpad = function(output, options) { - // check for error: input data not a multiple of blockSize - if(options.overflow > 0) { - return false; - } - - // ensure padding byte count is valid - var len = output.length(); - var count = output.at(len - 1); - if(count > (this.blockSize << 2)) { - return false; - } - - // trim off padding bytes - output.truncate(count); - return true; -}; - -/** Cipher feedback (CFB) **/ - -modes.cfb = function(options) { - options = options || {}; - this.name = 'CFB'; - this.cipher = options.cipher; - this.blockSize = options.blockSize || 16; - this._ints = this.blockSize / 4; - this._inBlock = null; - this._outBlock = new Array(this._ints); - this._partialBlock = new Array(this._ints); - this._partialOutput = forge$A.util.createBuffer(); - this._partialBytes = 0; -}; - -modes.cfb.prototype.start = function(options) { - if(!('iv' in options)) { - throw new Error('Invalid IV parameter.'); - } - // use IV as first input - this._iv = transformIV(options.iv, this.blockSize); - this._inBlock = this._iv.slice(0); - this._partialBytes = 0; -}; - -modes.cfb.prototype.encrypt = function(input, output, finish) { - // not enough input to encrypt - var inputLength = input.length(); - if(inputLength === 0) { - return true; - } - - // encrypt block - this.cipher.encrypt(this._inBlock, this._outBlock); - - // handle full block - if(this._partialBytes === 0 && inputLength >= this.blockSize) { - // XOR input with output, write input as output - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = input.getInt32() ^ this._outBlock[i]; - output.putInt32(this._inBlock[i]); - } - return; - } - - // handle partial block - var partialBytes = (this.blockSize - inputLength) % this.blockSize; - if(partialBytes > 0) { - partialBytes = this.blockSize - partialBytes; - } - - // XOR input with output, write input as partial output - this._partialOutput.clear(); - for(var i = 0; i < this._ints; ++i) { - this._partialBlock[i] = input.getInt32() ^ this._outBlock[i]; - this._partialOutput.putInt32(this._partialBlock[i]); - } - - if(partialBytes > 0) { - // block still incomplete, restore input buffer - input.read -= this.blockSize; - } else { - // block complete, update input block - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = this._partialBlock[i]; - } - } - - // skip any previous partial bytes - if(this._partialBytes > 0) { - this._partialOutput.getBytes(this._partialBytes); - } - - if(partialBytes > 0 && !finish) { - output.putBytes(this._partialOutput.getBytes( - partialBytes - this._partialBytes)); - this._partialBytes = partialBytes; - return true; - } - - output.putBytes(this._partialOutput.getBytes( - inputLength - this._partialBytes)); - this._partialBytes = 0; -}; - -modes.cfb.prototype.decrypt = function(input, output, finish) { - // not enough input to decrypt - var inputLength = input.length(); - if(inputLength === 0) { - return true; - } - - // encrypt block (CFB always uses encryption mode) - this.cipher.encrypt(this._inBlock, this._outBlock); - - // handle full block - if(this._partialBytes === 0 && inputLength >= this.blockSize) { - // XOR input with output, write input as output - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = input.getInt32(); - output.putInt32(this._inBlock[i] ^ this._outBlock[i]); - } - return; - } - - // handle partial block - var partialBytes = (this.blockSize - inputLength) % this.blockSize; - if(partialBytes > 0) { - partialBytes = this.blockSize - partialBytes; - } - - // XOR input with output, write input as partial output - this._partialOutput.clear(); - for(var i = 0; i < this._ints; ++i) { - this._partialBlock[i] = input.getInt32(); - this._partialOutput.putInt32(this._partialBlock[i] ^ this._outBlock[i]); - } - - if(partialBytes > 0) { - // block still incomplete, restore input buffer - input.read -= this.blockSize; - } else { - // block complete, update input block - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = this._partialBlock[i]; - } - } - - // skip any previous partial bytes - if(this._partialBytes > 0) { - this._partialOutput.getBytes(this._partialBytes); - } - - if(partialBytes > 0 && !finish) { - output.putBytes(this._partialOutput.getBytes( - partialBytes - this._partialBytes)); - this._partialBytes = partialBytes; - return true; - } - - output.putBytes(this._partialOutput.getBytes( - inputLength - this._partialBytes)); - this._partialBytes = 0; -}; - -/** Output feedback (OFB) **/ - -modes.ofb = function(options) { - options = options || {}; - this.name = 'OFB'; - this.cipher = options.cipher; - this.blockSize = options.blockSize || 16; - this._ints = this.blockSize / 4; - this._inBlock = null; - this._outBlock = new Array(this._ints); - this._partialOutput = forge$A.util.createBuffer(); - this._partialBytes = 0; -}; - -modes.ofb.prototype.start = function(options) { - if(!('iv' in options)) { - throw new Error('Invalid IV parameter.'); - } - // use IV as first input - this._iv = transformIV(options.iv, this.blockSize); - this._inBlock = this._iv.slice(0); - this._partialBytes = 0; -}; - -modes.ofb.prototype.encrypt = function(input, output, finish) { - // not enough input to encrypt - var inputLength = input.length(); - if(input.length() === 0) { - return true; - } - - // encrypt block (OFB always uses encryption mode) - this.cipher.encrypt(this._inBlock, this._outBlock); - - // handle full block - if(this._partialBytes === 0 && inputLength >= this.blockSize) { - // XOR input with output and update next input - for(var i = 0; i < this._ints; ++i) { - output.putInt32(input.getInt32() ^ this._outBlock[i]); - this._inBlock[i] = this._outBlock[i]; - } - return; - } - - // handle partial block - var partialBytes = (this.blockSize - inputLength) % this.blockSize; - if(partialBytes > 0) { - partialBytes = this.blockSize - partialBytes; - } - - // XOR input with output - this._partialOutput.clear(); - for(var i = 0; i < this._ints; ++i) { - this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); - } - - if(partialBytes > 0) { - // block still incomplete, restore input buffer - input.read -= this.blockSize; - } else { - // block complete, update input block - for(var i = 0; i < this._ints; ++i) { - this._inBlock[i] = this._outBlock[i]; - } - } - - // skip any previous partial bytes - if(this._partialBytes > 0) { - this._partialOutput.getBytes(this._partialBytes); - } - - if(partialBytes > 0 && !finish) { - output.putBytes(this._partialOutput.getBytes( - partialBytes - this._partialBytes)); - this._partialBytes = partialBytes; - return true; - } - - output.putBytes(this._partialOutput.getBytes( - inputLength - this._partialBytes)); - this._partialBytes = 0; -}; - -modes.ofb.prototype.decrypt = modes.ofb.prototype.encrypt; - -/** Counter (CTR) **/ - -modes.ctr = function(options) { - options = options || {}; - this.name = 'CTR'; - this.cipher = options.cipher; - this.blockSize = options.blockSize || 16; - this._ints = this.blockSize / 4; - this._inBlock = null; - this._outBlock = new Array(this._ints); - this._partialOutput = forge$A.util.createBuffer(); - this._partialBytes = 0; -}; - -modes.ctr.prototype.start = function(options) { - if(!('iv' in options)) { - throw new Error('Invalid IV parameter.'); - } - // use IV as first input - this._iv = transformIV(options.iv, this.blockSize); - this._inBlock = this._iv.slice(0); - this._partialBytes = 0; -}; - -modes.ctr.prototype.encrypt = function(input, output, finish) { - // not enough input to encrypt - var inputLength = input.length(); - if(inputLength === 0) { - return true; - } - - // encrypt block (CTR always uses encryption mode) - this.cipher.encrypt(this._inBlock, this._outBlock); - - // handle full block - if(this._partialBytes === 0 && inputLength >= this.blockSize) { - // XOR input with output - for(var i = 0; i < this._ints; ++i) { - output.putInt32(input.getInt32() ^ this._outBlock[i]); - } - } else { - // handle partial block - var partialBytes = (this.blockSize - inputLength) % this.blockSize; - if(partialBytes > 0) { - partialBytes = this.blockSize - partialBytes; - } - - // XOR input with output - this._partialOutput.clear(); - for(var i = 0; i < this._ints; ++i) { - this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); - } - - if(partialBytes > 0) { - // block still incomplete, restore input buffer - input.read -= this.blockSize; - } - - // skip any previous partial bytes - if(this._partialBytes > 0) { - this._partialOutput.getBytes(this._partialBytes); - } - - if(partialBytes > 0 && !finish) { - output.putBytes(this._partialOutput.getBytes( - partialBytes - this._partialBytes)); - this._partialBytes = partialBytes; - return true; - } - - output.putBytes(this._partialOutput.getBytes( - inputLength - this._partialBytes)); - this._partialBytes = 0; - } - - // block complete, increment counter (input block) - inc32(this._inBlock); -}; - -modes.ctr.prototype.decrypt = modes.ctr.prototype.encrypt; - -/** Galois/Counter Mode (GCM) **/ - -modes.gcm = function(options) { - options = options || {}; - this.name = 'GCM'; - this.cipher = options.cipher; - this.blockSize = options.blockSize || 16; - this._ints = this.blockSize / 4; - this._inBlock = new Array(this._ints); - this._outBlock = new Array(this._ints); - this._partialOutput = forge$A.util.createBuffer(); - this._partialBytes = 0; - - // R is actually this value concatenated with 120 more zero bits, but - // we only XOR against R so the other zeros have no effect -- we just - // apply this value to the first integer in a block - this._R = 0xE1000000; -}; - -modes.gcm.prototype.start = function(options) { - if(!('iv' in options)) { - throw new Error('Invalid IV parameter.'); - } - // ensure IV is a byte buffer - var iv = forge$A.util.createBuffer(options.iv); - - // no ciphered data processed yet - this._cipherLength = 0; - - // default additional data is none - var additionalData; - if('additionalData' in options) { - additionalData = forge$A.util.createBuffer(options.additionalData); - } else { - additionalData = forge$A.util.createBuffer(); - } - - // default tag length is 128 bits - if('tagLength' in options) { - this._tagLength = options.tagLength; - } else { - this._tagLength = 128; - } - - // if tag is given, ensure tag matches tag length - this._tag = null; - if(options.decrypt) { - // save tag to check later - this._tag = forge$A.util.createBuffer(options.tag).getBytes(); - if(this._tag.length !== (this._tagLength / 8)) { - throw new Error('Authentication tag does not match tag length.'); - } - } - - // create tmp storage for hash calculation - this._hashBlock = new Array(this._ints); - - // no tag generated yet - this.tag = null; - - // generate hash subkey - // (apply block cipher to "zero" block) - this._hashSubkey = new Array(this._ints); - this.cipher.encrypt([0, 0, 0, 0], this._hashSubkey); - - // generate table M - // use 4-bit tables (32 component decomposition of a 16 byte value) - // 8-bit tables take more space and are known to have security - // vulnerabilities (in native implementations) - this.componentBits = 4; - this._m = this.generateHashTable(this._hashSubkey, this.componentBits); - - // Note: support IV length different from 96 bits? (only supporting - // 96 bits is recommended by NIST SP-800-38D) - // generate J_0 - var ivLength = iv.length(); - if(ivLength === 12) { - // 96-bit IV - this._j0 = [iv.getInt32(), iv.getInt32(), iv.getInt32(), 1]; - } else { - // IV is NOT 96-bits - this._j0 = [0, 0, 0, 0]; - while(iv.length() > 0) { - this._j0 = this.ghash( - this._hashSubkey, this._j0, - [iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()]); - } - this._j0 = this.ghash( - this._hashSubkey, this._j0, [0, 0].concat(from64To32(ivLength * 8))); - } - - // generate ICB (initial counter block) - this._inBlock = this._j0.slice(0); - inc32(this._inBlock); - this._partialBytes = 0; - - // consume authentication data - additionalData = forge$A.util.createBuffer(additionalData); - // save additional data length as a BE 64-bit number - this._aDataLength = from64To32(additionalData.length() * 8); - // pad additional data to 128 bit (16 byte) block size - var overflow = additionalData.length() % this.blockSize; - if(overflow) { - additionalData.fillWithByte(0, this.blockSize - overflow); - } - this._s = [0, 0, 0, 0]; - while(additionalData.length() > 0) { - this._s = this.ghash(this._hashSubkey, this._s, [ - additionalData.getInt32(), - additionalData.getInt32(), - additionalData.getInt32(), - additionalData.getInt32() - ]); - } -}; - -modes.gcm.prototype.encrypt = function(input, output, finish) { - // not enough input to encrypt - var inputLength = input.length(); - if(inputLength === 0) { - return true; - } - - // encrypt block - this.cipher.encrypt(this._inBlock, this._outBlock); - - // handle full block - if(this._partialBytes === 0 && inputLength >= this.blockSize) { - // XOR input with output - for(var i = 0; i < this._ints; ++i) { - output.putInt32(this._outBlock[i] ^= input.getInt32()); - } - this._cipherLength += this.blockSize; - } else { - // handle partial block - var partialBytes = (this.blockSize - inputLength) % this.blockSize; - if(partialBytes > 0) { - partialBytes = this.blockSize - partialBytes; - } - - // XOR input with output - this._partialOutput.clear(); - for(var i = 0; i < this._ints; ++i) { - this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]); - } - - if(partialBytes <= 0 || finish) { - // handle overflow prior to hashing - if(finish) { - // get block overflow - var overflow = inputLength % this.blockSize; - this._cipherLength += overflow; - // truncate for hash function - this._partialOutput.truncate(this.blockSize - overflow); - } else { - this._cipherLength += this.blockSize; - } - - // get output block for hashing - for(var i = 0; i < this._ints; ++i) { - this._outBlock[i] = this._partialOutput.getInt32(); - } - this._partialOutput.read -= this.blockSize; - } - - // skip any previous partial bytes - if(this._partialBytes > 0) { - this._partialOutput.getBytes(this._partialBytes); - } - - if(partialBytes > 0 && !finish) { - // block still incomplete, restore input buffer, get partial output, - // and return early - input.read -= this.blockSize; - output.putBytes(this._partialOutput.getBytes( - partialBytes - this._partialBytes)); - this._partialBytes = partialBytes; - return true; - } - - output.putBytes(this._partialOutput.getBytes( - inputLength - this._partialBytes)); - this._partialBytes = 0; - } - - // update hash block S - this._s = this.ghash(this._hashSubkey, this._s, this._outBlock); - - // increment counter (input block) - inc32(this._inBlock); -}; - -modes.gcm.prototype.decrypt = function(input, output, finish) { - // not enough input to decrypt - var inputLength = input.length(); - if(inputLength < this.blockSize && !(finish && inputLength > 0)) { - return true; - } - - // encrypt block (GCM always uses encryption mode) - this.cipher.encrypt(this._inBlock, this._outBlock); - - // increment counter (input block) - inc32(this._inBlock); - - // update hash block S - this._hashBlock[0] = input.getInt32(); - this._hashBlock[1] = input.getInt32(); - this._hashBlock[2] = input.getInt32(); - this._hashBlock[3] = input.getInt32(); - this._s = this.ghash(this._hashSubkey, this._s, this._hashBlock); - - // XOR hash input with output - for(var i = 0; i < this._ints; ++i) { - output.putInt32(this._outBlock[i] ^ this._hashBlock[i]); - } - - // increment cipher data length - if(inputLength < this.blockSize) { - this._cipherLength += inputLength % this.blockSize; - } else { - this._cipherLength += this.blockSize; - } -}; - -modes.gcm.prototype.afterFinish = function(output, options) { - var rval = true; - - // handle overflow - if(options.decrypt && options.overflow) { - output.truncate(this.blockSize - options.overflow); - } - - // handle authentication tag - this.tag = forge$A.util.createBuffer(); - - // concatenate additional data length with cipher length - var lengths = this._aDataLength.concat(from64To32(this._cipherLength * 8)); - - // include lengths in hash - this._s = this.ghash(this._hashSubkey, this._s, lengths); - - // do GCTR(J_0, S) - var tag = []; - this.cipher.encrypt(this._j0, tag); - for(var i = 0; i < this._ints; ++i) { - this.tag.putInt32(this._s[i] ^ tag[i]); - } - - // trim tag to length - this.tag.truncate(this.tag.length() % (this._tagLength / 8)); - - // check authentication tag - if(options.decrypt && this.tag.bytes() !== this._tag) { - rval = false; - } - - return rval; -}; - -/** - * See NIST SP-800-38D 6.3 (Algorithm 1). This function performs Galois - * field multiplication. The field, GF(2^128), is defined by the polynomial: - * - * x^128 + x^7 + x^2 + x + 1 - * - * Which is represented in little-endian binary form as: 11100001 (0xe1). When - * the value of a coefficient is 1, a bit is set. The value R, is the - * concatenation of this value and 120 zero bits, yielding a 128-bit value - * which matches the block size. - * - * This function will multiply two elements (vectors of bytes), X and Y, in - * the field GF(2^128). The result is initialized to zero. For each bit of - * X (out of 128), x_i, if x_i is set, then the result is multiplied (XOR'd) - * by the current value of Y. For each bit, the value of Y will be raised by - * a power of x (multiplied by the polynomial x). This can be achieved by - * shifting Y once to the right. If the current value of Y, prior to being - * multiplied by x, has 0 as its LSB, then it is a 127th degree polynomial. - * Otherwise, we must divide by R after shifting to find the remainder. - * - * @param x the first block to multiply by the second. - * @param y the second block to multiply by the first. - * - * @return the block result of the multiplication. - */ -modes.gcm.prototype.multiply = function(x, y) { - var z_i = [0, 0, 0, 0]; - var v_i = y.slice(0); - - // calculate Z_128 (block has 128 bits) - for(var i = 0; i < 128; ++i) { - // if x_i is 0, Z_{i+1} = Z_i (unchanged) - // else Z_{i+1} = Z_i ^ V_i - // get x_i by finding 32-bit int position, then left shift 1 by remainder - var x_i = x[(i / 32) | 0] & (1 << (31 - i % 32)); - if(x_i) { - z_i[0] ^= v_i[0]; - z_i[1] ^= v_i[1]; - z_i[2] ^= v_i[2]; - z_i[3] ^= v_i[3]; - } - - // if LSB(V_i) is 1, V_i = V_i >> 1 - // else V_i = (V_i >> 1) ^ R - this.pow(v_i, v_i); - } - - return z_i; -}; - -modes.gcm.prototype.pow = function(x, out) { - // if LSB(x) is 1, x = x >>> 1 - // else x = (x >>> 1) ^ R - var lsb = x[3] & 1; - - // always do x >>> 1: - // starting with the rightmost integer, shift each integer to the right - // one bit, pulling in the bit from the integer to the left as its top - // most bit (do this for the last 3 integers) - for(var i = 3; i > 0; --i) { - out[i] = (x[i] >>> 1) | ((x[i - 1] & 1) << 31); - } - // shift the first integer normally - out[0] = x[0] >>> 1; - - // if lsb was not set, then polynomial had a degree of 127 and doesn't - // need to divided; otherwise, XOR with R to find the remainder; we only - // need to XOR the first integer since R technically ends w/120 zero bits - if(lsb) { - out[0] ^= this._R; - } -}; - -modes.gcm.prototype.tableMultiply = function(x) { - // assumes 4-bit tables are used - var z = [0, 0, 0, 0]; - for(var i = 0; i < 32; ++i) { - var idx = (i / 8) | 0; - var x_i = (x[idx] >>> ((7 - (i % 8)) * 4)) & 0xF; - var ah = this._m[i][x_i]; - z[0] ^= ah[0]; - z[1] ^= ah[1]; - z[2] ^= ah[2]; - z[3] ^= ah[3]; - } - return z; -}; - -/** - * A continuing version of the GHASH algorithm that operates on a single - * block. The hash block, last hash value (Ym) and the new block to hash - * are given. - * - * @param h the hash block. - * @param y the previous value for Ym, use [0, 0, 0, 0] for a new hash. - * @param x the block to hash. - * - * @return the hashed value (Ym). - */ -modes.gcm.prototype.ghash = function(h, y, x) { - y[0] ^= x[0]; - y[1] ^= x[1]; - y[2] ^= x[2]; - y[3] ^= x[3]; - return this.tableMultiply(y); - //return this.multiply(y, h); -}; - -/** - * Precomputes a table for multiplying against the hash subkey. This - * mechanism provides a substantial speed increase over multiplication - * performed without a table. The table-based multiplication this table is - * for solves X * H by multiplying each component of X by H and then - * composing the results together using XOR. - * - * This function can be used to generate tables with different bit sizes - * for the components, however, this implementation assumes there are - * 32 components of X (which is a 16 byte vector), therefore each component - * takes 4-bits (so the table is constructed with bits=4). - * - * @param h the hash subkey. - * @param bits the bit size for a component. - */ -modes.gcm.prototype.generateHashTable = function(h, bits) { - // TODO: There are further optimizations that would use only the - // first table M_0 (or some variant) along with a remainder table; - // this can be explored in the future - var multiplier = 8 / bits; - var perInt = 4 * multiplier; - var size = 16 * multiplier; - var m = new Array(size); - for(var i = 0; i < size; ++i) { - var tmp = [0, 0, 0, 0]; - var idx = (i / perInt) | 0; - var shft = ((perInt - 1 - (i % perInt)) * bits); - tmp[idx] = (1 << (bits - 1)) << shft; - m[i] = this.generateSubHashTable(this.multiply(tmp, h), bits); - } - return m; -}; - -/** - * Generates a table for multiplying against the hash subkey for one - * particular component (out of all possible component values). - * - * @param mid the pre-multiplied value for the middle key of the table. - * @param bits the bit size for a component. - */ -modes.gcm.prototype.generateSubHashTable = function(mid, bits) { - // compute the table quickly by minimizing the number of - // POW operations -- they only need to be performed for powers of 2, - // all other entries can be composed from those powers using XOR - var size = 1 << bits; - var half = size >>> 1; - var m = new Array(size); - m[half] = mid.slice(0); - var i = half >>> 1; - while(i > 0) { - // raise m0[2 * i] and store in m0[i] - this.pow(m[2 * i], m[i] = []); - i >>= 1; - } - i = 2; - while(i < half) { - for(var j = 1; j < i; ++j) { - var m_i = m[i]; - var m_j = m[j]; - m[i + j] = [ - m_i[0] ^ m_j[0], - m_i[1] ^ m_j[1], - m_i[2] ^ m_j[2], - m_i[3] ^ m_j[3] - ]; - } - i *= 2; - } - m[0] = [0, 0, 0, 0]; - /* Note: We could avoid storing these by doing composition during multiply - calculate top half using composition by speed is preferred. */ - for(i = half + 1; i < size; ++i) { - var c = m[i ^ half]; - m[i] = [mid[0] ^ c[0], mid[1] ^ c[1], mid[2] ^ c[2], mid[3] ^ c[3]]; - } - return m; -}; - -/** Utility functions */ - -function transformIV(iv, blockSize) { - if(typeof iv === 'string') { - // convert iv string into byte buffer - iv = forge$A.util.createBuffer(iv); - } - - if(forge$A.util.isArray(iv) && iv.length > 4) { - // convert iv byte array into byte buffer - var tmp = iv; - iv = forge$A.util.createBuffer(); - for(var i = 0; i < tmp.length; ++i) { - iv.putByte(tmp[i]); - } - } - - if(iv.length() < blockSize) { - throw new Error( - 'Invalid IV length; got ' + iv.length() + - ' bytes and expected ' + blockSize + ' bytes.'); - } - - if(!forge$A.util.isArray(iv)) { - // convert iv byte buffer into 32-bit integer array - var ints = []; - var blocks = blockSize / 4; - for(var i = 0; i < blocks; ++i) { - ints.push(iv.getInt32()); - } - iv = ints; - } - - return iv; -} - -function inc32(block) { - // increment last 32 bits of block only - block[block.length - 1] = (block[block.length - 1] + 1) & 0xFFFFFFFF; -} - -function from64To32(num) { - // convert 64-bit number to two BE Int32s - return [(num / 0x100000000) | 0, num & 0xFFFFFFFF]; -} - -/** - * Advanced Encryption Standard (AES) implementation. - * - * This implementation is based on the public domain library 'jscrypto' which - * was written by: - * - * Emily Stark (estark@stanford.edu) - * Mike Hamburg (mhamburg@stanford.edu) - * Dan Boneh (dabo@cs.stanford.edu) - * - * Parts of this code are based on the OpenSSL implementation of AES: - * http://www.openssl.org - * - * @author Dave Longley - * - * Copyright (c) 2010-2014 Digital Bazaar, Inc. - */ - -var forge$z = forge$D; - - - - -/* AES API */ -forge$z.aes = forge$z.aes || {}; - -/** - * Deprecated. Instead, use: - * - * var cipher = forge.cipher.createCipher('AES-', key); - * cipher.start({iv: iv}); - * - * Creates an AES cipher object to encrypt data using the given symmetric key. - * The output will be stored in the 'output' member of the returned cipher. - * - * The key and iv may be given as a string of bytes, an array of bytes, - * a byte buffer, or an array of 32-bit words. - * - * @param key the symmetric key to use. - * @param iv the initialization vector to use. - * @param output the buffer to write to, null to create one. - * @param mode the cipher mode to use (default: 'CBC'). - * - * @return the cipher. - */ -forge$z.aes.startEncrypting = function(key, iv, output, mode) { - var cipher = _createCipher$1({ - key: key, - output: output, - decrypt: false, - mode: mode - }); - cipher.start(iv); - return cipher; -}; - -/** - * Deprecated. Instead, use: - * - * var cipher = forge.cipher.createCipher('AES-', key); - * - * Creates an AES cipher object to encrypt data using the given symmetric key. - * - * The key may be given as a string of bytes, an array of bytes, a - * byte buffer, or an array of 32-bit words. - * - * @param key the symmetric key to use. - * @param mode the cipher mode to use (default: 'CBC'). - * - * @return the cipher. - */ -forge$z.aes.createEncryptionCipher = function(key, mode) { - return _createCipher$1({ - key: key, - output: null, - decrypt: false, - mode: mode - }); -}; - -/** - * Deprecated. Instead, use: - * - * var decipher = forge.cipher.createDecipher('AES-', key); - * decipher.start({iv: iv}); - * - * Creates an AES cipher object to decrypt data using the given symmetric key. - * The output will be stored in the 'output' member of the returned cipher. - * - * The key and iv may be given as a string of bytes, an array of bytes, - * a byte buffer, or an array of 32-bit words. - * - * @param key the symmetric key to use. - * @param iv the initialization vector to use. - * @param output the buffer to write to, null to create one. - * @param mode the cipher mode to use (default: 'CBC'). - * - * @return the cipher. - */ -forge$z.aes.startDecrypting = function(key, iv, output, mode) { - var cipher = _createCipher$1({ - key: key, - output: output, - decrypt: true, - mode: mode - }); - cipher.start(iv); - return cipher; -}; - -/** - * Deprecated. Instead, use: - * - * var decipher = forge.cipher.createDecipher('AES-', key); - * - * Creates an AES cipher object to decrypt data using the given symmetric key. - * - * The key may be given as a string of bytes, an array of bytes, a - * byte buffer, or an array of 32-bit words. - * - * @param key the symmetric key to use. - * @param mode the cipher mode to use (default: 'CBC'). - * - * @return the cipher. - */ -forge$z.aes.createDecryptionCipher = function(key, mode) { - return _createCipher$1({ - key: key, - output: null, - decrypt: true, - mode: mode - }); -}; - -/** - * Creates a new AES cipher algorithm object. - * - * @param name the name of the algorithm. - * @param mode the mode factory function. - * - * @return the AES algorithm object. - */ -forge$z.aes.Algorithm = function(name, mode) { - if(!init) { - initialize(); - } - var self = this; - self.name = name; - self.mode = new mode({ - blockSize: 16, - cipher: { - encrypt: function(inBlock, outBlock) { - return _updateBlock$1(self._w, inBlock, outBlock, false); - }, - decrypt: function(inBlock, outBlock) { - return _updateBlock$1(self._w, inBlock, outBlock, true); - } - } - }); - self._init = false; -}; - -/** - * Initializes this AES algorithm by expanding its key. - * - * @param options the options to use. - * key the key to use with this algorithm. - * decrypt true if the algorithm should be initialized for decryption, - * false for encryption. - */ -forge$z.aes.Algorithm.prototype.initialize = function(options) { - if(this._init) { - return; - } - - var key = options.key; - var tmp; - - /* Note: The key may be a string of bytes, an array of bytes, a byte - buffer, or an array of 32-bit integers. If the key is in bytes, then - it must be 16, 24, or 32 bytes in length. If it is in 32-bit - integers, it must be 4, 6, or 8 integers long. */ - - if(typeof key === 'string' && - (key.length === 16 || key.length === 24 || key.length === 32)) { - // convert key string into byte buffer - key = forge$z.util.createBuffer(key); - } else if(forge$z.util.isArray(key) && - (key.length === 16 || key.length === 24 || key.length === 32)) { - // convert key integer array into byte buffer - tmp = key; - key = forge$z.util.createBuffer(); - for(var i = 0; i < tmp.length; ++i) { - key.putByte(tmp[i]); - } - } - - // convert key byte buffer into 32-bit integer array - if(!forge$z.util.isArray(key)) { - tmp = key; - key = []; - - // key lengths of 16, 24, 32 bytes allowed - var len = tmp.length(); - if(len === 16 || len === 24 || len === 32) { - len = len >>> 2; - for(var i = 0; i < len; ++i) { - key.push(tmp.getInt32()); - } - } - } - - // key must be an array of 32-bit integers by now - if(!forge$z.util.isArray(key) || - !(key.length === 4 || key.length === 6 || key.length === 8)) { - throw new Error('Invalid key parameter.'); - } - - // encryption operation is always used for these modes - var mode = this.mode.name; - var encryptOp = (['CFB', 'OFB', 'CTR', 'GCM'].indexOf(mode) !== -1); - - // do key expansion - this._w = _expandKey(key, options.decrypt && !encryptOp); - this._init = true; -}; - -/** - * Expands a key. Typically only used for testing. - * - * @param key the symmetric key to expand, as an array of 32-bit words. - * @param decrypt true to expand for decryption, false for encryption. - * - * @return the expanded key. - */ -forge$z.aes._expandKey = function(key, decrypt) { - if(!init) { - initialize(); - } - return _expandKey(key, decrypt); -}; - -/** - * Updates a single block. Typically only used for testing. - * - * @param w the expanded key to use. - * @param input an array of block-size 32-bit words. - * @param output an array of block-size 32-bit words. - * @param decrypt true to decrypt, false to encrypt. - */ -forge$z.aes._updateBlock = _updateBlock$1; - -/** Register AES algorithms **/ - -registerAlgorithm$1('AES-ECB', forge$z.cipher.modes.ecb); -registerAlgorithm$1('AES-CBC', forge$z.cipher.modes.cbc); -registerAlgorithm$1('AES-CFB', forge$z.cipher.modes.cfb); -registerAlgorithm$1('AES-OFB', forge$z.cipher.modes.ofb); -registerAlgorithm$1('AES-CTR', forge$z.cipher.modes.ctr); -registerAlgorithm$1('AES-GCM', forge$z.cipher.modes.gcm); - -function registerAlgorithm$1(name, mode) { - var factory = function() { - return new forge$z.aes.Algorithm(name, mode); - }; - forge$z.cipher.registerAlgorithm(name, factory); -} - -/** AES implementation **/ - -var init = false; // not yet initialized -var Nb = 4; // number of words comprising the state (AES = 4) -var sbox; // non-linear substitution table used in key expansion -var isbox; // inversion of sbox -var rcon; // round constant word array -var mix; // mix-columns table -var imix; // inverse mix-columns table - -/** - * Performs initialization, ie: precomputes tables to optimize for speed. - * - * One way to understand how AES works is to imagine that 'addition' and - * 'multiplication' are interfaces that require certain mathematical - * properties to hold true (ie: they are associative) but they might have - * different implementations and produce different kinds of results ... - * provided that their mathematical properties remain true. AES defines - * its own methods of addition and multiplication but keeps some important - * properties the same, ie: associativity and distributivity. The - * explanation below tries to shed some light on how AES defines addition - * and multiplication of bytes and 32-bit words in order to perform its - * encryption and decryption algorithms. - * - * The basics: - * - * The AES algorithm views bytes as binary representations of polynomials - * that have either 1 or 0 as the coefficients. It defines the addition - * or subtraction of two bytes as the XOR operation. It also defines the - * multiplication of two bytes as a finite field referred to as GF(2^8) - * (Note: 'GF' means "Galois Field" which is a field that contains a finite - * number of elements so GF(2^8) has 256 elements). - * - * This means that any two bytes can be represented as binary polynomials; - * when they multiplied together and modularly reduced by an irreducible - * polynomial of the 8th degree, the results are the field GF(2^8). The - * specific irreducible polynomial that AES uses in hexadecimal is 0x11b. - * This multiplication is associative with 0x01 as the identity: - * - * (b * 0x01 = GF(b, 0x01) = b). - * - * The operation GF(b, 0x02) can be performed at the byte level by left - * shifting b once and then XOR'ing it (to perform the modular reduction) - * with 0x11b if b is >= 128. Repeated application of the multiplication - * of 0x02 can be used to implement the multiplication of any two bytes. - * - * For instance, multiplying 0x57 and 0x13, denoted as GF(0x57, 0x13), can - * be performed by factoring 0x13 into 0x01, 0x02, and 0x10. Then these - * factors can each be multiplied by 0x57 and then added together. To do - * the multiplication, values for 0x57 multiplied by each of these 3 factors - * can be precomputed and stored in a table. To add them, the values from - * the table are XOR'd together. - * - * AES also defines addition and multiplication of words, that is 4-byte - * numbers represented as polynomials of 3 degrees where the coefficients - * are the values of the bytes. - * - * The word [a0, a1, a2, a3] is a polynomial a3x^3 + a2x^2 + a1x + a0. - * - * Addition is performed by XOR'ing like powers of x. Multiplication - * is performed in two steps, the first is an algebriac expansion as - * you would do normally (where addition is XOR). But the result is - * a polynomial larger than 3 degrees and thus it cannot fit in a word. So - * next the result is modularly reduced by an AES-specific polynomial of - * degree 4 which will always produce a polynomial of less than 4 degrees - * such that it will fit in a word. In AES, this polynomial is x^4 + 1. - * - * The modular product of two polynomials 'a' and 'b' is thus: - * - * d(x) = d3x^3 + d2x^2 + d1x + d0 - * with - * d0 = GF(a0, b0) ^ GF(a3, b1) ^ GF(a2, b2) ^ GF(a1, b3) - * d1 = GF(a1, b0) ^ GF(a0, b1) ^ GF(a3, b2) ^ GF(a2, b3) - * d2 = GF(a2, b0) ^ GF(a1, b1) ^ GF(a0, b2) ^ GF(a3, b3) - * d3 = GF(a3, b0) ^ GF(a2, b1) ^ GF(a1, b2) ^ GF(a0, b3) - * - * As a matrix: - * - * [d0] = [a0 a3 a2 a1][b0] - * [d1] [a1 a0 a3 a2][b1] - * [d2] [a2 a1 a0 a3][b2] - * [d3] [a3 a2 a1 a0][b3] - * - * Special polynomials defined by AES (0x02 == {02}): - * a(x) = {03}x^3 + {01}x^2 + {01}x + {02} - * a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. - * - * These polynomials are used in the MixColumns() and InverseMixColumns() - * operations, respectively, to cause each element in the state to affect - * the output (referred to as diffusing). - * - * RotWord() uses: a0 = a1 = a2 = {00} and a3 = {01}, which is the - * polynomial x3. - * - * The ShiftRows() method modifies the last 3 rows in the state (where - * the state is 4 words with 4 bytes per word) by shifting bytes cyclically. - * The 1st byte in the second row is moved to the end of the row. The 1st - * and 2nd bytes in the third row are moved to the end of the row. The 1st, - * 2nd, and 3rd bytes are moved in the fourth row. - * - * More details on how AES arithmetic works: - * - * In the polynomial representation of binary numbers, XOR performs addition - * and subtraction and multiplication in GF(2^8) denoted as GF(a, b) - * corresponds with the multiplication of polynomials modulo an irreducible - * polynomial of degree 8. In other words, for AES, GF(a, b) will multiply - * polynomial 'a' with polynomial 'b' and then do a modular reduction by - * an AES-specific irreducible polynomial of degree 8. - * - * A polynomial is irreducible if its only divisors are one and itself. For - * the AES algorithm, this irreducible polynomial is: - * - * m(x) = x^8 + x^4 + x^3 + x + 1, - * - * or {01}{1b} in hexadecimal notation, where each coefficient is a bit: - * 100011011 = 283 = 0x11b. - * - * For example, GF(0x57, 0x83) = 0xc1 because - * - * 0x57 = 87 = 01010111 = x^6 + x^4 + x^2 + x + 1 - * 0x85 = 131 = 10000101 = x^7 + x + 1 - * - * (x^6 + x^4 + x^2 + x + 1) * (x^7 + x + 1) - * = x^13 + x^11 + x^9 + x^8 + x^7 + - * x^7 + x^5 + x^3 + x^2 + x + - * x^6 + x^4 + x^2 + x + 1 - * = x^13 + x^11 + x^9 + x^8 + x^6 + x^5 + x^4 + x^3 + 1 = y - * y modulo (x^8 + x^4 + x^3 + x + 1) - * = x^7 + x^6 + 1. - * - * The modular reduction by m(x) guarantees the result will be a binary - * polynomial of less than degree 8, so that it can fit in a byte. - * - * The operation to multiply a binary polynomial b with x (the polynomial - * x in binary representation is 00000010) is: - * - * b_7x^8 + b_6x^7 + b_5x^6 + b_4x^5 + b_3x^4 + b_2x^3 + b_1x^2 + b_0x^1 - * - * To get GF(b, x) we must reduce that by m(x). If b_7 is 0 (that is the - * most significant bit is 0 in b) then the result is already reduced. If - * it is 1, then we can reduce it by subtracting m(x) via an XOR. - * - * It follows that multiplication by x (00000010 or 0x02) can be implemented - * by performing a left shift followed by a conditional bitwise XOR with - * 0x1b. This operation on bytes is denoted by xtime(). Multiplication by - * higher powers of x can be implemented by repeated application of xtime(). - * - * By adding intermediate results, multiplication by any constant can be - * implemented. For instance: - * - * GF(0x57, 0x13) = 0xfe because: - * - * xtime(b) = (b & 128) ? (b << 1 ^ 0x11b) : (b << 1) - * - * Note: We XOR with 0x11b instead of 0x1b because in javascript our - * datatype for b can be larger than 1 byte, so a left shift will not - * automatically eliminate bits that overflow a byte ... by XOR'ing the - * overflow bit with 1 (the extra one from 0x11b) we zero it out. - * - * GF(0x57, 0x02) = xtime(0x57) = 0xae - * GF(0x57, 0x04) = xtime(0xae) = 0x47 - * GF(0x57, 0x08) = xtime(0x47) = 0x8e - * GF(0x57, 0x10) = xtime(0x8e) = 0x07 - * - * GF(0x57, 0x13) = GF(0x57, (0x01 ^ 0x02 ^ 0x10)) - * - * And by the distributive property (since XOR is addition and GF() is - * multiplication): - * - * = GF(0x57, 0x01) ^ GF(0x57, 0x02) ^ GF(0x57, 0x10) - * = 0x57 ^ 0xae ^ 0x07 - * = 0xfe. - */ -function initialize() { - init = true; - - /* Populate the Rcon table. These are the values given by - [x^(i-1),{00},{00},{00}] where x^(i-1) are powers of x (and x = 0x02) - in the field of GF(2^8), where i starts at 1. - - rcon[0] = [0x00, 0x00, 0x00, 0x00] - rcon[1] = [0x01, 0x00, 0x00, 0x00] 2^(1-1) = 2^0 = 1 - rcon[2] = [0x02, 0x00, 0x00, 0x00] 2^(2-1) = 2^1 = 2 - ... - rcon[9] = [0x1B, 0x00, 0x00, 0x00] 2^(9-1) = 2^8 = 0x1B - rcon[10] = [0x36, 0x00, 0x00, 0x00] 2^(10-1) = 2^9 = 0x36 - - We only store the first byte because it is the only one used. - */ - rcon = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]; - - // compute xtime table which maps i onto GF(i, 0x02) - var xtime = new Array(256); - for(var i = 0; i < 128; ++i) { - xtime[i] = i << 1; - xtime[i + 128] = (i + 128) << 1 ^ 0x11B; - } - - // compute all other tables - sbox = new Array(256); - isbox = new Array(256); - mix = new Array(4); - imix = new Array(4); - for(var i = 0; i < 4; ++i) { - mix[i] = new Array(256); - imix[i] = new Array(256); - } - var e = 0, ei = 0, e2, e4, e8, sx, sx2, me, ime; - for(var i = 0; i < 256; ++i) { - /* We need to generate the SubBytes() sbox and isbox tables so that - we can perform byte substitutions. This requires us to traverse - all of the elements in GF, find their multiplicative inverses, - and apply to each the following affine transformation: - - bi' = bi ^ b(i + 4) mod 8 ^ b(i + 5) mod 8 ^ b(i + 6) mod 8 ^ - b(i + 7) mod 8 ^ ci - for 0 <= i < 8, where bi is the ith bit of the byte, and ci is the - ith bit of a byte c with the value {63} or {01100011}. - - It is possible to traverse every possible value in a Galois field - using what is referred to as a 'generator'. There are many - generators (128 out of 256): 3,5,6,9,11,82 to name a few. To fully - traverse GF we iterate 255 times, multiplying by our generator - each time. - - On each iteration we can determine the multiplicative inverse for - the current element. - - Suppose there is an element in GF 'e'. For a given generator 'g', - e = g^x. The multiplicative inverse of e is g^(255 - x). It turns - out that if use the inverse of a generator as another generator - it will produce all of the corresponding multiplicative inverses - at the same time. For this reason, we choose 5 as our inverse - generator because it only requires 2 multiplies and 1 add and its - inverse, 82, requires relatively few operations as well. - - In order to apply the affine transformation, the multiplicative - inverse 'ei' of 'e' can be repeatedly XOR'd (4 times) with a - bit-cycling of 'ei'. To do this 'ei' is first stored in 's' and - 'x'. Then 's' is left shifted and the high bit of 's' is made the - low bit. The resulting value is stored in 's'. Then 'x' is XOR'd - with 's' and stored in 'x'. On each subsequent iteration the same - operation is performed. When 4 iterations are complete, 'x' is - XOR'd with 'c' (0x63) and the transformed value is stored in 'x'. - For example: - - s = 01000001 - x = 01000001 - - iteration 1: s = 10000010, x ^= s - iteration 2: s = 00000101, x ^= s - iteration 3: s = 00001010, x ^= s - iteration 4: s = 00010100, x ^= s - x ^= 0x63 - - This can be done with a loop where s = (s << 1) | (s >> 7). However, - it can also be done by using a single 16-bit (in this case 32-bit) - number 'sx'. Since XOR is an associative operation, we can set 'sx' - to 'ei' and then XOR it with 'sx' left-shifted 1,2,3, and 4 times. - The most significant bits will flow into the high 8 bit positions - and be correctly XOR'd with one another. All that remains will be - to cycle the high 8 bits by XOR'ing them all with the lower 8 bits - afterwards. - - At the same time we're populating sbox and isbox we can precompute - the multiplication we'll need to do to do MixColumns() later. - */ - - // apply affine transformation - sx = ei ^ (ei << 1) ^ (ei << 2) ^ (ei << 3) ^ (ei << 4); - sx = (sx >> 8) ^ (sx & 255) ^ 0x63; - - // update tables - sbox[e] = sx; - isbox[sx] = e; - - /* Mixing columns is done using matrix multiplication. The columns - that are to be mixed are each a single word in the current state. - The state has Nb columns (4 columns). Therefore each column is a - 4 byte word. So to mix the columns in a single column 'c' where - its rows are r0, r1, r2, and r3, we use the following matrix - multiplication: - - [2 3 1 1]*[r0,c]=[r'0,c] - [1 2 3 1] [r1,c] [r'1,c] - [1 1 2 3] [r2,c] [r'2,c] - [3 1 1 2] [r3,c] [r'3,c] - - r0, r1, r2, and r3 are each 1 byte of one of the words in the - state (a column). To do matrix multiplication for each mixed - column c' we multiply the corresponding row from the left matrix - with the corresponding column from the right matrix. In total, we - get 4 equations: - - r0,c' = 2*r0,c + 3*r1,c + 1*r2,c + 1*r3,c - r1,c' = 1*r0,c + 2*r1,c + 3*r2,c + 1*r3,c - r2,c' = 1*r0,c + 1*r1,c + 2*r2,c + 3*r3,c - r3,c' = 3*r0,c + 1*r1,c + 1*r2,c + 2*r3,c - - As usual, the multiplication is as previously defined and the - addition is XOR. In order to optimize mixing columns we can store - the multiplication results in tables. If you think of the whole - column as a word (it might help to visualize by mentally rotating - the equations above by counterclockwise 90 degrees) then you can - see that it would be useful to map the multiplications performed on - each byte (r0, r1, r2, r3) onto a word as well. For instance, we - could map 2*r0,1*r0,1*r0,3*r0 onto a word by storing 2*r0 in the - highest 8 bits and 3*r0 in the lowest 8 bits (with the other two - respectively in the middle). This means that a table can be - constructed that uses r0 as an index to the word. We can do the - same with r1, r2, and r3, creating a total of 4 tables. - - To construct a full c', we can just look up each byte of c in - their respective tables and XOR the results together. - - Also, to build each table we only have to calculate the word - for 2,1,1,3 for every byte ... which we can do on each iteration - of this loop since we will iterate over every byte. After we have - calculated 2,1,1,3 we can get the results for the other tables - by cycling the byte at the end to the beginning. For instance - we can take the result of table 2,1,1,3 and produce table 3,2,1,1 - by moving the right most byte to the left most position just like - how you can imagine the 3 moved out of 2,1,1,3 and to the front - to produce 3,2,1,1. - - There is another optimization in that the same multiples of - the current element we need in order to advance our generator - to the next iteration can be reused in performing the 2,1,1,3 - calculation. We also calculate the inverse mix column tables, - with e,9,d,b being the inverse of 2,1,1,3. - - When we're done, and we need to actually mix columns, the first - byte of each state word should be put through mix[0] (2,1,1,3), - the second through mix[1] (3,2,1,1) and so forth. Then they should - be XOR'd together to produce the fully mixed column. - */ - - // calculate mix and imix table values - sx2 = xtime[sx]; - e2 = xtime[e]; - e4 = xtime[e2]; - e8 = xtime[e4]; - me = - (sx2 << 24) ^ // 2 - (sx << 16) ^ // 1 - (sx << 8) ^ // 1 - (sx ^ sx2); // 3 - ime = - (e2 ^ e4 ^ e8) << 24 ^ // E (14) - (e ^ e8) << 16 ^ // 9 - (e ^ e4 ^ e8) << 8 ^ // D (13) - (e ^ e2 ^ e8); // B (11) - // produce each of the mix tables by rotating the 2,1,1,3 value - for(var n = 0; n < 4; ++n) { - mix[n][e] = me; - imix[n][sx] = ime; - // cycle the right most byte to the left most position - // ie: 2,1,1,3 becomes 3,2,1,1 - me = me << 24 | me >>> 8; - ime = ime << 24 | ime >>> 8; - } - - // get next element and inverse - if(e === 0) { - // 1 is the inverse of 1 - e = ei = 1; - } else { - // e = 2e + 2*2*2*(10e)) = multiply e by 82 (chosen generator) - // ei = ei + 2*2*ei = multiply ei by 5 (inverse generator) - e = e2 ^ xtime[xtime[xtime[e2 ^ e8]]]; - ei ^= xtime[xtime[ei]]; - } - } -} - -/** - * Generates a key schedule using the AES key expansion algorithm. - * - * The AES algorithm takes the Cipher Key, K, and performs a Key Expansion - * routine to generate a key schedule. The Key Expansion generates a total - * of Nb*(Nr + 1) words: the algorithm requires an initial set of Nb words, - * and each of the Nr rounds requires Nb words of key data. The resulting - * key schedule consists of a linear array of 4-byte words, denoted [wi ], - * with i in the range 0 <= i < Nb(Nr + 1). - * - * KeyExpansion(byte key[4*Nk], word w[Nb*(Nr+1)], Nk) - * AES-128 (Nb=4, Nk=4, Nr=10) - * AES-192 (Nb=4, Nk=6, Nr=12) - * AES-256 (Nb=4, Nk=8, Nr=14) - * Note: Nr=Nk+6. - * - * Nb is the number of columns (32-bit words) comprising the State (or - * number of bytes in a block). For AES, Nb=4. - * - * @param key the key to schedule (as an array of 32-bit words). - * @param decrypt true to modify the key schedule to decrypt, false not to. - * - * @return the generated key schedule. - */ -function _expandKey(key, decrypt) { - // copy the key's words to initialize the key schedule - var w = key.slice(0); - - /* RotWord() will rotate a word, moving the first byte to the last - byte's position (shifting the other bytes left). - - We will be getting the value of Rcon at i / Nk. 'i' will iterate - from Nk to (Nb * Nr+1). Nk = 4 (4 byte key), Nb = 4 (4 words in - a block), Nr = Nk + 6 (10). Therefore 'i' will iterate from - 4 to 44 (exclusive). Each time we iterate 4 times, i / Nk will - increase by 1. We use a counter iNk to keep track of this. - */ - - // go through the rounds expanding the key - var temp, iNk = 1; - var Nk = w.length; - var Nr1 = Nk + 6 + 1; - var end = Nb * Nr1; - for(var i = Nk; i < end; ++i) { - temp = w[i - 1]; - if(i % Nk === 0) { - // temp = SubWord(RotWord(temp)) ^ Rcon[i / Nk] - temp = - sbox[temp >>> 16 & 255] << 24 ^ - sbox[temp >>> 8 & 255] << 16 ^ - sbox[temp & 255] << 8 ^ - sbox[temp >>> 24] ^ (rcon[iNk] << 24); - iNk++; - } else if(Nk > 6 && (i % Nk === 4)) { - // temp = SubWord(temp) - temp = - sbox[temp >>> 24] << 24 ^ - sbox[temp >>> 16 & 255] << 16 ^ - sbox[temp >>> 8 & 255] << 8 ^ - sbox[temp & 255]; - } - w[i] = w[i - Nk] ^ temp; - } - - /* When we are updating a cipher block we always use the code path for - encryption whether we are decrypting or not (to shorten code and - simplify the generation of look up tables). However, because there - are differences in the decryption algorithm, other than just swapping - in different look up tables, we must transform our key schedule to - account for these changes: - - 1. The decryption algorithm gets its key rounds in reverse order. - 2. The decryption algorithm adds the round key before mixing columns - instead of afterwards. - - We don't need to modify our key schedule to handle the first case, - we can just traverse the key schedule in reverse order when decrypting. - - The second case requires a little work. - - The tables we built for performing rounds will take an input and then - perform SubBytes() and MixColumns() or, for the decrypt version, - InvSubBytes() and InvMixColumns(). But the decrypt algorithm requires - us to AddRoundKey() before InvMixColumns(). This means we'll need to - apply some transformations to the round key to inverse-mix its columns - so they'll be correct for moving AddRoundKey() to after the state has - had its columns inverse-mixed. - - To inverse-mix the columns of the state when we're decrypting we use a - lookup table that will apply InvSubBytes() and InvMixColumns() at the - same time. However, the round key's bytes are not inverse-substituted - in the decryption algorithm. To get around this problem, we can first - substitute the bytes in the round key so that when we apply the - transformation via the InvSubBytes()+InvMixColumns() table, it will - undo our substitution leaving us with the original value that we - want -- and then inverse-mix that value. - - This change will correctly alter our key schedule so that we can XOR - each round key with our already transformed decryption state. This - allows us to use the same code path as the encryption algorithm. - - We make one more change to the decryption key. Since the decryption - algorithm runs in reverse from the encryption algorithm, we reverse - the order of the round keys to avoid having to iterate over the key - schedule backwards when running the encryption algorithm later in - decryption mode. In addition to reversing the order of the round keys, - we also swap each round key's 2nd and 4th rows. See the comments - section where rounds are performed for more details about why this is - done. These changes are done inline with the other substitution - described above. - */ - if(decrypt) { - var tmp; - var m0 = imix[0]; - var m1 = imix[1]; - var m2 = imix[2]; - var m3 = imix[3]; - var wnew = w.slice(0); - end = w.length; - for(var i = 0, wi = end - Nb; i < end; i += Nb, wi -= Nb) { - // do not sub the first or last round key (round keys are Nb - // words) as no column mixing is performed before they are added, - // but do change the key order - if(i === 0 || i === (end - Nb)) { - wnew[i] = w[wi]; - wnew[i + 1] = w[wi + 3]; - wnew[i + 2] = w[wi + 2]; - wnew[i + 3] = w[wi + 1]; - } else { - // substitute each round key byte because the inverse-mix - // table will inverse-substitute it (effectively cancel the - // substitution because round key bytes aren't sub'd in - // decryption mode) and swap indexes 3 and 1 - for(var n = 0; n < Nb; ++n) { - tmp = w[wi + n]; - wnew[i + (3&-n)] = - m0[sbox[tmp >>> 24]] ^ - m1[sbox[tmp >>> 16 & 255]] ^ - m2[sbox[tmp >>> 8 & 255]] ^ - m3[sbox[tmp & 255]]; - } - } - } - w = wnew; - } - - return w; -} - -/** - * Updates a single block (16 bytes) using AES. The update will either - * encrypt or decrypt the block. - * - * @param w the key schedule. - * @param input the input block (an array of 32-bit words). - * @param output the updated output block. - * @param decrypt true to decrypt the block, false to encrypt it. - */ -function _updateBlock$1(w, input, output, decrypt) { - /* - Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) - begin - byte state[4,Nb] - state = in - AddRoundKey(state, w[0, Nb-1]) - for round = 1 step 1 to Nr-1 - SubBytes(state) - ShiftRows(state) - MixColumns(state) - AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) - end for - SubBytes(state) - ShiftRows(state) - AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - out = state - end - - InvCipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) - begin - byte state[4,Nb] - state = in - AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - for round = Nr-1 step -1 downto 1 - InvShiftRows(state) - InvSubBytes(state) - AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) - InvMixColumns(state) - end for - InvShiftRows(state) - InvSubBytes(state) - AddRoundKey(state, w[0, Nb-1]) - out = state - end - */ - - // Encrypt: AddRoundKey(state, w[0, Nb-1]) - // Decrypt: AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - var Nr = w.length / 4 - 1; - var m0, m1, m2, m3, sub; - if(decrypt) { - m0 = imix[0]; - m1 = imix[1]; - m2 = imix[2]; - m3 = imix[3]; - sub = isbox; - } else { - m0 = mix[0]; - m1 = mix[1]; - m2 = mix[2]; - m3 = mix[3]; - sub = sbox; - } - var a, b, c, d, a2, b2, c2; - a = input[0] ^ w[0]; - b = input[decrypt ? 3 : 1] ^ w[1]; - c = input[2] ^ w[2]; - d = input[decrypt ? 1 : 3] ^ w[3]; - var i = 3; - - /* In order to share code we follow the encryption algorithm when both - encrypting and decrypting. To account for the changes required in the - decryption algorithm, we use different lookup tables when decrypting - and use a modified key schedule to account for the difference in the - order of transformations applied when performing rounds. We also get - key rounds in reverse order (relative to encryption). */ - for(var round = 1; round < Nr; ++round) { - /* As described above, we'll be using table lookups to perform the - column mixing. Each column is stored as a word in the state (the - array 'input' has one column as a word at each index). In order to - mix a column, we perform these transformations on each row in c, - which is 1 byte in each word. The new column for c0 is c'0: - - m0 m1 m2 m3 - r0,c'0 = 2*r0,c0 + 3*r1,c0 + 1*r2,c0 + 1*r3,c0 - r1,c'0 = 1*r0,c0 + 2*r1,c0 + 3*r2,c0 + 1*r3,c0 - r2,c'0 = 1*r0,c0 + 1*r1,c0 + 2*r2,c0 + 3*r3,c0 - r3,c'0 = 3*r0,c0 + 1*r1,c0 + 1*r2,c0 + 2*r3,c0 - - So using mix tables where c0 is a word with r0 being its upper - 8 bits and r3 being its lower 8 bits: - - m0[c0 >> 24] will yield this word: [2*r0,1*r0,1*r0,3*r0] - ... - m3[c0 & 255] will yield this word: [1*r3,1*r3,3*r3,2*r3] - - Therefore to mix the columns in each word in the state we - do the following (& 255 omitted for brevity): - c'0,r0 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] - c'0,r1 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] - c'0,r2 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] - c'0,r3 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3] - - However, before mixing, the algorithm requires us to perform - ShiftRows(). The ShiftRows() transformation cyclically shifts the - last 3 rows of the state over different offsets. The first row - (r = 0) is not shifted. - - s'_r,c = s_r,(c + shift(r, Nb) mod Nb - for 0 < r < 4 and 0 <= c < Nb and - shift(1, 4) = 1 - shift(2, 4) = 2 - shift(3, 4) = 3. - - This causes the first byte in r = 1 to be moved to the end of - the row, the first 2 bytes in r = 2 to be moved to the end of - the row, the first 3 bytes in r = 3 to be moved to the end of - the row: - - r1: [c0 c1 c2 c3] => [c1 c2 c3 c0] - r2: [c0 c1 c2 c3] [c2 c3 c0 c1] - r3: [c0 c1 c2 c3] [c3 c0 c1 c2] - - We can make these substitutions inline with our column mixing to - generate an updated set of equations to produce each word in the - state (note the columns have changed positions): - - c0 c1 c2 c3 => c0 c1 c2 c3 - c0 c1 c2 c3 c1 c2 c3 c0 (cycled 1 byte) - c0 c1 c2 c3 c2 c3 c0 c1 (cycled 2 bytes) - c0 c1 c2 c3 c3 c0 c1 c2 (cycled 3 bytes) - - Therefore: - - c'0 = 2*r0,c0 + 3*r1,c1 + 1*r2,c2 + 1*r3,c3 - c'0 = 1*r0,c0 + 2*r1,c1 + 3*r2,c2 + 1*r3,c3 - c'0 = 1*r0,c0 + 1*r1,c1 + 2*r2,c2 + 3*r3,c3 - c'0 = 3*r0,c0 + 1*r1,c1 + 1*r2,c2 + 2*r3,c3 - - c'1 = 2*r0,c1 + 3*r1,c2 + 1*r2,c3 + 1*r3,c0 - c'1 = 1*r0,c1 + 2*r1,c2 + 3*r2,c3 + 1*r3,c0 - c'1 = 1*r0,c1 + 1*r1,c2 + 2*r2,c3 + 3*r3,c0 - c'1 = 3*r0,c1 + 1*r1,c2 + 1*r2,c3 + 2*r3,c0 - - ... and so forth for c'2 and c'3. The important distinction is - that the columns are cycling, with c0 being used with the m0 - map when calculating c0, but c1 being used with the m0 map when - calculating c1 ... and so forth. - - When performing the inverse we transform the mirror image and - skip the bottom row, instead of the top one, and move upwards: - - c3 c2 c1 c0 => c0 c3 c2 c1 (cycled 3 bytes) *same as encryption - c3 c2 c1 c0 c1 c0 c3 c2 (cycled 2 bytes) - c3 c2 c1 c0 c2 c1 c0 c3 (cycled 1 byte) *same as encryption - c3 c2 c1 c0 c3 c2 c1 c0 - - If you compare the resulting matrices for ShiftRows()+MixColumns() - and for InvShiftRows()+InvMixColumns() the 2nd and 4th columns are - different (in encrypt mode vs. decrypt mode). So in order to use - the same code to handle both encryption and decryption, we will - need to do some mapping. - - If in encryption mode we let a=c0, b=c1, c=c2, d=c3, and r be - a row number in the state, then the resulting matrix in encryption - mode for applying the above transformations would be: - - r1: a b c d - r2: b c d a - r3: c d a b - r4: d a b c - - If we did the same in decryption mode we would get: - - r1: a d c b - r2: b a d c - r3: c b a d - r4: d c b a - - If instead we swap d and b (set b=c3 and d=c1), then we get: - - r1: a b c d - r2: d a b c - r3: c d a b - r4: b c d a - - Now the 1st and 3rd rows are the same as the encryption matrix. All - we need to do then to make the mapping exactly the same is to swap - the 2nd and 4th rows when in decryption mode. To do this without - having to do it on each iteration, we swapped the 2nd and 4th rows - in the decryption key schedule. We also have to do the swap above - when we first pull in the input and when we set the final output. */ - a2 = - m0[a >>> 24] ^ - m1[b >>> 16 & 255] ^ - m2[c >>> 8 & 255] ^ - m3[d & 255] ^ w[++i]; - b2 = - m0[b >>> 24] ^ - m1[c >>> 16 & 255] ^ - m2[d >>> 8 & 255] ^ - m3[a & 255] ^ w[++i]; - c2 = - m0[c >>> 24] ^ - m1[d >>> 16 & 255] ^ - m2[a >>> 8 & 255] ^ - m3[b & 255] ^ w[++i]; - d = - m0[d >>> 24] ^ - m1[a >>> 16 & 255] ^ - m2[b >>> 8 & 255] ^ - m3[c & 255] ^ w[++i]; - a = a2; - b = b2; - c = c2; - } - - /* - Encrypt: - SubBytes(state) - ShiftRows(state) - AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - - Decrypt: - InvShiftRows(state) - InvSubBytes(state) - AddRoundKey(state, w[0, Nb-1]) - */ - // Note: rows are shifted inline - output[0] = - (sub[a >>> 24] << 24) ^ - (sub[b >>> 16 & 255] << 16) ^ - (sub[c >>> 8 & 255] << 8) ^ - (sub[d & 255]) ^ w[++i]; - output[decrypt ? 3 : 1] = - (sub[b >>> 24] << 24) ^ - (sub[c >>> 16 & 255] << 16) ^ - (sub[d >>> 8 & 255] << 8) ^ - (sub[a & 255]) ^ w[++i]; - output[2] = - (sub[c >>> 24] << 24) ^ - (sub[d >>> 16 & 255] << 16) ^ - (sub[a >>> 8 & 255] << 8) ^ - (sub[b & 255]) ^ w[++i]; - output[decrypt ? 1 : 3] = - (sub[d >>> 24] << 24) ^ - (sub[a >>> 16 & 255] << 16) ^ - (sub[b >>> 8 & 255] << 8) ^ - (sub[c & 255]) ^ w[++i]; -} - -/** - * Deprecated. Instead, use: - * - * forge.cipher.createCipher('AES-', key); - * forge.cipher.createDecipher('AES-', key); - * - * Creates a deprecated AES cipher object. This object's mode will default to - * CBC (cipher-block-chaining). - * - * The key and iv may be given as a string of bytes, an array of bytes, a - * byte buffer, or an array of 32-bit words. - * - * @param options the options to use. - * key the symmetric key to use. - * output the buffer to write to. - * decrypt true for decryption, false for encryption. - * mode the cipher mode to use (default: 'CBC'). - * - * @return the cipher. - */ -function _createCipher$1(options) { - options = options || {}; - var mode = (options.mode || 'CBC').toUpperCase(); - var algorithm = 'AES-' + mode; - - var cipher; - if(options.decrypt) { - cipher = forge$z.cipher.createDecipher(algorithm, options.key); - } else { - cipher = forge$z.cipher.createCipher(algorithm, options.key); - } - - // backwards compatible start API - var start = cipher.start; - cipher.start = function(iv, options) { - // backwards compatibility: support second arg as output buffer - var output = null; - if(options instanceof forge$z.util.ByteBuffer) { - output = options; - options = {}; - } - options = options || {}; - options.output = output; - options.iv = iv; - start.call(cipher, options); - }; - - return cipher; -} - -/** - * Object IDs for ASN.1. - * - * @author Dave Longley - * - * Copyright (c) 2010-2013 Digital Bazaar, Inc. - */ - -var forge$y = forge$D; - -forge$y.pki = forge$y.pki || {}; -var oids$2 = forge$y.pki.oids = forge$y.oids = forge$y.oids || {}; - -// set id to name mapping and name to id mapping -function _IN(id, name) { - oids$2[id] = name; - oids$2[name] = id; -} -// set id to name mapping only -function _I_(id, name) { - oids$2[id] = name; -} - -// algorithm OIDs -_IN('1.2.840.113549.1.1.1', 'rsaEncryption'); -// Note: md2 & md4 not implemented -//_IN('1.2.840.113549.1.1.2', 'md2WithRSAEncryption'); -//_IN('1.2.840.113549.1.1.3', 'md4WithRSAEncryption'); -_IN('1.2.840.113549.1.1.4', 'md5WithRSAEncryption'); -_IN('1.2.840.113549.1.1.5', 'sha1WithRSAEncryption'); -_IN('1.2.840.113549.1.1.7', 'RSAES-OAEP'); -_IN('1.2.840.113549.1.1.8', 'mgf1'); -_IN('1.2.840.113549.1.1.9', 'pSpecified'); -_IN('1.2.840.113549.1.1.10', 'RSASSA-PSS'); -_IN('1.2.840.113549.1.1.11', 'sha256WithRSAEncryption'); -_IN('1.2.840.113549.1.1.12', 'sha384WithRSAEncryption'); -_IN('1.2.840.113549.1.1.13', 'sha512WithRSAEncryption'); -// Edwards-curve Digital Signature Algorithm (EdDSA) Ed25519 -_IN('1.3.101.112', 'EdDSA25519'); - -_IN('1.2.840.10040.4.3', 'dsa-with-sha1'); - -_IN('1.3.14.3.2.7', 'desCBC'); - -_IN('1.3.14.3.2.26', 'sha1'); -// Deprecated equivalent of sha1WithRSAEncryption -_IN('1.3.14.3.2.29', 'sha1WithRSASignature'); -_IN('2.16.840.1.101.3.4.2.1', 'sha256'); -_IN('2.16.840.1.101.3.4.2.2', 'sha384'); -_IN('2.16.840.1.101.3.4.2.3', 'sha512'); -_IN('2.16.840.1.101.3.4.2.4', 'sha224'); -_IN('2.16.840.1.101.3.4.2.5', 'sha512-224'); -_IN('2.16.840.1.101.3.4.2.6', 'sha512-256'); -_IN('1.2.840.113549.2.2', 'md2'); -_IN('1.2.840.113549.2.5', 'md5'); - -// pkcs#7 content types -_IN('1.2.840.113549.1.7.1', 'data'); -_IN('1.2.840.113549.1.7.2', 'signedData'); -_IN('1.2.840.113549.1.7.3', 'envelopedData'); -_IN('1.2.840.113549.1.7.4', 'signedAndEnvelopedData'); -_IN('1.2.840.113549.1.7.5', 'digestedData'); -_IN('1.2.840.113549.1.7.6', 'encryptedData'); - -// pkcs#9 oids -_IN('1.2.840.113549.1.9.1', 'emailAddress'); -_IN('1.2.840.113549.1.9.2', 'unstructuredName'); -_IN('1.2.840.113549.1.9.3', 'contentType'); -_IN('1.2.840.113549.1.9.4', 'messageDigest'); -_IN('1.2.840.113549.1.9.5', 'signingTime'); -_IN('1.2.840.113549.1.9.6', 'counterSignature'); -_IN('1.2.840.113549.1.9.7', 'challengePassword'); -_IN('1.2.840.113549.1.9.8', 'unstructuredAddress'); -_IN('1.2.840.113549.1.9.14', 'extensionRequest'); - -_IN('1.2.840.113549.1.9.20', 'friendlyName'); -_IN('1.2.840.113549.1.9.21', 'localKeyId'); -_IN('1.2.840.113549.1.9.22.1', 'x509Certificate'); - -// pkcs#12 safe bags -_IN('1.2.840.113549.1.12.10.1.1', 'keyBag'); -_IN('1.2.840.113549.1.12.10.1.2', 'pkcs8ShroudedKeyBag'); -_IN('1.2.840.113549.1.12.10.1.3', 'certBag'); -_IN('1.2.840.113549.1.12.10.1.4', 'crlBag'); -_IN('1.2.840.113549.1.12.10.1.5', 'secretBag'); -_IN('1.2.840.113549.1.12.10.1.6', 'safeContentsBag'); - -// password-based-encryption for pkcs#12 -_IN('1.2.840.113549.1.5.13', 'pkcs5PBES2'); -_IN('1.2.840.113549.1.5.12', 'pkcs5PBKDF2'); - -_IN('1.2.840.113549.1.12.1.1', 'pbeWithSHAAnd128BitRC4'); -_IN('1.2.840.113549.1.12.1.2', 'pbeWithSHAAnd40BitRC4'); -_IN('1.2.840.113549.1.12.1.3', 'pbeWithSHAAnd3-KeyTripleDES-CBC'); -_IN('1.2.840.113549.1.12.1.4', 'pbeWithSHAAnd2-KeyTripleDES-CBC'); -_IN('1.2.840.113549.1.12.1.5', 'pbeWithSHAAnd128BitRC2-CBC'); -_IN('1.2.840.113549.1.12.1.6', 'pbewithSHAAnd40BitRC2-CBC'); - -// hmac OIDs -_IN('1.2.840.113549.2.7', 'hmacWithSHA1'); -_IN('1.2.840.113549.2.8', 'hmacWithSHA224'); -_IN('1.2.840.113549.2.9', 'hmacWithSHA256'); -_IN('1.2.840.113549.2.10', 'hmacWithSHA384'); -_IN('1.2.840.113549.2.11', 'hmacWithSHA512'); - -// symmetric key algorithm oids -_IN('1.2.840.113549.3.7', 'des-EDE3-CBC'); -_IN('2.16.840.1.101.3.4.1.2', 'aes128-CBC'); -_IN('2.16.840.1.101.3.4.1.22', 'aes192-CBC'); -_IN('2.16.840.1.101.3.4.1.42', 'aes256-CBC'); - -// certificate issuer/subject OIDs -_IN('2.5.4.3', 'commonName'); -_IN('2.5.4.4', 'surname'); -_IN('2.5.4.5', 'serialNumber'); -_IN('2.5.4.6', 'countryName'); -_IN('2.5.4.7', 'localityName'); -_IN('2.5.4.8', 'stateOrProvinceName'); -_IN('2.5.4.9', 'streetAddress'); -_IN('2.5.4.10', 'organizationName'); -_IN('2.5.4.11', 'organizationalUnitName'); -_IN('2.5.4.12', 'title'); -_IN('2.5.4.13', 'description'); -_IN('2.5.4.15', 'businessCategory'); -_IN('2.5.4.17', 'postalCode'); -_IN('2.5.4.42', 'givenName'); -_IN('1.3.6.1.4.1.311.60.2.1.2', 'jurisdictionOfIncorporationStateOrProvinceName'); -_IN('1.3.6.1.4.1.311.60.2.1.3', 'jurisdictionOfIncorporationCountryName'); - -// X.509 extension OIDs -_IN('2.16.840.1.113730.1.1', 'nsCertType'); -_IN('2.16.840.1.113730.1.13', 'nsComment'); // deprecated in theory; still widely used -_I_('2.5.29.1', 'authorityKeyIdentifier'); // deprecated, use .35 -_I_('2.5.29.2', 'keyAttributes'); // obsolete use .37 or .15 -_I_('2.5.29.3', 'certificatePolicies'); // deprecated, use .32 -_I_('2.5.29.4', 'keyUsageRestriction'); // obsolete use .37 or .15 -_I_('2.5.29.5', 'policyMapping'); // deprecated use .33 -_I_('2.5.29.6', 'subtreesConstraint'); // obsolete use .30 -_I_('2.5.29.7', 'subjectAltName'); // deprecated use .17 -_I_('2.5.29.8', 'issuerAltName'); // deprecated use .18 -_I_('2.5.29.9', 'subjectDirectoryAttributes'); -_I_('2.5.29.10', 'basicConstraints'); // deprecated use .19 -_I_('2.5.29.11', 'nameConstraints'); // deprecated use .30 -_I_('2.5.29.12', 'policyConstraints'); // deprecated use .36 -_I_('2.5.29.13', 'basicConstraints'); // deprecated use .19 -_IN('2.5.29.14', 'subjectKeyIdentifier'); -_IN('2.5.29.15', 'keyUsage'); -_I_('2.5.29.16', 'privateKeyUsagePeriod'); -_IN('2.5.29.17', 'subjectAltName'); -_IN('2.5.29.18', 'issuerAltName'); -_IN('2.5.29.19', 'basicConstraints'); -_I_('2.5.29.20', 'cRLNumber'); -_I_('2.5.29.21', 'cRLReason'); -_I_('2.5.29.22', 'expirationDate'); -_I_('2.5.29.23', 'instructionCode'); -_I_('2.5.29.24', 'invalidityDate'); -_I_('2.5.29.25', 'cRLDistributionPoints'); // deprecated use .31 -_I_('2.5.29.26', 'issuingDistributionPoint'); // deprecated use .28 -_I_('2.5.29.27', 'deltaCRLIndicator'); -_I_('2.5.29.28', 'issuingDistributionPoint'); -_I_('2.5.29.29', 'certificateIssuer'); -_I_('2.5.29.30', 'nameConstraints'); -_IN('2.5.29.31', 'cRLDistributionPoints'); -_IN('2.5.29.32', 'certificatePolicies'); -_I_('2.5.29.33', 'policyMappings'); -_I_('2.5.29.34', 'policyConstraints'); // deprecated use .36 -_IN('2.5.29.35', 'authorityKeyIdentifier'); -_I_('2.5.29.36', 'policyConstraints'); -_IN('2.5.29.37', 'extKeyUsage'); -_I_('2.5.29.46', 'freshestCRL'); -_I_('2.5.29.54', 'inhibitAnyPolicy'); - -// extKeyUsage purposes -_IN('1.3.6.1.4.1.11129.2.4.2', 'timestampList'); -_IN('1.3.6.1.5.5.7.1.1', 'authorityInfoAccess'); -_IN('1.3.6.1.5.5.7.3.1', 'serverAuth'); -_IN('1.3.6.1.5.5.7.3.2', 'clientAuth'); -_IN('1.3.6.1.5.5.7.3.3', 'codeSigning'); -_IN('1.3.6.1.5.5.7.3.4', 'emailProtection'); -_IN('1.3.6.1.5.5.7.3.8', 'timeStamping'); - -/** - * Javascript implementation of Abstract Syntax Notation Number One. - * - * @author Dave Longley - * - * Copyright (c) 2010-2015 Digital Bazaar, Inc. - * - * An API for storing data using the Abstract Syntax Notation Number One - * format using DER (Distinguished Encoding Rules) encoding. This encoding is - * commonly used to store data for PKI, i.e. X.509 Certificates, and this - * implementation exists for that purpose. - * - * Abstract Syntax Notation Number One (ASN.1) is used to define the abstract - * syntax of information without restricting the way the information is encoded - * for transmission. It provides a standard that allows for open systems - * communication. ASN.1 defines the syntax of information data and a number of - * simple data types as well as a notation for describing them and specifying - * values for them. - * - * The RSA algorithm creates public and private keys that are often stored in - * X.509 or PKCS#X formats -- which use ASN.1 (encoded in DER format). This - * class provides the most basic functionality required to store and load DSA - * keys that are encoded according to ASN.1. - * - * The most common binary encodings for ASN.1 are BER (Basic Encoding Rules) - * and DER (Distinguished Encoding Rules). DER is just a subset of BER that - * has stricter requirements for how data must be encoded. - * - * Each ASN.1 structure has a tag (a byte identifying the ASN.1 structure type) - * and a byte array for the value of this ASN1 structure which may be data or a - * list of ASN.1 structures. - * - * Each ASN.1 structure using BER is (Tag-Length-Value): - * - * | byte 0 | bytes X | bytes Y | - * |--------|---------|---------- - * | tag | length | value | - * - * ASN.1 allows for tags to be of "High-tag-number form" which allows a tag to - * be two or more octets, but that is not supported by this class. A tag is - * only 1 byte. Bits 1-5 give the tag number (ie the data type within a - * particular 'class'), 6 indicates whether or not the ASN.1 value is - * constructed from other ASN.1 values, and bits 7 and 8 give the 'class'. If - * bits 7 and 8 are both zero, the class is UNIVERSAL. If only bit 7 is set, - * then the class is APPLICATION. If only bit 8 is set, then the class is - * CONTEXT_SPECIFIC. If both bits 7 and 8 are set, then the class is PRIVATE. - * The tag numbers for the data types for the class UNIVERSAL are listed below: - * - * UNIVERSAL 0 Reserved for use by the encoding rules - * UNIVERSAL 1 Boolean type - * UNIVERSAL 2 Integer type - * UNIVERSAL 3 Bitstring type - * UNIVERSAL 4 Octetstring type - * UNIVERSAL 5 Null type - * UNIVERSAL 6 Object identifier type - * UNIVERSAL 7 Object descriptor type - * UNIVERSAL 8 External type and Instance-of type - * UNIVERSAL 9 Real type - * UNIVERSAL 10 Enumerated type - * UNIVERSAL 11 Embedded-pdv type - * UNIVERSAL 12 UTF8String type - * UNIVERSAL 13 Relative object identifier type - * UNIVERSAL 14-15 Reserved for future editions - * UNIVERSAL 16 Sequence and Sequence-of types - * UNIVERSAL 17 Set and Set-of types - * UNIVERSAL 18-22, 25-30 Character string types - * UNIVERSAL 23-24 Time types - * - * The length of an ASN.1 structure is specified after the tag identifier. - * There is a definite form and an indefinite form. The indefinite form may - * be used if the encoding is constructed and not all immediately available. - * The indefinite form is encoded using a length byte with only the 8th bit - * set. The end of the constructed object is marked using end-of-contents - * octets (two zero bytes). - * - * The definite form looks like this: - * - * The length may take up 1 or more bytes, it depends on the length of the - * value of the ASN.1 structure. DER encoding requires that if the ASN.1 - * structure has a value that has a length greater than 127, more than 1 byte - * will be used to store its length, otherwise just one byte will be used. - * This is strict. - * - * In the case that the length of the ASN.1 value is less than 127, 1 octet - * (byte) is used to store the "short form" length. The 8th bit has a value of - * 0 indicating the length is "short form" and not "long form" and bits 7-1 - * give the length of the data. (The 8th bit is the left-most, most significant - * bit: also known as big endian or network format). - * - * In the case that the length of the ASN.1 value is greater than 127, 2 to - * 127 octets (bytes) are used to store the "long form" length. The first - * byte's 8th bit is set to 1 to indicate the length is "long form." Bits 7-1 - * give the number of additional octets. All following octets are in base 256 - * with the most significant digit first (typical big-endian binary unsigned - * integer storage). So, for instance, if the length of a value was 257, the - * first byte would be set to: - * - * 10000010 = 130 = 0x82. - * - * This indicates there are 2 octets (base 256) for the length. The second and - * third bytes (the octets just mentioned) would store the length in base 256: - * - * octet 2: 00000001 = 1 * 256^1 = 256 - * octet 3: 00000001 = 1 * 256^0 = 1 - * total = 257 - * - * The algorithm for converting a js integer value of 257 to base-256 is: - * - * var value = 257; - * var bytes = []; - * bytes[0] = (value >>> 8) & 0xFF; // most significant byte first - * bytes[1] = value & 0xFF; // least significant byte last - * - * On the ASN.1 UNIVERSAL Object Identifier (OID) type: - * - * An OID can be written like: "value1.value2.value3...valueN" - * - * The DER encoding rules: - * - * The first byte has the value 40 * value1 + value2. - * The following bytes, if any, encode the remaining values. Each value is - * encoded in base 128, most significant digit first (big endian), with as - * few digits as possible, and the most significant bit of each byte set - * to 1 except the last in each value's encoding. For example: Given the - * OID "1.2.840.113549", its DER encoding is (remember each byte except the - * last one in each encoding is OR'd with 0x80): - * - * byte 1: 40 * 1 + 2 = 42 = 0x2A. - * bytes 2-3: 128 * 6 + 72 = 840 = 6 72 = 6 72 = 0x0648 = 0x8648 - * bytes 4-6: 16384 * 6 + 128 * 119 + 13 = 6 119 13 = 0x06770D = 0x86F70D - * - * The final value is: 0x2A864886F70D. - * The full OID (including ASN.1 tag and length of 6 bytes) is: - * 0x06062A864886F70D - */ - -var forge$x = forge$D; - - - -/* ASN.1 API */ -var asn1$8 = forge$x.asn1 = forge$x.asn1 || {}; - -/** - * ASN.1 classes. - */ -asn1$8.Class = { - UNIVERSAL: 0x00, - APPLICATION: 0x40, - CONTEXT_SPECIFIC: 0x80, - PRIVATE: 0xC0 -}; - -/** - * ASN.1 types. Not all types are supported by this implementation, only - * those necessary to implement a simple PKI are implemented. - */ -asn1$8.Type = { - NONE: 0, - BOOLEAN: 1, - INTEGER: 2, - BITSTRING: 3, - OCTETSTRING: 4, - NULL: 5, - OID: 6, - ODESC: 7, - EXTERNAL: 8, - REAL: 9, - ENUMERATED: 10, - EMBEDDED: 11, - UTF8: 12, - ROID: 13, - SEQUENCE: 16, - SET: 17, - PRINTABLESTRING: 19, - IA5STRING: 22, - UTCTIME: 23, - GENERALIZEDTIME: 24, - BMPSTRING: 30 -}; - -/** - * Creates a new asn1 object. - * - * @param tagClass the tag class for the object. - * @param type the data type (tag number) for the object. - * @param constructed true if the asn1 object is in constructed form. - * @param value the value for the object, if it is not constructed. - * @param [options] the options to use: - * [bitStringContents] the plain BIT STRING content including padding - * byte. - * - * @return the asn1 object. - */ -asn1$8.create = function(tagClass, type, constructed, value, options) { - /* An asn1 object has a tagClass, a type, a constructed flag, and a - value. The value's type depends on the constructed flag. If - constructed, it will contain a list of other asn1 objects. If not, - it will contain the ASN.1 value as an array of bytes formatted - according to the ASN.1 data type. */ - - // remove undefined values - if(forge$x.util.isArray(value)) { - var tmp = []; - for(var i = 0; i < value.length; ++i) { - if(value[i] !== undefined) { - tmp.push(value[i]); - } - } - value = tmp; - } - - var obj = { - tagClass: tagClass, - type: type, - constructed: constructed, - composed: constructed || forge$x.util.isArray(value), - value: value - }; - if(options && 'bitStringContents' in options) { - // TODO: copy byte buffer if it's a buffer not a string - obj.bitStringContents = options.bitStringContents; - // TODO: add readonly flag to avoid this overhead - // save copy to detect changes - obj.original = asn1$8.copy(obj); - } - return obj; -}; - -/** - * Copies an asn1 object. - * - * @param obj the asn1 object. - * @param [options] copy options: - * [excludeBitStringContents] true to not copy bitStringContents - * - * @return the a copy of the asn1 object. - */ -asn1$8.copy = function(obj, options) { - var copy; - - if(forge$x.util.isArray(obj)) { - copy = []; - for(var i = 0; i < obj.length; ++i) { - copy.push(asn1$8.copy(obj[i], options)); - } - return copy; - } - - if(typeof obj === 'string') { - // TODO: copy byte buffer if it's a buffer not a string - return obj; - } - - copy = { - tagClass: obj.tagClass, - type: obj.type, - constructed: obj.constructed, - composed: obj.composed, - value: asn1$8.copy(obj.value, options) - }; - if(options && !options.excludeBitStringContents) { - // TODO: copy byte buffer if it's a buffer not a string - copy.bitStringContents = obj.bitStringContents; - } - return copy; -}; - -/** - * Compares asn1 objects for equality. - * - * Note this function does not run in constant time. - * - * @param obj1 the first asn1 object. - * @param obj2 the second asn1 object. - * @param [options] compare options: - * [includeBitStringContents] true to compare bitStringContents - * - * @return true if the asn1 objects are equal. - */ -asn1$8.equals = function(obj1, obj2, options) { - if(forge$x.util.isArray(obj1)) { - if(!forge$x.util.isArray(obj2)) { - return false; - } - if(obj1.length !== obj2.length) { - return false; - } - for(var i = 0; i < obj1.length; ++i) { - if(!asn1$8.equals(obj1[i], obj2[i])) { - return false; - } - } - return true; - } - - if(typeof obj1 !== typeof obj2) { - return false; - } - - if(typeof obj1 === 'string') { - return obj1 === obj2; - } - - var equal = obj1.tagClass === obj2.tagClass && - obj1.type === obj2.type && - obj1.constructed === obj2.constructed && - obj1.composed === obj2.composed && - asn1$8.equals(obj1.value, obj2.value); - if(options && options.includeBitStringContents) { - equal = equal && (obj1.bitStringContents === obj2.bitStringContents); - } - - return equal; -}; - -/** - * Gets the length of a BER-encoded ASN.1 value. - * - * In case the length is not specified, undefined is returned. - * - * @param b the BER-encoded ASN.1 byte buffer, starting with the first - * length byte. - * - * @return the length of the BER-encoded ASN.1 value or undefined. - */ -asn1$8.getBerValueLength = function(b) { - // TODO: move this function and related DER/BER functions to a der.js - // file; better abstract ASN.1 away from der/ber. - var b2 = b.getByte(); - if(b2 === 0x80) { - return undefined; - } - - // see if the length is "short form" or "long form" (bit 8 set) - var length; - var longForm = b2 & 0x80; - if(!longForm) { - // length is just the first byte - length = b2; - } else { - // the number of bytes the length is specified in bits 7 through 1 - // and each length byte is in big-endian base-256 - length = b.getInt((b2 & 0x7F) << 3); - } - return length; -}; - -/** - * Check if the byte buffer has enough bytes. Throws an Error if not. - * - * @param bytes the byte buffer to parse from. - * @param remaining the bytes remaining in the current parsing state. - * @param n the number of bytes the buffer must have. - */ -function _checkBufferLength(bytes, remaining, n) { - if(n > remaining) { - var error = new Error('Too few bytes to parse DER.'); - error.available = bytes.length(); - error.remaining = remaining; - error.requested = n; - throw error; - } -} - -/** - * Gets the length of a BER-encoded ASN.1 value. - * - * In case the length is not specified, undefined is returned. - * - * @param bytes the byte buffer to parse from. - * @param remaining the bytes remaining in the current parsing state. - * - * @return the length of the BER-encoded ASN.1 value or undefined. - */ -var _getValueLength = function(bytes, remaining) { - // TODO: move this function and related DER/BER functions to a der.js - // file; better abstract ASN.1 away from der/ber. - // fromDer already checked that this byte exists - var b2 = bytes.getByte(); - remaining--; - if(b2 === 0x80) { - return undefined; - } - - // see if the length is "short form" or "long form" (bit 8 set) - var length; - var longForm = b2 & 0x80; - if(!longForm) { - // length is just the first byte - length = b2; - } else { - // the number of bytes the length is specified in bits 7 through 1 - // and each length byte is in big-endian base-256 - var longFormBytes = b2 & 0x7F; - _checkBufferLength(bytes, remaining, longFormBytes); - length = bytes.getInt(longFormBytes << 3); - } - // FIXME: this will only happen for 32 bit getInt with high bit set - if(length < 0) { - throw new Error('Negative length: ' + length); - } - return length; -}; - -/** - * Parses an asn1 object from a byte buffer in DER format. - * - * @param bytes the byte buffer to parse from. - * @param [strict] true to be strict when checking value lengths, false to - * allow truncated values (default: true). - * @param [options] object with options or boolean strict flag - * [strict] true to be strict when checking value lengths, false to - * allow truncated values (default: true). - * [parseAllBytes] true to ensure all bytes are parsed - * (default: true) - * [decodeBitStrings] true to attempt to decode the content of - * BIT STRINGs (not OCTET STRINGs) using strict mode. Note that - * without schema support to understand the data context this can - * erroneously decode values that happen to be valid ASN.1. This - * flag will be deprecated or removed as soon as schema support is - * available. (default: true) - * - * @throws Will throw an error for various malformed input conditions. - * - * @return the parsed asn1 object. - */ -asn1$8.fromDer = function(bytes, options) { - if(options === undefined) { - options = { - strict: true, - parseAllBytes: true, - decodeBitStrings: true - }; - } - if(typeof options === 'boolean') { - options = { - strict: options, - parseAllBytes: true, - decodeBitStrings: true - }; - } - if(!('strict' in options)) { - options.strict = true; - } - if(!('parseAllBytes' in options)) { - options.parseAllBytes = true; - } - if(!('decodeBitStrings' in options)) { - options.decodeBitStrings = true; - } - - // wrap in buffer if needed - if(typeof bytes === 'string') { - bytes = forge$x.util.createBuffer(bytes); - } - - var byteCount = bytes.length(); - var value = _fromDer(bytes, bytes.length(), 0, options); - if(options.parseAllBytes && bytes.length() !== 0) { - var error = new Error('Unparsed DER bytes remain after ASN.1 parsing.'); - error.byteCount = byteCount; - error.remaining = bytes.length(); - throw error; - } - return value; -}; - -/** - * Internal function to parse an asn1 object from a byte buffer in DER format. - * - * @param bytes the byte buffer to parse from. - * @param remaining the number of bytes remaining for this chunk. - * @param depth the current parsing depth. - * @param options object with same options as fromDer(). - * - * @return the parsed asn1 object. - */ -function _fromDer(bytes, remaining, depth, options) { - // temporary storage for consumption calculations - var start; - - // minimum length for ASN.1 DER structure is 2 - _checkBufferLength(bytes, remaining, 2); - - // get the first byte - var b1 = bytes.getByte(); - // consumed one byte - remaining--; - - // get the tag class - var tagClass = (b1 & 0xC0); - - // get the type (bits 1-5) - var type = b1 & 0x1F; - - // get the variable value length and adjust remaining bytes - start = bytes.length(); - var length = _getValueLength(bytes, remaining); - remaining -= start - bytes.length(); - - // ensure there are enough bytes to get the value - if(length !== undefined && length > remaining) { - if(options.strict) { - var error = new Error('Too few bytes to read ASN.1 value.'); - error.available = bytes.length(); - error.remaining = remaining; - error.requested = length; - throw error; - } - // Note: be lenient with truncated values and use remaining state bytes - length = remaining; - } - - // value storage - var value; - // possible BIT STRING contents storage - var bitStringContents; - - // constructed flag is bit 6 (32 = 0x20) of the first byte - var constructed = ((b1 & 0x20) === 0x20); - if(constructed) { - // parse child asn1 objects from the value - value = []; - if(length === undefined) { - // asn1 object of indefinite length, read until end tag - for(;;) { - _checkBufferLength(bytes, remaining, 2); - if(bytes.bytes(2) === String.fromCharCode(0, 0)) { - bytes.getBytes(2); - remaining -= 2; - break; - } - start = bytes.length(); - value.push(_fromDer(bytes, remaining, depth + 1, options)); - remaining -= start - bytes.length(); - } - } else { - // parsing asn1 object of definite length - while(length > 0) { - start = bytes.length(); - value.push(_fromDer(bytes, length, depth + 1, options)); - remaining -= start - bytes.length(); - length -= start - bytes.length(); - } - } - } - - // if a BIT STRING, save the contents including padding - if(value === undefined && tagClass === asn1$8.Class.UNIVERSAL && - type === asn1$8.Type.BITSTRING) { - bitStringContents = bytes.bytes(length); - } - - // determine if a non-constructed value should be decoded as a composed - // value that contains other ASN.1 objects. BIT STRINGs (and OCTET STRINGs) - // can be used this way. - if(value === undefined && options.decodeBitStrings && - tagClass === asn1$8.Class.UNIVERSAL && - // FIXME: OCTET STRINGs not yet supported here - // .. other parts of forge expect to decode OCTET STRINGs manually - (type === asn1$8.Type.BITSTRING /*|| type === asn1.Type.OCTETSTRING*/) && - length > 1) { - // save read position - var savedRead = bytes.read; - var savedRemaining = remaining; - var unused = 0; - if(type === asn1$8.Type.BITSTRING) { - /* The first octet gives the number of bits by which the length of the - bit string is less than the next multiple of eight (this is called - the "number of unused bits"). - - The second and following octets give the value of the bit string - converted to an octet string. */ - _checkBufferLength(bytes, remaining, 1); - unused = bytes.getByte(); - remaining--; - } - // if all bits are used, maybe the BIT/OCTET STRING holds ASN.1 objs - if(unused === 0) { - try { - // attempt to parse child asn1 object from the value - // (stored in array to signal composed value) - start = bytes.length(); - var subOptions = { - // enforce strict mode to avoid parsing ASN.1 from plain data - strict: true, - decodeBitStrings: true - }; - var composed = _fromDer(bytes, remaining, depth + 1, subOptions); - var used = start - bytes.length(); - remaining -= used; - if(type == asn1$8.Type.BITSTRING) { - used++; - } - - // if the data all decoded and the class indicates UNIVERSAL or - // CONTEXT_SPECIFIC then assume we've got an encapsulated ASN.1 object - var tc = composed.tagClass; - if(used === length && - (tc === asn1$8.Class.UNIVERSAL || tc === asn1$8.Class.CONTEXT_SPECIFIC)) { - value = [composed]; - } - } catch(ex) { - } - } - if(value === undefined) { - // restore read position - bytes.read = savedRead; - remaining = savedRemaining; - } - } - - if(value === undefined) { - // asn1 not constructed or composed, get raw value - // TODO: do DER to OID conversion and vice-versa in .toDer? - - if(length === undefined) { - if(options.strict) { - throw new Error('Non-constructed ASN.1 object of indefinite length.'); - } - // be lenient and use remaining state bytes - length = remaining; - } - - if(type === asn1$8.Type.BMPSTRING) { - value = ''; - for(; length > 0; length -= 2) { - _checkBufferLength(bytes, remaining, 2); - value += String.fromCharCode(bytes.getInt16()); - remaining -= 2; - } - } else { - value = bytes.getBytes(length); - remaining -= length; - } - } - - // add BIT STRING contents if available - var asn1Options = bitStringContents === undefined ? null : { - bitStringContents: bitStringContents - }; - - // create and return asn1 object - return asn1$8.create(tagClass, type, constructed, value, asn1Options); -} - -/** - * Converts the given asn1 object to a buffer of bytes in DER format. - * - * @param asn1 the asn1 object to convert to bytes. - * - * @return the buffer of bytes. - */ -asn1$8.toDer = function(obj) { - var bytes = forge$x.util.createBuffer(); - - // build the first byte - var b1 = obj.tagClass | obj.type; - - // for storing the ASN.1 value - var value = forge$x.util.createBuffer(); - - // use BIT STRING contents if available and data not changed - var useBitStringContents = false; - if('bitStringContents' in obj) { - useBitStringContents = true; - if(obj.original) { - useBitStringContents = asn1$8.equals(obj, obj.original); - } - } - - if(useBitStringContents) { - value.putBytes(obj.bitStringContents); - } else if(obj.composed) { - // if composed, use each child asn1 object's DER bytes as value - // turn on 6th bit (0x20 = 32) to indicate asn1 is constructed - // from other asn1 objects - if(obj.constructed) { - b1 |= 0x20; - } else { - // type is a bit string, add unused bits of 0x00 - value.putByte(0x00); - } - - // add all of the child DER bytes together - for(var i = 0; i < obj.value.length; ++i) { - if(obj.value[i] !== undefined) { - value.putBuffer(asn1$8.toDer(obj.value[i])); - } - } - } else { - // use asn1.value directly - if(obj.type === asn1$8.Type.BMPSTRING) { - for(var i = 0; i < obj.value.length; ++i) { - value.putInt16(obj.value.charCodeAt(i)); - } - } else { - // ensure integer is minimally-encoded - // TODO: should all leading bytes be stripped vs just one? - // .. ex '00 00 01' => '01'? - if(obj.type === asn1$8.Type.INTEGER && - obj.value.length > 1 && - // leading 0x00 for positive integer - ((obj.value.charCodeAt(0) === 0 && - (obj.value.charCodeAt(1) & 0x80) === 0) || - // leading 0xFF for negative integer - (obj.value.charCodeAt(0) === 0xFF && - (obj.value.charCodeAt(1) & 0x80) === 0x80))) { - value.putBytes(obj.value.substr(1)); - } else { - value.putBytes(obj.value); - } - } - } - - // add tag byte - bytes.putByte(b1); - - // use "short form" encoding - if(value.length() <= 127) { - // one byte describes the length - // bit 8 = 0 and bits 7-1 = length - bytes.putByte(value.length() & 0x7F); - } else { - // use "long form" encoding - // 2 to 127 bytes describe the length - // first byte: bit 8 = 1 and bits 7-1 = # of additional bytes - // other bytes: length in base 256, big-endian - var len = value.length(); - var lenBytes = ''; - do { - lenBytes += String.fromCharCode(len & 0xFF); - len = len >>> 8; - } while(len > 0); - - // set first byte to # bytes used to store the length and turn on - // bit 8 to indicate long-form length is used - bytes.putByte(lenBytes.length | 0x80); - - // concatenate length bytes in reverse since they were generated - // little endian and we need big endian - for(var i = lenBytes.length - 1; i >= 0; --i) { - bytes.putByte(lenBytes.charCodeAt(i)); - } - } - - // concatenate value bytes - bytes.putBuffer(value); - return bytes; -}; - -/** - * Converts an OID dot-separated string to a byte buffer. The byte buffer - * contains only the DER-encoded value, not any tag or length bytes. - * - * @param oid the OID dot-separated string. - * - * @return the byte buffer. - */ -asn1$8.oidToDer = function(oid) { - // split OID into individual values - var values = oid.split('.'); - var bytes = forge$x.util.createBuffer(); - - // first byte is 40 * value1 + value2 - bytes.putByte(40 * parseInt(values[0], 10) + parseInt(values[1], 10)); - // other bytes are each value in base 128 with 8th bit set except for - // the last byte for each value - var last, valueBytes, value, b; - for(var i = 2; i < values.length; ++i) { - // produce value bytes in reverse because we don't know how many - // bytes it will take to store the value - last = true; - valueBytes = []; - value = parseInt(values[i], 10); - do { - b = value & 0x7F; - value = value >>> 7; - // if value is not last, then turn on 8th bit - if(!last) { - b |= 0x80; - } - valueBytes.push(b); - last = false; - } while(value > 0); - - // add value bytes in reverse (needs to be in big endian) - for(var n = valueBytes.length - 1; n >= 0; --n) { - bytes.putByte(valueBytes[n]); - } - } - - return bytes; -}; - -/** - * Converts a DER-encoded byte buffer to an OID dot-separated string. The - * byte buffer should contain only the DER-encoded value, not any tag or - * length bytes. - * - * @param bytes the byte buffer. - * - * @return the OID dot-separated string. - */ -asn1$8.derToOid = function(bytes) { - var oid; - - // wrap in buffer if needed - if(typeof bytes === 'string') { - bytes = forge$x.util.createBuffer(bytes); - } - - // first byte is 40 * value1 + value2 - var b = bytes.getByte(); - oid = Math.floor(b / 40) + '.' + (b % 40); - - // other bytes are each value in base 128 with 8th bit set except for - // the last byte for each value - var value = 0; - while(bytes.length() > 0) { - b = bytes.getByte(); - value = value << 7; - // not the last byte for the value - if(b & 0x80) { - value += b & 0x7F; - } else { - // last byte - oid += '.' + (value + b); - value = 0; - } - } - - return oid; -}; - -/** - * Converts a UTCTime value to a date. - * - * Note: GeneralizedTime has 4 digits for the year and is used for X.509 - * dates past 2049. Parsing that structure hasn't been implemented yet. - * - * @param utc the UTCTime value to convert. - * - * @return the date. - */ -asn1$8.utcTimeToDate = function(utc) { - /* The following formats can be used: - - YYMMDDhhmmZ - YYMMDDhhmm+hh'mm' - YYMMDDhhmm-hh'mm' - YYMMDDhhmmssZ - YYMMDDhhmmss+hh'mm' - YYMMDDhhmmss-hh'mm' - - Where: - - YY is the least significant two digits of the year - MM is the month (01 to 12) - DD is the day (01 to 31) - hh is the hour (00 to 23) - mm are the minutes (00 to 59) - ss are the seconds (00 to 59) - Z indicates that local time is GMT, + indicates that local time is - later than GMT, and - indicates that local time is earlier than GMT - hh' is the absolute value of the offset from GMT in hours - mm' is the absolute value of the offset from GMT in minutes */ - var date = new Date(); - - // if YY >= 50 use 19xx, if YY < 50 use 20xx - var year = parseInt(utc.substr(0, 2), 10); - year = (year >= 50) ? 1900 + year : 2000 + year; - var MM = parseInt(utc.substr(2, 2), 10) - 1; // use 0-11 for month - var DD = parseInt(utc.substr(4, 2), 10); - var hh = parseInt(utc.substr(6, 2), 10); - var mm = parseInt(utc.substr(8, 2), 10); - var ss = 0; - - // not just YYMMDDhhmmZ - if(utc.length > 11) { - // get character after minutes - var c = utc.charAt(10); - var end = 10; - - // see if seconds are present - if(c !== '+' && c !== '-') { - // get seconds - ss = parseInt(utc.substr(10, 2), 10); - end += 2; - } - } - - // update date - date.setUTCFullYear(year, MM, DD); - date.setUTCHours(hh, mm, ss, 0); - - if(end) { - // get +/- after end of time - c = utc.charAt(end); - if(c === '+' || c === '-') { - // get hours+minutes offset - var hhoffset = parseInt(utc.substr(end + 1, 2), 10); - var mmoffset = parseInt(utc.substr(end + 4, 2), 10); - - // calculate offset in milliseconds - var offset = hhoffset * 60 + mmoffset; - offset *= 60000; - - // apply offset - if(c === '+') { - date.setTime(+date - offset); - } else { - date.setTime(+date + offset); - } - } - } - - return date; -}; - -/** - * Converts a GeneralizedTime value to a date. - * - * @param gentime the GeneralizedTime value to convert. - * - * @return the date. - */ -asn1$8.generalizedTimeToDate = function(gentime) { - /* The following formats can be used: - - YYYYMMDDHHMMSS - YYYYMMDDHHMMSS.fff - YYYYMMDDHHMMSSZ - YYYYMMDDHHMMSS.fffZ - YYYYMMDDHHMMSS+hh'mm' - YYYYMMDDHHMMSS.fff+hh'mm' - YYYYMMDDHHMMSS-hh'mm' - YYYYMMDDHHMMSS.fff-hh'mm' - - Where: - - YYYY is the year - MM is the month (01 to 12) - DD is the day (01 to 31) - hh is the hour (00 to 23) - mm are the minutes (00 to 59) - ss are the seconds (00 to 59) - .fff is the second fraction, accurate to three decimal places - Z indicates that local time is GMT, + indicates that local time is - later than GMT, and - indicates that local time is earlier than GMT - hh' is the absolute value of the offset from GMT in hours - mm' is the absolute value of the offset from GMT in minutes */ - var date = new Date(); - - var YYYY = parseInt(gentime.substr(0, 4), 10); - var MM = parseInt(gentime.substr(4, 2), 10) - 1; // use 0-11 for month - var DD = parseInt(gentime.substr(6, 2), 10); - var hh = parseInt(gentime.substr(8, 2), 10); - var mm = parseInt(gentime.substr(10, 2), 10); - var ss = parseInt(gentime.substr(12, 2), 10); - var fff = 0; - var offset = 0; - var isUTC = false; - - if(gentime.charAt(gentime.length - 1) === 'Z') { - isUTC = true; - } - - var end = gentime.length - 5, c = gentime.charAt(end); - if(c === '+' || c === '-') { - // get hours+minutes offset - var hhoffset = parseInt(gentime.substr(end + 1, 2), 10); - var mmoffset = parseInt(gentime.substr(end + 4, 2), 10); - - // calculate offset in milliseconds - offset = hhoffset * 60 + mmoffset; - offset *= 60000; - - // apply offset - if(c === '+') { - offset *= -1; - } - - isUTC = true; - } - - // check for second fraction - if(gentime.charAt(14) === '.') { - fff = parseFloat(gentime.substr(14), 10) * 1000; - } - - if(isUTC) { - date.setUTCFullYear(YYYY, MM, DD); - date.setUTCHours(hh, mm, ss, fff); - - // apply offset - date.setTime(+date + offset); - } else { - date.setFullYear(YYYY, MM, DD); - date.setHours(hh, mm, ss, fff); - } - - return date; -}; - -/** - * Converts a date to a UTCTime value. - * - * Note: GeneralizedTime has 4 digits for the year and is used for X.509 - * dates past 2049. Converting to a GeneralizedTime hasn't been - * implemented yet. - * - * @param date the date to convert. - * - * @return the UTCTime value. - */ -asn1$8.dateToUtcTime = function(date) { - // TODO: validate; currently assumes proper format - if(typeof date === 'string') { - return date; - } - - var rval = ''; - - // create format YYMMDDhhmmssZ - var format = []; - format.push(('' + date.getUTCFullYear()).substr(2)); - format.push('' + (date.getUTCMonth() + 1)); - format.push('' + date.getUTCDate()); - format.push('' + date.getUTCHours()); - format.push('' + date.getUTCMinutes()); - format.push('' + date.getUTCSeconds()); - - // ensure 2 digits are used for each format entry - for(var i = 0; i < format.length; ++i) { - if(format[i].length < 2) { - rval += '0'; - } - rval += format[i]; - } - rval += 'Z'; - - return rval; -}; - -/** - * Converts a date to a GeneralizedTime value. - * - * @param date the date to convert. - * - * @return the GeneralizedTime value as a string. - */ -asn1$8.dateToGeneralizedTime = function(date) { - // TODO: validate; currently assumes proper format - if(typeof date === 'string') { - return date; - } - - var rval = ''; - - // create format YYYYMMDDHHMMSSZ - var format = []; - format.push('' + date.getUTCFullYear()); - format.push('' + (date.getUTCMonth() + 1)); - format.push('' + date.getUTCDate()); - format.push('' + date.getUTCHours()); - format.push('' + date.getUTCMinutes()); - format.push('' + date.getUTCSeconds()); - - // ensure 2 digits are used for each format entry - for(var i = 0; i < format.length; ++i) { - if(format[i].length < 2) { - rval += '0'; - } - rval += format[i]; - } - rval += 'Z'; - - return rval; -}; - -/** - * Converts a javascript integer to a DER-encoded byte buffer to be used - * as the value for an INTEGER type. - * - * @param x the integer. - * - * @return the byte buffer. - */ -asn1$8.integerToDer = function(x) { - var rval = forge$x.util.createBuffer(); - if(x >= -0x80 && x < 0x80) { - return rval.putSignedInt(x, 8); - } - if(x >= -0x8000 && x < 0x8000) { - return rval.putSignedInt(x, 16); - } - if(x >= -0x800000 && x < 0x800000) { - return rval.putSignedInt(x, 24); - } - if(x >= -0x80000000 && x < 0x80000000) { - return rval.putSignedInt(x, 32); - } - var error = new Error('Integer too large; max is 32-bits.'); - error.integer = x; - throw error; -}; - -/** - * Converts a DER-encoded byte buffer to a javascript integer. This is - * typically used to decode the value of an INTEGER type. - * - * @param bytes the byte buffer. - * - * @return the integer. - */ -asn1$8.derToInteger = function(bytes) { - // wrap in buffer if needed - if(typeof bytes === 'string') { - bytes = forge$x.util.createBuffer(bytes); - } - - var n = bytes.length() * 8; - if(n > 32) { - throw new Error('Integer too large; max is 32-bits.'); - } - return bytes.getSignedInt(n); -}; - -/** - * Validates that the given ASN.1 object is at least a super set of the - * given ASN.1 structure. Only tag classes and types are checked. An - * optional map may also be provided to capture ASN.1 values while the - * structure is checked. - * - * To capture an ASN.1 value, set an object in the validator's 'capture' - * parameter to the key to use in the capture map. To capture the full - * ASN.1 object, specify 'captureAsn1'. To capture BIT STRING bytes, including - * the leading unused bits counter byte, specify 'captureBitStringContents'. - * To capture BIT STRING bytes, without the leading unused bits counter byte, - * specify 'captureBitStringValue'. - * - * Objects in the validator may set a field 'optional' to true to indicate - * that it isn't necessary to pass validation. - * - * @param obj the ASN.1 object to validate. - * @param v the ASN.1 structure validator. - * @param capture an optional map to capture values in. - * @param errors an optional array for storing validation errors. - * - * @return true on success, false on failure. - */ -asn1$8.validate = function(obj, v, capture, errors) { - var rval = false; - - // ensure tag class and type are the same if specified - if((obj.tagClass === v.tagClass || typeof(v.tagClass) === 'undefined') && - (obj.type === v.type || typeof(v.type) === 'undefined')) { - // ensure constructed flag is the same if specified - if(obj.constructed === v.constructed || - typeof(v.constructed) === 'undefined') { - rval = true; - - // handle sub values - if(v.value && forge$x.util.isArray(v.value)) { - var j = 0; - for(var i = 0; rval && i < v.value.length; ++i) { - rval = v.value[i].optional || false; - if(obj.value[j]) { - rval = asn1$8.validate(obj.value[j], v.value[i], capture, errors); - if(rval) { - ++j; - } else if(v.value[i].optional) { - rval = true; - } - } - if(!rval && errors) { - errors.push( - '[' + v.name + '] ' + - 'Tag class "' + v.tagClass + '", type "' + - v.type + '" expected value length "' + - v.value.length + '", got "' + - obj.value.length + '"'); - } - } - } - - if(rval && capture) { - if(v.capture) { - capture[v.capture] = obj.value; - } - if(v.captureAsn1) { - capture[v.captureAsn1] = obj; - } - if(v.captureBitStringContents && 'bitStringContents' in obj) { - capture[v.captureBitStringContents] = obj.bitStringContents; - } - if(v.captureBitStringValue && 'bitStringContents' in obj) { - if(obj.bitStringContents.length < 2) { - capture[v.captureBitStringValue] = ''; - } else { - // FIXME: support unused bits with data shifting - var unused = obj.bitStringContents.charCodeAt(0); - if(unused !== 0) { - throw new Error( - 'captureBitStringValue only supported for zero unused bits'); - } - capture[v.captureBitStringValue] = obj.bitStringContents.slice(1); - } - } - } - } else if(errors) { - errors.push( - '[' + v.name + '] ' + - 'Expected constructed "' + v.constructed + '", got "' + - obj.constructed + '"'); - } - } else if(errors) { - if(obj.tagClass !== v.tagClass) { - errors.push( - '[' + v.name + '] ' + - 'Expected tag class "' + v.tagClass + '", got "' + - obj.tagClass + '"'); - } - if(obj.type !== v.type) { - errors.push( - '[' + v.name + '] ' + - 'Expected type "' + v.type + '", got "' + obj.type + '"'); - } - } - return rval; -}; - -// regex for testing for non-latin characters -var _nonLatinRegex = /[^\\u0000-\\u00ff]/; - -/** - * Pretty prints an ASN.1 object to a string. - * - * @param obj the object to write out. - * @param level the level in the tree. - * @param indentation the indentation to use. - * - * @return the string. - */ -asn1$8.prettyPrint = function(obj, level, indentation) { - var rval = ''; - - // set default level and indentation - level = level || 0; - indentation = indentation || 2; - - // start new line for deep levels - if(level > 0) { - rval += '\n'; - } - - // create indent - var indent = ''; - for(var i = 0; i < level * indentation; ++i) { - indent += ' '; - } - - // print class:type - rval += indent + 'Tag: '; - switch(obj.tagClass) { - case asn1$8.Class.UNIVERSAL: - rval += 'Universal:'; - break; - case asn1$8.Class.APPLICATION: - rval += 'Application:'; - break; - case asn1$8.Class.CONTEXT_SPECIFIC: - rval += 'Context-Specific:'; - break; - case asn1$8.Class.PRIVATE: - rval += 'Private:'; - break; - } - - if(obj.tagClass === asn1$8.Class.UNIVERSAL) { - rval += obj.type; - - // known types - switch(obj.type) { - case asn1$8.Type.NONE: - rval += ' (None)'; - break; - case asn1$8.Type.BOOLEAN: - rval += ' (Boolean)'; - break; - case asn1$8.Type.INTEGER: - rval += ' (Integer)'; - break; - case asn1$8.Type.BITSTRING: - rval += ' (Bit string)'; - break; - case asn1$8.Type.OCTETSTRING: - rval += ' (Octet string)'; - break; - case asn1$8.Type.NULL: - rval += ' (Null)'; - break; - case asn1$8.Type.OID: - rval += ' (Object Identifier)'; - break; - case asn1$8.Type.ODESC: - rval += ' (Object Descriptor)'; - break; - case asn1$8.Type.EXTERNAL: - rval += ' (External or Instance of)'; - break; - case asn1$8.Type.REAL: - rval += ' (Real)'; - break; - case asn1$8.Type.ENUMERATED: - rval += ' (Enumerated)'; - break; - case asn1$8.Type.EMBEDDED: - rval += ' (Embedded PDV)'; - break; - case asn1$8.Type.UTF8: - rval += ' (UTF8)'; - break; - case asn1$8.Type.ROID: - rval += ' (Relative Object Identifier)'; - break; - case asn1$8.Type.SEQUENCE: - rval += ' (Sequence)'; - break; - case asn1$8.Type.SET: - rval += ' (Set)'; - break; - case asn1$8.Type.PRINTABLESTRING: - rval += ' (Printable String)'; - break; - case asn1$8.Type.IA5String: - rval += ' (IA5String (ASCII))'; - break; - case asn1$8.Type.UTCTIME: - rval += ' (UTC time)'; - break; - case asn1$8.Type.GENERALIZEDTIME: - rval += ' (Generalized time)'; - break; - case asn1$8.Type.BMPSTRING: - rval += ' (BMP String)'; - break; - } - } else { - rval += obj.type; - } - - rval += '\n'; - rval += indent + 'Constructed: ' + obj.constructed + '\n'; - - if(obj.composed) { - var subvalues = 0; - var sub = ''; - for(var i = 0; i < obj.value.length; ++i) { - if(obj.value[i] !== undefined) { - subvalues += 1; - sub += asn1$8.prettyPrint(obj.value[i], level + 1, indentation); - if((i + 1) < obj.value.length) { - sub += ','; - } - } - } - rval += indent + 'Sub values: ' + subvalues + sub; - } else { - rval += indent + 'Value: '; - if(obj.type === asn1$8.Type.OID) { - var oid = asn1$8.derToOid(obj.value); - rval += oid; - if(forge$x.pki && forge$x.pki.oids) { - if(oid in forge$x.pki.oids) { - rval += ' (' + forge$x.pki.oids[oid] + ') '; - } - } - } - if(obj.type === asn1$8.Type.INTEGER) { - try { - rval += asn1$8.derToInteger(obj.value); - } catch(ex) { - rval += '0x' + forge$x.util.bytesToHex(obj.value); - } - } else if(obj.type === asn1$8.Type.BITSTRING) { - // TODO: shift bits as needed to display without padding - if(obj.value.length > 1) { - // remove unused bits field - rval += '0x' + forge$x.util.bytesToHex(obj.value.slice(1)); - } else { - rval += '(none)'; - } - // show unused bit count - if(obj.value.length > 0) { - var unused = obj.value.charCodeAt(0); - if(unused == 1) { - rval += ' (1 unused bit shown)'; - } else if(unused > 1) { - rval += ' (' + unused + ' unused bits shown)'; - } - } - } else if(obj.type === asn1$8.Type.OCTETSTRING) { - if(!_nonLatinRegex.test(obj.value)) { - rval += '(' + obj.value + ') '; - } - rval += '0x' + forge$x.util.bytesToHex(obj.value); - } else if(obj.type === asn1$8.Type.UTF8) { - try { - rval += forge$x.util.decodeUtf8(obj.value); - } catch(e) { - if(e.message === 'URI malformed') { - rval += - '0x' + forge$x.util.bytesToHex(obj.value) + ' (malformed UTF8)'; - } else { - throw e; - } - } - } else if(obj.type === asn1$8.Type.PRINTABLESTRING || - obj.type === asn1$8.Type.IA5String) { - rval += obj.value; - } else if(_nonLatinRegex.test(obj.value)) { - rval += '0x' + forge$x.util.bytesToHex(obj.value); - } else if(obj.value.length === 0) { - rval += '[null]'; - } else { - rval += obj.value; - } - } - - return rval; -}; - -/** - * Node.js module for Forge message digests. - * - * @author Dave Longley - * - * Copyright 2011-2017 Digital Bazaar, Inc. - */ - -var forge$w = forge$D; - -forge$w.md = forge$w.md || {}; -forge$w.md.algorithms = forge$w.md.algorithms || {}; - -/** - * Hash-based Message Authentication Code implementation. Requires a message - * digest object that can be obtained, for example, from forge.md.sha1 or - * forge.md.md5. - * - * @author Dave Longley - * - * Copyright (c) 2010-2012 Digital Bazaar, Inc. All rights reserved. - */ - -var forge$v = forge$D; - - - -/* HMAC API */ -var hmac = forge$v.hmac = forge$v.hmac || {}; - -/** - * Creates an HMAC object that uses the given message digest object. - * - * @return an HMAC object. - */ -hmac.create = function() { - // the hmac key to use - var _key = null; - - // the message digest to use - var _md = null; - - // the inner padding - var _ipadding = null; - - // the outer padding - var _opadding = null; - - // hmac context - var ctx = {}; - - /** - * Starts or restarts the HMAC with the given key and message digest. - * - * @param md the message digest to use, null to reuse the previous one, - * a string to use builtin 'sha1', 'md5', 'sha256'. - * @param key the key to use as a string, array of bytes, byte buffer, - * or null to reuse the previous key. - */ - ctx.start = function(md, key) { - if(md !== null) { - if(typeof md === 'string') { - // create builtin message digest - md = md.toLowerCase(); - if(md in forge$v.md.algorithms) { - _md = forge$v.md.algorithms[md].create(); - } else { - throw new Error('Unknown hash algorithm "' + md + '"'); - } - } else { - // store message digest - _md = md; - } - } - - if(key === null) { - // reuse previous key - key = _key; - } else { - if(typeof key === 'string') { - // convert string into byte buffer - key = forge$v.util.createBuffer(key); - } else if(forge$v.util.isArray(key)) { - // convert byte array into byte buffer - var tmp = key; - key = forge$v.util.createBuffer(); - for(var i = 0; i < tmp.length; ++i) { - key.putByte(tmp[i]); - } - } - - // if key is longer than blocksize, hash it - var keylen = key.length(); - if(keylen > _md.blockLength) { - _md.start(); - _md.update(key.bytes()); - key = _md.digest(); - } - - // mix key into inner and outer padding - // ipadding = [0x36 * blocksize] ^ key - // opadding = [0x5C * blocksize] ^ key - _ipadding = forge$v.util.createBuffer(); - _opadding = forge$v.util.createBuffer(); - keylen = key.length(); - for(var i = 0; i < keylen; ++i) { - var tmp = key.at(i); - _ipadding.putByte(0x36 ^ tmp); - _opadding.putByte(0x5C ^ tmp); - } - - // if key is shorter than blocksize, add additional padding - if(keylen < _md.blockLength) { - var tmp = _md.blockLength - keylen; - for(var i = 0; i < tmp; ++i) { - _ipadding.putByte(0x36); - _opadding.putByte(0x5C); - } - } - _key = key; - _ipadding = _ipadding.bytes(); - _opadding = _opadding.bytes(); - } - - // digest is done like so: hash(opadding | hash(ipadding | message)) - - // prepare to do inner hash - // hash(ipadding | message) - _md.start(); - _md.update(_ipadding); - }; - - /** - * Updates the HMAC with the given message bytes. - * - * @param bytes the bytes to update with. - */ - ctx.update = function(bytes) { - _md.update(bytes); - }; - - /** - * Produces the Message Authentication Code (MAC). - * - * @return a byte buffer containing the digest value. - */ - ctx.getMac = function() { - // digest is done like so: hash(opadding | hash(ipadding | message)) - // here we do the outer hashing - var inner = _md.digest().bytes(); - _md.start(); - _md.update(_opadding); - _md.update(inner); - return _md.digest(); - }; - // alias for getMac - ctx.digest = ctx.getMac; - - return ctx; -}; - -/** - * Message Digest Algorithm 5 with 128-bit digest (MD5) implementation. - * - * @author Dave Longley - * - * Copyright (c) 2010-2014 Digital Bazaar, Inc. - */ - -var forge$u = forge$D; - - - -var md5 = forge$u.md5 = forge$u.md5 || {}; -forge$u.md.md5 = forge$u.md.algorithms.md5 = md5; - -/** - * Creates an MD5 message digest object. - * - * @return a message digest object. - */ -md5.create = function() { - // do initialization as necessary - if(!_initialized$3) { - _init$3(); - } - - // MD5 state contains four 32-bit integers - var _state = null; - - // input buffer - var _input = forge$u.util.createBuffer(); - - // used for word storage - var _w = new Array(16); - - // message digest object - var md = { - algorithm: 'md5', - blockLength: 64, - digestLength: 16, - // 56-bit length of message so far (does not including padding) - messageLength: 0, - // true message length - fullMessageLength: null, - // size of message length in bytes - messageLengthSize: 8 - }; - - /** - * Starts the digest. - * - * @return this digest object. - */ - md.start = function() { - // up to 56-bit message length for convenience - md.messageLength = 0; - - // full message length (set md.messageLength64 for backwards-compatibility) - md.fullMessageLength = md.messageLength64 = []; - var int32s = md.messageLengthSize / 4; - for(var i = 0; i < int32s; ++i) { - md.fullMessageLength.push(0); - } - _input = forge$u.util.createBuffer(); - _state = { - h0: 0x67452301, - h1: 0xEFCDAB89, - h2: 0x98BADCFE, - h3: 0x10325476 - }; - return md; - }; - // start digest automatically for first time - md.start(); - - /** - * Updates the digest with the given message input. The given input can - * treated as raw input (no encoding will be applied) or an encoding of - * 'utf8' maybe given to encode the input using UTF-8. - * - * @param msg the message input to update with. - * @param encoding the encoding to use (default: 'raw', other: 'utf8'). - * - * @return this digest object. - */ - md.update = function(msg, encoding) { - if(encoding === 'utf8') { - msg = forge$u.util.encodeUtf8(msg); - } - - // update message length - var len = msg.length; - md.messageLength += len; - len = [(len / 0x100000000) >>> 0, len >>> 0]; - for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { - md.fullMessageLength[i] += len[1]; - len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0); - md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; - len[0] = (len[1] / 0x100000000) >>> 0; - } - - // add bytes to input buffer - _input.putBytes(msg); - - // process bytes - _update$3(_state, _w, _input); - - // compact input buffer every 2K or if empty - if(_input.read > 2048 || _input.length() === 0) { - _input.compact(); - } - - return md; - }; - - /** - * Produces the digest. - * - * @return a byte buffer containing the digest value. - */ - md.digest = function() { - /* Note: Here we copy the remaining bytes in the input buffer and - add the appropriate MD5 padding. Then we do the final update - on a copy of the state so that if the user wants to get - intermediate digests they can do so. */ - - /* Determine the number of bytes that must be added to the message - to ensure its length is congruent to 448 mod 512. In other words, - the data to be digested must be a multiple of 512 bits (or 128 bytes). - This data includes the message, some padding, and the length of the - message. Since the length of the message will be encoded as 8 bytes (64 - bits), that means that the last segment of the data must have 56 bytes - (448 bits) of message and padding. Therefore, the length of the message - plus the padding must be congruent to 448 mod 512 because - 512 - 128 = 448. - - In order to fill up the message length it must be filled with - padding that begins with 1 bit followed by all 0 bits. Padding - must *always* be present, so if the message length is already - congruent to 448 mod 512, then 512 padding bits must be added. */ - - var finalBlock = forge$u.util.createBuffer(); - finalBlock.putBytes(_input.bytes()); - - // compute remaining size to be digested (include message length size) - var remaining = ( - md.fullMessageLength[md.fullMessageLength.length - 1] + - md.messageLengthSize); - - // add padding for overflow blockSize - overflow - // _padding starts with 1 byte with first bit is set (byte value 128), then - // there may be up to (blockSize - 1) other pad bytes - var overflow = remaining & (md.blockLength - 1); - finalBlock.putBytes(_padding$3.substr(0, md.blockLength - overflow)); - - // serialize message length in bits in little-endian order; since length - // is stored in bytes we multiply by 8 and add carry - var bits, carry = 0; - for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { - bits = md.fullMessageLength[i] * 8 + carry; - carry = (bits / 0x100000000) >>> 0; - finalBlock.putInt32Le(bits >>> 0); - } - - var s2 = { - h0: _state.h0, - h1: _state.h1, - h2: _state.h2, - h3: _state.h3 - }; - _update$3(s2, _w, finalBlock); - var rval = forge$u.util.createBuffer(); - rval.putInt32Le(s2.h0); - rval.putInt32Le(s2.h1); - rval.putInt32Le(s2.h2); - rval.putInt32Le(s2.h3); - return rval; - }; - - return md; -}; - -// padding, constant tables for calculating md5 -var _padding$3 = null; -var _g = null; -var _r = null; -var _k$2 = null; -var _initialized$3 = false; - -/** - * Initializes the constant tables. - */ -function _init$3() { - // create padding - _padding$3 = String.fromCharCode(128); - _padding$3 += forge$u.util.fillString(String.fromCharCode(0x00), 64); - - // g values - _g = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, - 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, - 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9]; - - // rounds table - _r = [ - 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, - 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, - 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, - 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]; - - // get the result of abs(sin(i + 1)) as a 32-bit integer - _k$2 = new Array(64); - for(var i = 0; i < 64; ++i) { - _k$2[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 0x100000000); - } - - // now initialized - _initialized$3 = true; -} - -/** - * Updates an MD5 state with the given byte buffer. - * - * @param s the MD5 state to update. - * @param w the array to use to store words. - * @param bytes the byte buffer to update with. - */ -function _update$3(s, w, bytes) { - // consume 512 bit (64 byte) chunks - var t, a, b, c, d, f, r, i; - var len = bytes.length(); - while(len >= 64) { - // initialize hash value for this chunk - a = s.h0; - b = s.h1; - c = s.h2; - d = s.h3; - - // round 1 - for(i = 0; i < 16; ++i) { - w[i] = bytes.getInt32Le(); - f = d ^ (b & (c ^ d)); - t = (a + f + _k$2[i] + w[i]); - r = _r[i]; - a = d; - d = c; - c = b; - b += (t << r) | (t >>> (32 - r)); - } - // round 2 - for(; i < 32; ++i) { - f = c ^ (d & (b ^ c)); - t = (a + f + _k$2[i] + w[_g[i]]); - r = _r[i]; - a = d; - d = c; - c = b; - b += (t << r) | (t >>> (32 - r)); - } - // round 3 - for(; i < 48; ++i) { - f = b ^ c ^ d; - t = (a + f + _k$2[i] + w[_g[i]]); - r = _r[i]; - a = d; - d = c; - c = b; - b += (t << r) | (t >>> (32 - r)); - } - // round 4 - for(; i < 64; ++i) { - f = c ^ (b | ~d); - t = (a + f + _k$2[i] + w[_g[i]]); - r = _r[i]; - a = d; - d = c; - c = b; - b += (t << r) | (t >>> (32 - r)); - } - - // update hash state - s.h0 = (s.h0 + a) | 0; - s.h1 = (s.h1 + b) | 0; - s.h2 = (s.h2 + c) | 0; - s.h3 = (s.h3 + d) | 0; - - len -= 64; - } -} - -/** - * Javascript implementation of basic PEM (Privacy Enhanced Mail) algorithms. - * - * See: RFC 1421. - * - * @author Dave Longley - * - * Copyright (c) 2013-2014 Digital Bazaar, Inc. - * - * A Forge PEM object has the following fields: - * - * type: identifies the type of message (eg: "RSA PRIVATE KEY"). - * - * procType: identifies the type of processing performed on the message, - * it has two subfields: version and type, eg: 4,ENCRYPTED. - * - * contentDomain: identifies the type of content in the message, typically - * only uses the value: "RFC822". - * - * dekInfo: identifies the message encryption algorithm and mode and includes - * any parameters for the algorithm, it has two subfields: algorithm and - * parameters, eg: DES-CBC,F8143EDE5960C597. - * - * headers: contains all other PEM encapsulated headers -- where order is - * significant (for pairing data like recipient ID + key info). - * - * body: the binary-encoded body. - */ - -var forge$t = forge$D; - - -// shortcut for pem API -var pem = forge$t.pem = forge$t.pem || {}; - -/** - * Encodes (serializes) the given PEM object. - * - * @param msg the PEM message object to encode. - * @param options the options to use: - * maxline the maximum characters per line for the body, (default: 64). - * - * @return the PEM-formatted string. - */ -pem.encode = function(msg, options) { - options = options || {}; - var rval = '-----BEGIN ' + msg.type + '-----\r\n'; - - // encode special headers - var header; - if(msg.procType) { - header = { - name: 'Proc-Type', - values: [String(msg.procType.version), msg.procType.type] - }; - rval += foldHeader(header); - } - if(msg.contentDomain) { - header = {name: 'Content-Domain', values: [msg.contentDomain]}; - rval += foldHeader(header); - } - if(msg.dekInfo) { - header = {name: 'DEK-Info', values: [msg.dekInfo.algorithm]}; - if(msg.dekInfo.parameters) { - header.values.push(msg.dekInfo.parameters); - } - rval += foldHeader(header); - } - - if(msg.headers) { - // encode all other headers - for(var i = 0; i < msg.headers.length; ++i) { - rval += foldHeader(msg.headers[i]); - } - } - - // terminate header - if(msg.procType) { - rval += '\r\n'; - } - - // add body - rval += forge$t.util.encode64(msg.body, options.maxline || 64) + '\r\n'; - - rval += '-----END ' + msg.type + '-----\r\n'; - return rval; -}; - -/** - * Decodes (deserializes) all PEM messages found in the given string. - * - * @param str the PEM-formatted string to decode. - * - * @return the PEM message objects in an array. - */ -pem.decode = function(str) { - var rval = []; - - // split string into PEM messages (be lenient w/EOF on BEGIN line) - var rMessage = /\s*-----BEGIN ([A-Z0-9- ]+)-----\r?\n?([\x21-\x7e\s]+?(?:\r?\n\r?\n))?([:A-Za-z0-9+\/=\s]+?)-----END \1-----/g; - var rHeader = /([\x21-\x7e]+):\s*([\x21-\x7e\s^:]+)/; - var rCRLF = /\r?\n/; - var match; - while(true) { - match = rMessage.exec(str); - if(!match) { - break; - } - - // accept "NEW CERTIFICATE REQUEST" as "CERTIFICATE REQUEST" - // https://datatracker.ietf.org/doc/html/rfc7468#section-7 - var type = match[1]; - if(type === 'NEW CERTIFICATE REQUEST') { - type = 'CERTIFICATE REQUEST'; - } - - var msg = { - type: type, - procType: null, - contentDomain: null, - dekInfo: null, - headers: [], - body: forge$t.util.decode64(match[3]) - }; - rval.push(msg); - - // no headers - if(!match[2]) { - continue; - } - - // parse headers - var lines = match[2].split(rCRLF); - var li = 0; - while(match && li < lines.length) { - // get line, trim any rhs whitespace - var line = lines[li].replace(/\s+$/, ''); - - // RFC2822 unfold any following folded lines - for(var nl = li + 1; nl < lines.length; ++nl) { - var next = lines[nl]; - if(!/\s/.test(next[0])) { - break; - } - line += next; - li = nl; - } - - // parse header - match = line.match(rHeader); - if(match) { - var header = {name: match[1], values: []}; - var values = match[2].split(','); - for(var vi = 0; vi < values.length; ++vi) { - header.values.push(ltrim(values[vi])); - } - - // Proc-Type must be the first header - if(!msg.procType) { - if(header.name !== 'Proc-Type') { - throw new Error('Invalid PEM formatted message. The first ' + - 'encapsulated header must be "Proc-Type".'); - } else if(header.values.length !== 2) { - throw new Error('Invalid PEM formatted message. The "Proc-Type" ' + - 'header must have two subfields.'); - } - msg.procType = {version: values[0], type: values[1]}; - } else if(!msg.contentDomain && header.name === 'Content-Domain') { - // special-case Content-Domain - msg.contentDomain = values[0] || ''; - } else if(!msg.dekInfo && header.name === 'DEK-Info') { - // special-case DEK-Info - if(header.values.length === 0) { - throw new Error('Invalid PEM formatted message. The "DEK-Info" ' + - 'header must have at least one subfield.'); - } - msg.dekInfo = {algorithm: values[0], parameters: values[1] || null}; - } else { - msg.headers.push(header); - } - } - - ++li; - } - - if(msg.procType === 'ENCRYPTED' && !msg.dekInfo) { - throw new Error('Invalid PEM formatted message. The "DEK-Info" ' + - 'header must be present if "Proc-Type" is "ENCRYPTED".'); - } - } - - if(rval.length === 0) { - throw new Error('Invalid PEM formatted message.'); - } - - return rval; -}; - -function foldHeader(header) { - var rval = header.name + ': '; - - // ensure values with CRLF are folded - var values = []; - var insertSpace = function(match, $1) { - return ' ' + $1; - }; - for(var i = 0; i < header.values.length; ++i) { - values.push(header.values[i].replace(/^(\S+\r\n)/, insertSpace)); - } - rval += values.join(',') + '\r\n'; - - // do folding - var length = 0; - var candidate = -1; - for(var i = 0; i < rval.length; ++i, ++length) { - if(length > 65 && candidate !== -1) { - var insert = rval[candidate]; - if(insert === ',') { - ++candidate; - rval = rval.substr(0, candidate) + '\r\n ' + rval.substr(candidate); - } else { - rval = rval.substr(0, candidate) + - '\r\n' + insert + rval.substr(candidate + 1); - } - length = (i - candidate - 1); - candidate = -1; - ++i; - } else if(rval[i] === ' ' || rval[i] === '\t' || rval[i] === ',') { - candidate = i; - } - } - - return rval; -} - -function ltrim(str) { - return str.replace(/^\s+/, ''); -} - -/** - * DES (Data Encryption Standard) implementation. - * - * This implementation supports DES as well as 3DES-EDE in ECB and CBC mode. - * It is based on the BSD-licensed implementation by Paul Tero: - * - * Paul Tero, July 2001 - * http://www.tero.co.uk/des/ - * - * Optimised for performance with large blocks by - * Michael Hayworth, November 2001 - * http://www.netdealing.com - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @author Stefan Siegl - * @author Dave Longley - * - * Copyright (c) 2012 Stefan Siegl - * Copyright (c) 2012-2014 Digital Bazaar, Inc. - */ - -var forge$s = forge$D; - - - - -/* DES API */ -forge$s.des = forge$s.des || {}; - -/** - * Deprecated. Instead, use: - * - * var cipher = forge.cipher.createCipher('DES-', key); - * cipher.start({iv: iv}); - * - * Creates an DES cipher object to encrypt data using the given symmetric key. - * The output will be stored in the 'output' member of the returned cipher. - * - * The key and iv may be given as binary-encoded strings of bytes or - * byte buffers. - * - * @param key the symmetric key to use (64 or 192 bits). - * @param iv the initialization vector to use. - * @param output the buffer to write to, null to create one. - * @param mode the cipher mode to use (default: 'CBC' if IV is - * given, 'ECB' if null). - * - * @return the cipher. - */ -forge$s.des.startEncrypting = function(key, iv, output, mode) { - var cipher = _createCipher({ - key: key, - output: output, - decrypt: false, - mode: mode || (iv === null ? 'ECB' : 'CBC') - }); - cipher.start(iv); - return cipher; -}; - -/** - * Deprecated. Instead, use: - * - * var cipher = forge.cipher.createCipher('DES-', key); - * - * Creates an DES cipher object to encrypt data using the given symmetric key. - * - * The key may be given as a binary-encoded string of bytes or a byte buffer. - * - * @param key the symmetric key to use (64 or 192 bits). - * @param mode the cipher mode to use (default: 'CBC'). - * - * @return the cipher. - */ -forge$s.des.createEncryptionCipher = function(key, mode) { - return _createCipher({ - key: key, - output: null, - decrypt: false, - mode: mode - }); -}; - -/** - * Deprecated. Instead, use: - * - * var decipher = forge.cipher.createDecipher('DES-', key); - * decipher.start({iv: iv}); - * - * Creates an DES cipher object to decrypt data using the given symmetric key. - * The output will be stored in the 'output' member of the returned cipher. - * - * The key and iv may be given as binary-encoded strings of bytes or - * byte buffers. - * - * @param key the symmetric key to use (64 or 192 bits). - * @param iv the initialization vector to use. - * @param output the buffer to write to, null to create one. - * @param mode the cipher mode to use (default: 'CBC' if IV is - * given, 'ECB' if null). - * - * @return the cipher. - */ -forge$s.des.startDecrypting = function(key, iv, output, mode) { - var cipher = _createCipher({ - key: key, - output: output, - decrypt: true, - mode: mode || (iv === null ? 'ECB' : 'CBC') - }); - cipher.start(iv); - return cipher; -}; - -/** - * Deprecated. Instead, use: - * - * var decipher = forge.cipher.createDecipher('DES-', key); - * - * Creates an DES cipher object to decrypt data using the given symmetric key. - * - * The key may be given as a binary-encoded string of bytes or a byte buffer. - * - * @param key the symmetric key to use (64 or 192 bits). - * @param mode the cipher mode to use (default: 'CBC'). - * - * @return the cipher. - */ -forge$s.des.createDecryptionCipher = function(key, mode) { - return _createCipher({ - key: key, - output: null, - decrypt: true, - mode: mode - }); -}; - -/** - * Creates a new DES cipher algorithm object. - * - * @param name the name of the algorithm. - * @param mode the mode factory function. - * - * @return the DES algorithm object. - */ -forge$s.des.Algorithm = function(name, mode) { - var self = this; - self.name = name; - self.mode = new mode({ - blockSize: 8, - cipher: { - encrypt: function(inBlock, outBlock) { - return _updateBlock(self._keys, inBlock, outBlock, false); - }, - decrypt: function(inBlock, outBlock) { - return _updateBlock(self._keys, inBlock, outBlock, true); - } - } - }); - self._init = false; -}; - -/** - * Initializes this DES algorithm by expanding its key. - * - * @param options the options to use. - * key the key to use with this algorithm. - * decrypt true if the algorithm should be initialized for decryption, - * false for encryption. - */ -forge$s.des.Algorithm.prototype.initialize = function(options) { - if(this._init) { - return; - } - - var key = forge$s.util.createBuffer(options.key); - if(this.name.indexOf('3DES') === 0) { - if(key.length() !== 24) { - throw new Error('Invalid Triple-DES key size: ' + key.length() * 8); - } - } - - // do key expansion to 16 or 48 subkeys (single or triple DES) - this._keys = _createKeys(key); - this._init = true; -}; - -/** Register DES algorithms **/ - -registerAlgorithm('DES-ECB', forge$s.cipher.modes.ecb); -registerAlgorithm('DES-CBC', forge$s.cipher.modes.cbc); -registerAlgorithm('DES-CFB', forge$s.cipher.modes.cfb); -registerAlgorithm('DES-OFB', forge$s.cipher.modes.ofb); -registerAlgorithm('DES-CTR', forge$s.cipher.modes.ctr); - -registerAlgorithm('3DES-ECB', forge$s.cipher.modes.ecb); -registerAlgorithm('3DES-CBC', forge$s.cipher.modes.cbc); -registerAlgorithm('3DES-CFB', forge$s.cipher.modes.cfb); -registerAlgorithm('3DES-OFB', forge$s.cipher.modes.ofb); -registerAlgorithm('3DES-CTR', forge$s.cipher.modes.ctr); - -function registerAlgorithm(name, mode) { - var factory = function() { - return new forge$s.des.Algorithm(name, mode); - }; - forge$s.cipher.registerAlgorithm(name, factory); -} - -/** DES implementation **/ - -var spfunction1 = [0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004]; -var spfunction2 = [-0x7fef7fe0,-0x7fff8000,0x8000,0x108020,0x100000,0x20,-0x7fefffe0,-0x7fff7fe0,-0x7fffffe0,-0x7fef7fe0,-0x7fef8000,-0x80000000,-0x7fff8000,0x100000,0x20,-0x7fefffe0,0x108000,0x100020,-0x7fff7fe0,0,-0x80000000,0x8000,0x108020,-0x7ff00000,0x100020,-0x7fffffe0,0,0x108000,0x8020,-0x7fef8000,-0x7ff00000,0x8020,0,0x108020,-0x7fefffe0,0x100000,-0x7fff7fe0,-0x7ff00000,-0x7fef8000,0x8000,-0x7ff00000,-0x7fff8000,0x20,-0x7fef7fe0,0x108020,0x20,0x8000,-0x80000000,0x8020,-0x7fef8000,0x100000,-0x7fffffe0,0x100020,-0x7fff7fe0,-0x7fffffe0,0x100020,0x108000,0,-0x7fff8000,0x8020,-0x80000000,-0x7fefffe0,-0x7fef7fe0,0x108000]; -var spfunction3 = [0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200]; -var spfunction4 = [0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080]; -var spfunction5 = [0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100]; -var spfunction6 = [0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010]; -var spfunction7 = [0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002]; -var spfunction8 = [0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000]; - -/** - * Create necessary sub keys. - * - * @param key the 64-bit or 192-bit key. - * - * @return the expanded keys. - */ -function _createKeys(key) { - var pc2bytes0 = [0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204], - pc2bytes1 = [0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101], - pc2bytes2 = [0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808], - pc2bytes3 = [0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000], - pc2bytes4 = [0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010], - pc2bytes5 = [0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420], - pc2bytes6 = [0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002], - pc2bytes7 = [0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800], - pc2bytes8 = [0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002], - pc2bytes9 = [0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408], - pc2bytes10 = [0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020], - pc2bytes11 = [0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200], - pc2bytes12 = [0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010], - pc2bytes13 = [0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105]; - - // how many iterations (1 for des, 3 for triple des) - // changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys - var iterations = key.length() > 8 ? 3 : 1; - - // stores the return keys - var keys = []; - - // now define the left shifts which need to be done - var shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0]; - - var n = 0, tmp; - for(var j = 0; j < iterations; j++) { - var left = key.getInt32(); - var right = key.getInt32(); - - tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= tmp; - left ^= (tmp << 4); - - tmp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= tmp; - right ^= (tmp << -16); - - tmp = ((left >>> 2) ^ right) & 0x33333333; - right ^= tmp; - left ^= (tmp << 2); - - tmp = ((right >>> -16) ^ left) & 0x0000ffff; - left ^= tmp; - right ^= (tmp << -16); - - tmp = ((left >>> 1) ^ right) & 0x55555555; - right ^= tmp; - left ^= (tmp << 1); - - tmp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= tmp; - right ^= (tmp << 8); - - tmp = ((left >>> 1) ^ right) & 0x55555555; - right ^= tmp; - left ^= (tmp << 1); - - // right needs to be shifted and OR'd with last four bits of left - tmp = (left << 8) | ((right >>> 20) & 0x000000f0); - - // left needs to be put upside down - left = ((right << 24) | ((right << 8) & 0xff0000) | - ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0)); - right = tmp; - - // now go through and perform these shifts on the left and right keys - for(var i = 0; i < shifts.length; ++i) { - //shift the keys either one or two bits to the left - if(shifts[i]) { - left = (left << 2) | (left >>> 26); - right = (right << 2) | (right >>> 26); - } else { - left = (left << 1) | (left >>> 27); - right = (right << 1) | (right >>> 27); - } - left &= -0xf; - right &= -0xf; - - // now apply PC-2, in such a way that E is easier when encrypting or - // decrypting this conversion will look like PC-2 except only the last 6 - // bits of each byte are used rather than 48 consecutive bits and the - // order of lines will be according to how the S selection functions will - // be applied: S2, S4, S6, S8, S1, S3, S5, S7 - var lefttmp = ( - pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] | - pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf] | - pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] | - pc2bytes6[(left >>> 4) & 0xf]); - var righttmp = ( - pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] | - pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf] | - pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] | - pc2bytes13[(right >>> 4) & 0xf]); - tmp = ((righttmp >>> 16) ^ lefttmp) & 0x0000ffff; - keys[n++] = lefttmp ^ tmp; - keys[n++] = righttmp ^ (tmp << 16); - } - } - - return keys; -} - -/** - * Updates a single block (1 byte) using DES. The update will either - * encrypt or decrypt the block. - * - * @param keys the expanded keys. - * @param input the input block (an array of 32-bit words). - * @param output the updated output block. - * @param decrypt true to decrypt the block, false to encrypt it. - */ -function _updateBlock(keys, input, output, decrypt) { - // set up loops for single or triple DES - var iterations = keys.length === 32 ? 3 : 9; - var looping; - if(iterations === 3) { - looping = decrypt ? [30, -2, -2] : [0, 32, 2]; - } else { - looping = (decrypt ? - [94, 62, -2, 32, 64, 2, 30, -2, -2] : - [0, 32, 2, 62, 30, -2, 64, 96, 2]); - } - - var tmp; - - var left = input[0]; - var right = input[1]; - - // first each 64 bit chunk of the message must be permuted according to IP - tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= tmp; - left ^= (tmp << 4); - - tmp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= tmp; - left ^= (tmp << 16); - - tmp = ((right >>> 2) ^ left) & 0x33333333; - left ^= tmp; - right ^= (tmp << 2); - - tmp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= tmp; - right ^= (tmp << 8); - - tmp = ((left >>> 1) ^ right) & 0x55555555; - right ^= tmp; - left ^= (tmp << 1); - - // rotate left 1 bit - left = ((left << 1) | (left >>> 31)); - right = ((right << 1) | (right >>> 31)); - - for(var j = 0; j < iterations; j += 3) { - var endloop = looping[j + 1]; - var loopinc = looping[j + 2]; - - // now go through and perform the encryption or decryption - for(var i = looping[j]; i != endloop; i += loopinc) { - var right1 = right ^ keys[i]; - var right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1]; - - // passing these bytes through the S selection functions - tmp = left; - left = right; - right = tmp ^ ( - spfunction2[(right1 >>> 24) & 0x3f] | - spfunction4[(right1 >>> 16) & 0x3f] | - spfunction6[(right1 >>> 8) & 0x3f] | - spfunction8[right1 & 0x3f] | - spfunction1[(right2 >>> 24) & 0x3f] | - spfunction3[(right2 >>> 16) & 0x3f] | - spfunction5[(right2 >>> 8) & 0x3f] | - spfunction7[right2 & 0x3f]); - } - // unreverse left and right - tmp = left; - left = right; - right = tmp; - } - - // rotate right 1 bit - left = ((left >>> 1) | (left << 31)); - right = ((right >>> 1) | (right << 31)); - - // now perform IP-1, which is IP in the opposite direction - tmp = ((left >>> 1) ^ right) & 0x55555555; - right ^= tmp; - left ^= (tmp << 1); - - tmp = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= tmp; - right ^= (tmp << 8); - - tmp = ((right >>> 2) ^ left) & 0x33333333; - left ^= tmp; - right ^= (tmp << 2); - - tmp = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= tmp; - left ^= (tmp << 16); - - tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= tmp; - left ^= (tmp << 4); - - output[0] = left; - output[1] = right; -} - -/** - * Deprecated. Instead, use: - * - * forge.cipher.createCipher('DES-', key); - * forge.cipher.createDecipher('DES-', key); - * - * Creates a deprecated DES cipher object. This object's mode will default to - * CBC (cipher-block-chaining). - * - * The key may be given as a binary-encoded string of bytes or a byte buffer. - * - * @param options the options to use. - * key the symmetric key to use (64 or 192 bits). - * output the buffer to write to. - * decrypt true for decryption, false for encryption. - * mode the cipher mode to use (default: 'CBC'). - * - * @return the cipher. - */ -function _createCipher(options) { - options = options || {}; - var mode = (options.mode || 'CBC').toUpperCase(); - var algorithm = 'DES-' + mode; - - var cipher; - if(options.decrypt) { - cipher = forge$s.cipher.createDecipher(algorithm, options.key); - } else { - cipher = forge$s.cipher.createCipher(algorithm, options.key); - } - - // backwards compatible start API - var start = cipher.start; - cipher.start = function(iv, options) { - // backwards compatibility: support second arg as output buffer - var output = null; - if(options instanceof forge$s.util.ByteBuffer) { - output = options; - options = {}; - } - options = options || {}; - options.output = output; - options.iv = iv; - start.call(cipher, options); - }; - - return cipher; -} - -/** - * Password-Based Key-Derivation Function #2 implementation. - * - * See RFC 2898 for details. - * - * @author Dave Longley - * - * Copyright (c) 2010-2013 Digital Bazaar, Inc. - */ - -var forge$r = forge$D; - - - - -var pkcs5 = forge$r.pkcs5 = forge$r.pkcs5 || {}; - -var crypto; -if(forge$r.util.isNodejs && !forge$r.options.usePureJavaScript) { - crypto = require$$1$1; -} - -/** - * Derives a key from a password. - * - * @param p the password as a binary-encoded string of bytes. - * @param s the salt as a binary-encoded string of bytes. - * @param c the iteration count, a positive integer. - * @param dkLen the intended length, in bytes, of the derived key, - * (max: 2^32 - 1) * hash length of the PRF. - * @param [md] the message digest (or algorithm identifier as a string) to use - * in the PRF, defaults to SHA-1. - * @param [callback(err, key)] presence triggers asynchronous version, called - * once the operation completes. - * - * @return the derived key, as a binary-encoded string of bytes, for the - * synchronous version (if no callback is specified). - */ -forge$r.pbkdf2 = pkcs5.pbkdf2 = function( - p, s, c, dkLen, md, callback) { - if(typeof md === 'function') { - callback = md; - md = null; - } - - // use native implementation if possible and not disabled, note that - // some node versions only support SHA-1, others allow digest to be changed - if(forge$r.util.isNodejs && !forge$r.options.usePureJavaScript && - crypto.pbkdf2 && (md === null || typeof md !== 'object') && - (crypto.pbkdf2Sync.length > 4 || (!md || md === 'sha1'))) { - if(typeof md !== 'string') { - // default prf to SHA-1 - md = 'sha1'; - } - p = Buffer.from(p, 'binary'); - s = Buffer.from(s, 'binary'); - if(!callback) { - if(crypto.pbkdf2Sync.length === 4) { - return crypto.pbkdf2Sync(p, s, c, dkLen).toString('binary'); - } - return crypto.pbkdf2Sync(p, s, c, dkLen, md).toString('binary'); - } - if(crypto.pbkdf2Sync.length === 4) { - return crypto.pbkdf2(p, s, c, dkLen, function(err, key) { - if(err) { - return callback(err); - } - callback(null, key.toString('binary')); - }); - } - return crypto.pbkdf2(p, s, c, dkLen, md, function(err, key) { - if(err) { - return callback(err); - } - callback(null, key.toString('binary')); - }); - } - - if(typeof md === 'undefined' || md === null) { - // default prf to SHA-1 - md = 'sha1'; - } - if(typeof md === 'string') { - if(!(md in forge$r.md.algorithms)) { - throw new Error('Unknown hash algorithm: ' + md); - } - md = forge$r.md[md].create(); - } - - var hLen = md.digestLength; - - /* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and - stop. */ - if(dkLen > (0xFFFFFFFF * hLen)) { - var err = new Error('Derived key is too long.'); - if(callback) { - return callback(err); - } - throw err; - } - - /* 2. Let len be the number of hLen-octet blocks in the derived key, - rounding up, and let r be the number of octets in the last - block: - - len = CEIL(dkLen / hLen), - r = dkLen - (len - 1) * hLen. */ - var len = Math.ceil(dkLen / hLen); - var r = dkLen - (len - 1) * hLen; - - /* 3. For each block of the derived key apply the function F defined - below to the password P, the salt S, the iteration count c, and - the block index to compute the block: - - T_1 = F(P, S, c, 1), - T_2 = F(P, S, c, 2), - ... - T_len = F(P, S, c, len), - - where the function F is defined as the exclusive-or sum of the - first c iterates of the underlying pseudorandom function PRF - applied to the password P and the concatenation of the salt S - and the block index i: - - F(P, S, c, i) = u_1 XOR u_2 XOR ... XOR u_c - - where - - u_1 = PRF(P, S || INT(i)), - u_2 = PRF(P, u_1), - ... - u_c = PRF(P, u_{c-1}). - - Here, INT(i) is a four-octet encoding of the integer i, most - significant octet first. */ - var prf = forge$r.hmac.create(); - prf.start(md, p); - var dk = ''; - var xor, u_c, u_c1; - - // sync version - if(!callback) { - for(var i = 1; i <= len; ++i) { - // PRF(P, S || INT(i)) (first iteration) - prf.start(null, null); - prf.update(s); - prf.update(forge$r.util.int32ToBytes(i)); - xor = u_c1 = prf.digest().getBytes(); - - // PRF(P, u_{c-1}) (other iterations) - for(var j = 2; j <= c; ++j) { - prf.start(null, null); - prf.update(u_c1); - u_c = prf.digest().getBytes(); - // F(p, s, c, i) - xor = forge$r.util.xorBytes(xor, u_c, hLen); - u_c1 = u_c; - } - - /* 4. Concatenate the blocks and extract the first dkLen octets to - produce a derived key DK: - - DK = T_1 || T_2 || ... || T_len<0..r-1> */ - dk += (i < len) ? xor : xor.substr(0, r); - } - /* 5. Output the derived key DK. */ - return dk; - } - - // async version - var i = 1, j; - function outer() { - if(i > len) { - // done - return callback(null, dk); - } - - // PRF(P, S || INT(i)) (first iteration) - prf.start(null, null); - prf.update(s); - prf.update(forge$r.util.int32ToBytes(i)); - xor = u_c1 = prf.digest().getBytes(); - - // PRF(P, u_{c-1}) (other iterations) - j = 2; - inner(); - } - - function inner() { - if(j <= c) { - prf.start(null, null); - prf.update(u_c1); - u_c = prf.digest().getBytes(); - // F(p, s, c, i) - xor = forge$r.util.xorBytes(xor, u_c, hLen); - u_c1 = u_c; - ++j; - return forge$r.util.setImmediate(inner); - } - - /* 4. Concatenate the blocks and extract the first dkLen octets to - produce a derived key DK: - - DK = T_1 || T_2 || ... || T_len<0..r-1> */ - dk += (i < len) ? xor : xor.substr(0, r); - - ++i; - outer(); - } - - outer(); -}; - -/** - * Secure Hash Algorithm with 256-bit digest (SHA-256) implementation. - * - * See FIPS 180-2 for details. - * - * @author Dave Longley - * - * Copyright (c) 2010-2015 Digital Bazaar, Inc. - */ - -var forge$q = forge$D; - - - -var sha256 = forge$q.sha256 = forge$q.sha256 || {}; -forge$q.md.sha256 = forge$q.md.algorithms.sha256 = sha256; - -/** - * Creates a SHA-256 message digest object. - * - * @return a message digest object. - */ -sha256.create = function() { - // do initialization as necessary - if(!_initialized$2) { - _init$2(); - } - - // SHA-256 state contains eight 32-bit integers - var _state = null; - - // input buffer - var _input = forge$q.util.createBuffer(); - - // used for word storage - var _w = new Array(64); - - // message digest object - var md = { - algorithm: 'sha256', - blockLength: 64, - digestLength: 32, - // 56-bit length of message so far (does not including padding) - messageLength: 0, - // true message length - fullMessageLength: null, - // size of message length in bytes - messageLengthSize: 8 - }; - - /** - * Starts the digest. - * - * @return this digest object. - */ - md.start = function() { - // up to 56-bit message length for convenience - md.messageLength = 0; - - // full message length (set md.messageLength64 for backwards-compatibility) - md.fullMessageLength = md.messageLength64 = []; - var int32s = md.messageLengthSize / 4; - for(var i = 0; i < int32s; ++i) { - md.fullMessageLength.push(0); - } - _input = forge$q.util.createBuffer(); - _state = { - h0: 0x6A09E667, - h1: 0xBB67AE85, - h2: 0x3C6EF372, - h3: 0xA54FF53A, - h4: 0x510E527F, - h5: 0x9B05688C, - h6: 0x1F83D9AB, - h7: 0x5BE0CD19 - }; - return md; - }; - // start digest automatically for first time - md.start(); - - /** - * Updates the digest with the given message input. The given input can - * treated as raw input (no encoding will be applied) or an encoding of - * 'utf8' maybe given to encode the input using UTF-8. - * - * @param msg the message input to update with. - * @param encoding the encoding to use (default: 'raw', other: 'utf8'). - * - * @return this digest object. - */ - md.update = function(msg, encoding) { - if(encoding === 'utf8') { - msg = forge$q.util.encodeUtf8(msg); - } - - // update message length - var len = msg.length; - md.messageLength += len; - len = [(len / 0x100000000) >>> 0, len >>> 0]; - for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { - md.fullMessageLength[i] += len[1]; - len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0); - md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; - len[0] = ((len[1] / 0x100000000) >>> 0); - } - - // add bytes to input buffer - _input.putBytes(msg); - - // process bytes - _update$2(_state, _w, _input); - - // compact input buffer every 2K or if empty - if(_input.read > 2048 || _input.length() === 0) { - _input.compact(); - } - - return md; - }; - - /** - * Produces the digest. - * - * @return a byte buffer containing the digest value. - */ - md.digest = function() { - /* Note: Here we copy the remaining bytes in the input buffer and - add the appropriate SHA-256 padding. Then we do the final update - on a copy of the state so that if the user wants to get - intermediate digests they can do so. */ - - /* Determine the number of bytes that must be added to the message - to ensure its length is congruent to 448 mod 512. In other words, - the data to be digested must be a multiple of 512 bits (or 128 bytes). - This data includes the message, some padding, and the length of the - message. Since the length of the message will be encoded as 8 bytes (64 - bits), that means that the last segment of the data must have 56 bytes - (448 bits) of message and padding. Therefore, the length of the message - plus the padding must be congruent to 448 mod 512 because - 512 - 128 = 448. - - In order to fill up the message length it must be filled with - padding that begins with 1 bit followed by all 0 bits. Padding - must *always* be present, so if the message length is already - congruent to 448 mod 512, then 512 padding bits must be added. */ - - var finalBlock = forge$q.util.createBuffer(); - finalBlock.putBytes(_input.bytes()); - - // compute remaining size to be digested (include message length size) - var remaining = ( - md.fullMessageLength[md.fullMessageLength.length - 1] + - md.messageLengthSize); - - // add padding for overflow blockSize - overflow - // _padding starts with 1 byte with first bit is set (byte value 128), then - // there may be up to (blockSize - 1) other pad bytes - var overflow = remaining & (md.blockLength - 1); - finalBlock.putBytes(_padding$2.substr(0, md.blockLength - overflow)); - - // serialize message length in bits in big-endian order; since length - // is stored in bytes we multiply by 8 and add carry from next int - var next, carry; - var bits = md.fullMessageLength[0] * 8; - for(var i = 0; i < md.fullMessageLength.length - 1; ++i) { - next = md.fullMessageLength[i + 1] * 8; - carry = (next / 0x100000000) >>> 0; - bits += carry; - finalBlock.putInt32(bits >>> 0); - bits = next >>> 0; - } - finalBlock.putInt32(bits); - - var s2 = { - h0: _state.h0, - h1: _state.h1, - h2: _state.h2, - h3: _state.h3, - h4: _state.h4, - h5: _state.h5, - h6: _state.h6, - h7: _state.h7 - }; - _update$2(s2, _w, finalBlock); - var rval = forge$q.util.createBuffer(); - rval.putInt32(s2.h0); - rval.putInt32(s2.h1); - rval.putInt32(s2.h2); - rval.putInt32(s2.h3); - rval.putInt32(s2.h4); - rval.putInt32(s2.h5); - rval.putInt32(s2.h6); - rval.putInt32(s2.h7); - return rval; - }; - - return md; -}; - -// sha-256 padding bytes not initialized yet -var _padding$2 = null; -var _initialized$2 = false; - -// table of constants -var _k$1 = null; - -/** - * Initializes the constant tables. - */ -function _init$2() { - // create padding - _padding$2 = String.fromCharCode(128); - _padding$2 += forge$q.util.fillString(String.fromCharCode(0x00), 64); - - // create K table for SHA-256 - _k$1 = [ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; - - // now initialized - _initialized$2 = true; -} - -/** - * Updates a SHA-256 state with the given byte buffer. - * - * @param s the SHA-256 state to update. - * @param w the array to use to store words. - * @param bytes the byte buffer to update with. - */ -function _update$2(s, w, bytes) { - // consume 512 bit (64 byte) chunks - var t1, t2, s0, s1, ch, maj, i, a, b, c, d, e, f, g, h; - var len = bytes.length(); - while(len >= 64) { - // the w array will be populated with sixteen 32-bit big-endian words - // and then extended into 64 32-bit words according to SHA-256 - for(i = 0; i < 16; ++i) { - w[i] = bytes.getInt32(); - } - for(; i < 64; ++i) { - // XOR word 2 words ago rot right 17, rot right 19, shft right 10 - t1 = w[i - 2]; - t1 = - ((t1 >>> 17) | (t1 << 15)) ^ - ((t1 >>> 19) | (t1 << 13)) ^ - (t1 >>> 10); - // XOR word 15 words ago rot right 7, rot right 18, shft right 3 - t2 = w[i - 15]; - t2 = - ((t2 >>> 7) | (t2 << 25)) ^ - ((t2 >>> 18) | (t2 << 14)) ^ - (t2 >>> 3); - // sum(t1, word 7 ago, t2, word 16 ago) modulo 2^32 - w[i] = (t1 + w[i - 7] + t2 + w[i - 16]) | 0; - } - - // initialize hash value for this chunk - a = s.h0; - b = s.h1; - c = s.h2; - d = s.h3; - e = s.h4; - f = s.h5; - g = s.h6; - h = s.h7; - - // round function - for(i = 0; i < 64; ++i) { - // Sum1(e) - s1 = - ((e >>> 6) | (e << 26)) ^ - ((e >>> 11) | (e << 21)) ^ - ((e >>> 25) | (e << 7)); - // Ch(e, f, g) (optimized the same way as SHA-1) - ch = g ^ (e & (f ^ g)); - // Sum0(a) - s0 = - ((a >>> 2) | (a << 30)) ^ - ((a >>> 13) | (a << 19)) ^ - ((a >>> 22) | (a << 10)); - // Maj(a, b, c) (optimized the same way as SHA-1) - maj = (a & b) | (c & (a ^ b)); - - // main algorithm - t1 = h + s1 + ch + _k$1[i] + w[i]; - t2 = s0 + maj; - h = g; - g = f; - f = e; - // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug - // can't truncate with `| 0` - e = (d + t1) >>> 0; - d = c; - c = b; - b = a; - // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug - // can't truncate with `| 0` - a = (t1 + t2) >>> 0; - } - - // update hash state - s.h0 = (s.h0 + a) | 0; - s.h1 = (s.h1 + b) | 0; - s.h2 = (s.h2 + c) | 0; - s.h3 = (s.h3 + d) | 0; - s.h4 = (s.h4 + e) | 0; - s.h5 = (s.h5 + f) | 0; - s.h6 = (s.h6 + g) | 0; - s.h7 = (s.h7 + h) | 0; - len -= 64; - } -} - -/** - * A javascript implementation of a cryptographically-secure - * Pseudo Random Number Generator (PRNG). The Fortuna algorithm is followed - * here though the use of SHA-256 is not enforced; when generating an - * a PRNG context, the hashing algorithm and block cipher used for - * the generator are specified via a plugin. - * - * @author Dave Longley - * - * Copyright (c) 2010-2014 Digital Bazaar, Inc. - */ - -var forge$p = forge$D; - - -var _crypto$1 = null; -if(forge$p.util.isNodejs && !forge$p.options.usePureJavaScript && - !process.versions['node-webkit']) { - _crypto$1 = require$$1$1; -} - -/* PRNG API */ -var prng = forge$p.prng = forge$p.prng || {}; - -/** - * Creates a new PRNG context. - * - * A PRNG plugin must be passed in that will provide: - * - * 1. A function that initializes the key and seed of a PRNG context. It - * will be given a 16 byte key and a 16 byte seed. Any key expansion - * or transformation of the seed from a byte string into an array of - * integers (or similar) should be performed. - * 2. The cryptographic function used by the generator. It takes a key and - * a seed. - * 3. A seed increment function. It takes the seed and returns seed + 1. - * 4. An api to create a message digest. - * - * For an example, see random.js. - * - * @param plugin the PRNG plugin to use. - */ -prng.create = function(plugin) { - var ctx = { - plugin: plugin, - key: null, - seed: null, - time: null, - // number of reseeds so far - reseeds: 0, - // amount of data generated so far - generated: 0, - // no initial key bytes - keyBytes: '' - }; - - // create 32 entropy pools (each is a message digest) - var md = plugin.md; - var pools = new Array(32); - for(var i = 0; i < 32; ++i) { - pools[i] = md.create(); - } - ctx.pools = pools; - - // entropy pools are written to cyclically, starting at index 0 - ctx.pool = 0; - - /** - * Generates random bytes. The bytes may be generated synchronously or - * asynchronously. Web workers must use the asynchronous interface or - * else the behavior is undefined. - * - * @param count the number of random bytes to generate. - * @param [callback(err, bytes)] called once the operation completes. - * - * @return count random bytes as a string. - */ - ctx.generate = function(count, callback) { - // do synchronously - if(!callback) { - return ctx.generateSync(count); - } - - // simple generator using counter-based CBC - var cipher = ctx.plugin.cipher; - var increment = ctx.plugin.increment; - var formatKey = ctx.plugin.formatKey; - var formatSeed = ctx.plugin.formatSeed; - var b = forge$p.util.createBuffer(); - - // paranoid deviation from Fortuna: - // reset key for every request to protect previously - // generated random bytes should the key be discovered; - // there is no 100ms based reseeding because of this - // forced reseed for every `generate` call - ctx.key = null; - - generate(); - - function generate(err) { - if(err) { - return callback(err); - } - - // sufficient bytes generated - if(b.length() >= count) { - return callback(null, b.getBytes(count)); - } - - // if amount of data generated is greater than 1 MiB, trigger reseed - if(ctx.generated > 0xfffff) { - ctx.key = null; - } - - if(ctx.key === null) { - // prevent stack overflow - return forge$p.util.nextTick(function() { - _reseed(generate); - }); - } - - // generate the random bytes - var bytes = cipher(ctx.key, ctx.seed); - ctx.generated += bytes.length; - b.putBytes(bytes); - - // generate bytes for a new key and seed - ctx.key = formatKey(cipher(ctx.key, increment(ctx.seed))); - ctx.seed = formatSeed(cipher(ctx.key, ctx.seed)); - - forge$p.util.setImmediate(generate); - } - }; - - /** - * Generates random bytes synchronously. - * - * @param count the number of random bytes to generate. - * - * @return count random bytes as a string. - */ - ctx.generateSync = function(count) { - // simple generator using counter-based CBC - var cipher = ctx.plugin.cipher; - var increment = ctx.plugin.increment; - var formatKey = ctx.plugin.formatKey; - var formatSeed = ctx.plugin.formatSeed; - - // paranoid deviation from Fortuna: - // reset key for every request to protect previously - // generated random bytes should the key be discovered; - // there is no 100ms based reseeding because of this - // forced reseed for every `generateSync` call - ctx.key = null; - - var b = forge$p.util.createBuffer(); - while(b.length() < count) { - // if amount of data generated is greater than 1 MiB, trigger reseed - if(ctx.generated > 0xfffff) { - ctx.key = null; - } - - if(ctx.key === null) { - _reseedSync(); - } - - // generate the random bytes - var bytes = cipher(ctx.key, ctx.seed); - ctx.generated += bytes.length; - b.putBytes(bytes); - - // generate bytes for a new key and seed - ctx.key = formatKey(cipher(ctx.key, increment(ctx.seed))); - ctx.seed = formatSeed(cipher(ctx.key, ctx.seed)); - } - - return b.getBytes(count); - }; - - /** - * Private function that asynchronously reseeds a generator. - * - * @param callback(err) called once the operation completes. - */ - function _reseed(callback) { - if(ctx.pools[0].messageLength >= 32) { - _seed(); - return callback(); - } - // not enough seed data... - var needed = (32 - ctx.pools[0].messageLength) << 5; - ctx.seedFile(needed, function(err, bytes) { - if(err) { - return callback(err); - } - ctx.collect(bytes); - _seed(); - callback(); - }); - } - - /** - * Private function that synchronously reseeds a generator. - */ - function _reseedSync() { - if(ctx.pools[0].messageLength >= 32) { - return _seed(); - } - // not enough seed data... - var needed = (32 - ctx.pools[0].messageLength) << 5; - ctx.collect(ctx.seedFileSync(needed)); - _seed(); - } - - /** - * Private function that seeds a generator once enough bytes are available. - */ - function _seed() { - // update reseed count - ctx.reseeds = (ctx.reseeds === 0xffffffff) ? 0 : ctx.reseeds + 1; - - // goal is to update `key` via: - // key = hash(key + s) - // where 's' is all collected entropy from selected pools, then... - - // create a plugin-based message digest - var md = ctx.plugin.md.create(); - - // consume current key bytes - md.update(ctx.keyBytes); - - // digest the entropy of pools whose index k meet the - // condition 'n mod 2^k == 0' where n is the number of reseeds - var _2powK = 1; - for(var k = 0; k < 32; ++k) { - if(ctx.reseeds % _2powK === 0) { - md.update(ctx.pools[k].digest().getBytes()); - ctx.pools[k].start(); - } - _2powK = _2powK << 1; - } - - // get digest for key bytes - ctx.keyBytes = md.digest().getBytes(); - - // paranoid deviation from Fortuna: - // update `seed` via `seed = hash(key)` - // instead of initializing to zero once and only - // ever incrementing it - md.start(); - md.update(ctx.keyBytes); - var seedBytes = md.digest().getBytes(); - - // update state - ctx.key = ctx.plugin.formatKey(ctx.keyBytes); - ctx.seed = ctx.plugin.formatSeed(seedBytes); - ctx.generated = 0; - } - - /** - * The built-in default seedFile. This seedFile is used when entropy - * is needed immediately. - * - * @param needed the number of bytes that are needed. - * - * @return the random bytes. - */ - function defaultSeedFile(needed) { - // use window.crypto.getRandomValues strong source of entropy if available - var getRandomValues = null; - var globalScope = forge$p.util.globalScope; - var _crypto = globalScope.crypto || globalScope.msCrypto; - if(_crypto && _crypto.getRandomValues) { - getRandomValues = function(arr) { - return _crypto.getRandomValues(arr); - }; - } - - var b = forge$p.util.createBuffer(); - if(getRandomValues) { - while(b.length() < needed) { - // max byte length is 65536 before QuotaExceededError is thrown - // http://www.w3.org/TR/WebCryptoAPI/#RandomSource-method-getRandomValues - var count = Math.max(1, Math.min(needed - b.length(), 65536) / 4); - var entropy = new Uint32Array(Math.floor(count)); - try { - getRandomValues(entropy); - for(var i = 0; i < entropy.length; ++i) { - b.putInt32(entropy[i]); - } - } catch(e) { - /* only ignore QuotaExceededError */ - if(!(typeof QuotaExceededError !== 'undefined' && - e instanceof QuotaExceededError)) { - throw e; - } - } - } - } - - // be sad and add some weak random data - if(b.length() < needed) { - /* Draws from Park-Miller "minimal standard" 31 bit PRNG, - implemented with David G. Carta's optimization: with 32 bit math - and without division (Public Domain). */ - var hi, lo, next; - var seed = Math.floor(Math.random() * 0x010000); - while(b.length() < needed) { - lo = 16807 * (seed & 0xFFFF); - hi = 16807 * (seed >> 16); - lo += (hi & 0x7FFF) << 16; - lo += hi >> 15; - lo = (lo & 0x7FFFFFFF) + (lo >> 31); - seed = lo & 0xFFFFFFFF; - - // consume lower 3 bytes of seed - for(var i = 0; i < 3; ++i) { - // throw in more pseudo random - next = seed >>> (i << 3); - next ^= Math.floor(Math.random() * 0x0100); - b.putByte(next & 0xFF); - } - } - } - - return b.getBytes(needed); - } - // initialize seed file APIs - if(_crypto$1) { - // use nodejs async API - ctx.seedFile = function(needed, callback) { - _crypto$1.randomBytes(needed, function(err, bytes) { - if(err) { - return callback(err); - } - callback(null, bytes.toString()); - }); - }; - // use nodejs sync API - ctx.seedFileSync = function(needed) { - return _crypto$1.randomBytes(needed).toString(); - }; - } else { - ctx.seedFile = function(needed, callback) { - try { - callback(null, defaultSeedFile(needed)); - } catch(e) { - callback(e); - } - }; - ctx.seedFileSync = defaultSeedFile; - } - - /** - * Adds entropy to a prng ctx's accumulator. - * - * @param bytes the bytes of entropy as a string. - */ - ctx.collect = function(bytes) { - // iterate over pools distributing entropy cyclically - var count = bytes.length; - for(var i = 0; i < count; ++i) { - ctx.pools[ctx.pool].update(bytes.substr(i, 1)); - ctx.pool = (ctx.pool === 31) ? 0 : ctx.pool + 1; - } - }; - - /** - * Collects an integer of n bits. - * - * @param i the integer entropy. - * @param n the number of bits in the integer. - */ - ctx.collectInt = function(i, n) { - var bytes = ''; - for(var x = 0; x < n; x += 8) { - bytes += String.fromCharCode((i >> x) & 0xFF); - } - ctx.collect(bytes); - }; - - /** - * Registers a Web Worker to receive immediate entropy from the main thread. - * This method is required until Web Workers can access the native crypto - * API. This method should be called twice for each created worker, once in - * the main thread, and once in the worker itself. - * - * @param worker the worker to register. - */ - ctx.registerWorker = function(worker) { - // worker receives random bytes - if(worker === self) { - ctx.seedFile = function(needed, callback) { - function listener(e) { - var data = e.data; - if(data.forge && data.forge.prng) { - self.removeEventListener('message', listener); - callback(data.forge.prng.err, data.forge.prng.bytes); - } - } - self.addEventListener('message', listener); - self.postMessage({forge: {prng: {needed: needed}}}); - }; - } else { - // main thread sends random bytes upon request - var listener = function(e) { - var data = e.data; - if(data.forge && data.forge.prng) { - ctx.seedFile(data.forge.prng.needed, function(err, bytes) { - worker.postMessage({forge: {prng: {err: err, bytes: bytes}}}); - }); - } - }; - // TODO: do we need to remove the event listener when the worker dies? - worker.addEventListener('message', listener); - } - }; - - return ctx; -}; - -/** - * An API for getting cryptographically-secure random bytes. The bytes are - * generated using the Fortuna algorithm devised by Bruce Schneier and - * Niels Ferguson. - * - * Getting strong random bytes is not yet easy to do in javascript. The only - * truish random entropy that can be collected is from the mouse, keyboard, or - * from timing with respect to page loads, etc. This generator makes a poor - * attempt at providing random bytes when those sources haven't yet provided - * enough entropy to initially seed or to reseed the PRNG. - * - * @author Dave Longley - * - * Copyright (c) 2009-2014 Digital Bazaar, Inc. - */ - -var forge$o = forge$D; - - - - - -(function() { - -// forge.random already defined -if(forge$o.random && forge$o.random.getBytes) { - forge$o.random; - return; -} - -(function(jQuery) { - -// the default prng plugin, uses AES-128 -var prng_aes = {}; -var _prng_aes_output = new Array(4); -var _prng_aes_buffer = forge$o.util.createBuffer(); -prng_aes.formatKey = function(key) { - // convert the key into 32-bit integers - var tmp = forge$o.util.createBuffer(key); - key = new Array(4); - key[0] = tmp.getInt32(); - key[1] = tmp.getInt32(); - key[2] = tmp.getInt32(); - key[3] = tmp.getInt32(); - - // return the expanded key - return forge$o.aes._expandKey(key, false); -}; -prng_aes.formatSeed = function(seed) { - // convert seed into 32-bit integers - var tmp = forge$o.util.createBuffer(seed); - seed = new Array(4); - seed[0] = tmp.getInt32(); - seed[1] = tmp.getInt32(); - seed[2] = tmp.getInt32(); - seed[3] = tmp.getInt32(); - return seed; -}; -prng_aes.cipher = function(key, seed) { - forge$o.aes._updateBlock(key, seed, _prng_aes_output, false); - _prng_aes_buffer.putInt32(_prng_aes_output[0]); - _prng_aes_buffer.putInt32(_prng_aes_output[1]); - _prng_aes_buffer.putInt32(_prng_aes_output[2]); - _prng_aes_buffer.putInt32(_prng_aes_output[3]); - return _prng_aes_buffer.getBytes(); -}; -prng_aes.increment = function(seed) { - // FIXME: do we care about carry or signed issues? - ++seed[3]; - return seed; -}; -prng_aes.md = forge$o.md.sha256; - -/** - * Creates a new PRNG. - */ -function spawnPrng() { - var ctx = forge$o.prng.create(prng_aes); - - /** - * Gets random bytes. If a native secure crypto API is unavailable, this - * method tries to make the bytes more unpredictable by drawing from data that - * can be collected from the user of the browser, eg: mouse movement. - * - * If a callback is given, this method will be called asynchronously. - * - * @param count the number of random bytes to get. - * @param [callback(err, bytes)] called once the operation completes. - * - * @return the random bytes in a string. - */ - ctx.getBytes = function(count, callback) { - return ctx.generate(count, callback); - }; - - /** - * Gets random bytes asynchronously. If a native secure crypto API is - * unavailable, this method tries to make the bytes more unpredictable by - * drawing from data that can be collected from the user of the browser, - * eg: mouse movement. - * - * @param count the number of random bytes to get. - * - * @return the random bytes in a string. - */ - ctx.getBytesSync = function(count) { - return ctx.generate(count); - }; - - return ctx; -} - -// create default prng context -var _ctx = spawnPrng(); - -// add other sources of entropy only if window.crypto.getRandomValues is not -// available -- otherwise this source will be automatically used by the prng -var getRandomValues = null; -var globalScope = forge$o.util.globalScope; -var _crypto = globalScope.crypto || globalScope.msCrypto; -if(_crypto && _crypto.getRandomValues) { - getRandomValues = function(arr) { - return _crypto.getRandomValues(arr); - }; -} - -if(forge$o.options.usePureJavaScript || - (!forge$o.util.isNodejs && !getRandomValues)) { - - // get load time entropy - _ctx.collectInt(+new Date(), 32); - - // add some entropy from navigator object - if(typeof(navigator) !== 'undefined') { - var _navBytes = ''; - for(var key in navigator) { - try { - if(typeof(navigator[key]) == 'string') { - _navBytes += navigator[key]; - } - } catch(e) { - /* Some navigator keys might not be accessible, e.g. the geolocation - attribute throws an exception if touched in Mozilla chrome:// - context. - - Silently ignore this and just don't use this as a source of - entropy. */ - } - } - _ctx.collect(_navBytes); - _navBytes = null; - } - - // add mouse and keyboard collectors if jquery is available - if(jQuery) { - // set up mouse entropy capture - jQuery().mousemove(function(e) { - // add mouse coords - _ctx.collectInt(e.clientX, 16); - _ctx.collectInt(e.clientY, 16); - }); - - // set up keyboard entropy capture - jQuery().keypress(function(e) { - _ctx.collectInt(e.charCode, 8); - }); - } -} - -/* Random API */ -if(!forge$o.random) { - forge$o.random = _ctx; -} else { - // extend forge.random with _ctx - for(var key in _ctx) { - forge$o.random[key] = _ctx[key]; - } -} - -// expose spawn PRNG -forge$o.random.createInstance = spawnPrng; - -forge$o.random; - -})(typeof(jQuery) !== 'undefined' ? jQuery : null); - -})(); - -/** - * RC2 implementation. - * - * @author Stefan Siegl - * - * Copyright (c) 2012 Stefan Siegl - * - * Information on the RC2 cipher is available from RFC #2268, - * http://www.ietf.org/rfc/rfc2268.txt - */ - -var forge$n = forge$D; - - -var piTable = [ - 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, - 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, - 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, - 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, - 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, - 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, - 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, - 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, - 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, - 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, - 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, - 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, - 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, - 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, - 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, - 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad -]; - -var s = [1, 2, 3, 5]; - -/** - * Rotate a word left by given number of bits. - * - * Bits that are shifted out on the left are put back in on the right - * hand side. - * - * @param word The word to shift left. - * @param bits The number of bits to shift by. - * @return The rotated word. - */ -var rol = function(word, bits) { - return ((word << bits) & 0xffff) | ((word & 0xffff) >> (16 - bits)); -}; - -/** - * Rotate a word right by given number of bits. - * - * Bits that are shifted out on the right are put back in on the left - * hand side. - * - * @param word The word to shift right. - * @param bits The number of bits to shift by. - * @return The rotated word. - */ -var ror = function(word, bits) { - return ((word & 0xffff) >> bits) | ((word << (16 - bits)) & 0xffff); -}; - -/* RC2 API */ -forge$n.rc2 = forge$n.rc2 || {}; - -/** - * Perform RC2 key expansion as per RFC #2268, section 2. - * - * @param key variable-length user key (between 1 and 128 bytes) - * @param effKeyBits number of effective key bits (default: 128) - * @return the expanded RC2 key (ByteBuffer of 128 bytes) - */ -forge$n.rc2.expandKey = function(key, effKeyBits) { - if(typeof key === 'string') { - key = forge$n.util.createBuffer(key); - } - effKeyBits = effKeyBits || 128; - - /* introduce variables that match the names used in RFC #2268 */ - var L = key; - var T = key.length(); - var T1 = effKeyBits; - var T8 = Math.ceil(T1 / 8); - var TM = 0xff >> (T1 & 0x07); - var i; - - for(i = T; i < 128; i++) { - L.putByte(piTable[(L.at(i - 1) + L.at(i - T)) & 0xff]); - } - - L.setAt(128 - T8, piTable[L.at(128 - T8) & TM]); - - for(i = 127 - T8; i >= 0; i--) { - L.setAt(i, piTable[L.at(i + 1) ^ L.at(i + T8)]); - } - - return L; -}; - -/** - * Creates a RC2 cipher object. - * - * @param key the symmetric key to use (as base for key generation). - * @param bits the number of effective key bits. - * @param encrypt false for decryption, true for encryption. - * - * @return the cipher. - */ -var createCipher = function(key, bits, encrypt) { - var _finish = false, _input = null, _output = null, _iv = null; - var mixRound, mashRound; - var i, j, K = []; - - /* Expand key and fill into K[] Array */ - key = forge$n.rc2.expandKey(key, bits); - for(i = 0; i < 64; i++) { - K.push(key.getInt16Le()); - } - - if(encrypt) { - /** - * Perform one mixing round "in place". - * - * @param R Array of four words to perform mixing on. - */ - mixRound = function(R) { - for(i = 0; i < 4; i++) { - R[i] += K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) + - ((~R[(i + 3) % 4]) & R[(i + 1) % 4]); - R[i] = rol(R[i], s[i]); - j++; - } - }; - - /** - * Perform one mashing round "in place". - * - * @param R Array of four words to perform mashing on. - */ - mashRound = function(R) { - for(i = 0; i < 4; i++) { - R[i] += K[R[(i + 3) % 4] & 63]; - } - }; - } else { - /** - * Perform one r-mixing round "in place". - * - * @param R Array of four words to perform mixing on. - */ - mixRound = function(R) { - for(i = 3; i >= 0; i--) { - R[i] = ror(R[i], s[i]); - R[i] -= K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) + - ((~R[(i + 3) % 4]) & R[(i + 1) % 4]); - j--; - } - }; - - /** - * Perform one r-mashing round "in place". - * - * @param R Array of four words to perform mashing on. - */ - mashRound = function(R) { - for(i = 3; i >= 0; i--) { - R[i] -= K[R[(i + 3) % 4] & 63]; - } - }; - } - - /** - * Run the specified cipher execution plan. - * - * This function takes four words from the input buffer, applies the IV on - * it (if requested) and runs the provided execution plan. - * - * The plan must be put together in form of a array of arrays. Where the - * outer one is simply a list of steps to perform and the inner one needs - * to have two elements: the first one telling how many rounds to perform, - * the second one telling what to do (i.e. the function to call). - * - * @param {Array} plan The plan to execute. - */ - var runPlan = function(plan) { - var R = []; - - /* Get data from input buffer and fill the four words into R */ - for(i = 0; i < 4; i++) { - var val = _input.getInt16Le(); - - if(_iv !== null) { - if(encrypt) { - /* We're encrypting, apply the IV first. */ - val ^= _iv.getInt16Le(); - } else { - /* We're decryption, keep cipher text for next block. */ - _iv.putInt16Le(val); - } - } - - R.push(val & 0xffff); - } - - /* Reset global "j" variable as per spec. */ - j = encrypt ? 0 : 63; - - /* Run execution plan. */ - for(var ptr = 0; ptr < plan.length; ptr++) { - for(var ctr = 0; ctr < plan[ptr][0]; ctr++) { - plan[ptr][1](R); - } - } - - /* Write back result to output buffer. */ - for(i = 0; i < 4; i++) { - if(_iv !== null) { - if(encrypt) { - /* We're encrypting in CBC-mode, feed back encrypted bytes into - IV buffer to carry it forward to next block. */ - _iv.putInt16Le(R[i]); - } else { - R[i] ^= _iv.getInt16Le(); - } - } - - _output.putInt16Le(R[i]); - } - }; - - /* Create cipher object */ - var cipher = null; - cipher = { - /** - * Starts or restarts the encryption or decryption process, whichever - * was previously configured. - * - * To use the cipher in CBC mode, iv may be given either as a string - * of bytes, or as a byte buffer. For ECB mode, give null as iv. - * - * @param iv the initialization vector to use, null for ECB mode. - * @param output the output the buffer to write to, null to create one. - */ - start: function(iv, output) { - if(iv) { - /* CBC mode */ - if(typeof iv === 'string') { - iv = forge$n.util.createBuffer(iv); - } - } - - _finish = false; - _input = forge$n.util.createBuffer(); - _output = output || new forge$n.util.createBuffer(); - _iv = iv; - - cipher.output = _output; - }, - - /** - * Updates the next block. - * - * @param input the buffer to read from. - */ - update: function(input) { - if(!_finish) { - // not finishing, so fill the input buffer with more input - _input.putBuffer(input); - } - - while(_input.length() >= 8) { - runPlan([ - [ 5, mixRound ], - [ 1, mashRound ], - [ 6, mixRound ], - [ 1, mashRound ], - [ 5, mixRound ] - ]); - } - }, - - /** - * Finishes encrypting or decrypting. - * - * @param pad a padding function to use, null for PKCS#7 padding, - * signature(blockSize, buffer, decrypt). - * - * @return true if successful, false on error. - */ - finish: function(pad) { - var rval = true; - - if(encrypt) { - if(pad) { - rval = pad(8, _input, !encrypt); - } else { - // add PKCS#7 padding to block (each pad byte is the - // value of the number of pad bytes) - var padding = (_input.length() === 8) ? 8 : (8 - _input.length()); - _input.fillWithByte(padding, padding); - } - } - - if(rval) { - // do final update - _finish = true; - cipher.update(); - } - - if(!encrypt) { - // check for error: input data not a multiple of block size - rval = (_input.length() === 0); - if(rval) { - if(pad) { - rval = pad(8, _output, !encrypt); - } else { - // ensure padding byte count is valid - var len = _output.length(); - var count = _output.at(len - 1); - - if(count > len) { - rval = false; - } else { - // trim off padding bytes - _output.truncate(count); - } - } - } - } - - return rval; - } - }; - - return cipher; -}; - -/** - * Creates an RC2 cipher object to encrypt data in ECB or CBC mode using the - * given symmetric key. The output will be stored in the 'output' member - * of the returned cipher. - * - * The key and iv may be given as a string of bytes or a byte buffer. - * The cipher is initialized to use 128 effective key bits. - * - * @param key the symmetric key to use. - * @param iv the initialization vector to use. - * @param output the buffer to write to, null to create one. - * - * @return the cipher. - */ -forge$n.rc2.startEncrypting = function(key, iv, output) { - var cipher = forge$n.rc2.createEncryptionCipher(key, 128); - cipher.start(iv, output); - return cipher; -}; - -/** - * Creates an RC2 cipher object to encrypt data in ECB or CBC mode using the - * given symmetric key. - * - * The key may be given as a string of bytes or a byte buffer. - * - * To start encrypting call start() on the cipher with an iv and optional - * output buffer. - * - * @param key the symmetric key to use. - * - * @return the cipher. - */ -forge$n.rc2.createEncryptionCipher = function(key, bits) { - return createCipher(key, bits, true); -}; - -/** - * Creates an RC2 cipher object to decrypt data in ECB or CBC mode using the - * given symmetric key. The output will be stored in the 'output' member - * of the returned cipher. - * - * The key and iv may be given as a string of bytes or a byte buffer. - * The cipher is initialized to use 128 effective key bits. - * - * @param key the symmetric key to use. - * @param iv the initialization vector to use. - * @param output the buffer to write to, null to create one. - * - * @return the cipher. - */ -forge$n.rc2.startDecrypting = function(key, iv, output) { - var cipher = forge$n.rc2.createDecryptionCipher(key, 128); - cipher.start(iv, output); - return cipher; -}; - -/** - * Creates an RC2 cipher object to decrypt data in ECB or CBC mode using the - * given symmetric key. - * - * The key may be given as a string of bytes or a byte buffer. - * - * To start decrypting call start() on the cipher with an iv and optional - * output buffer. - * - * @param key the symmetric key to use. - * - * @return the cipher. - */ -forge$n.rc2.createDecryptionCipher = function(key, bits) { - return createCipher(key, bits, false); -}; - -// Copyright (c) 2005 Tom Wu -// All Rights Reserved. -// See "LICENSE" for details. - -// Basic JavaScript BN library - subset useful for RSA encryption. - -/* -Licensing (LICENSE) -------------------- - -This software is covered under the following copyright: -*/ -/* - * Copyright (c) 2003-2005 Tom Wu - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF - * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * In addition, the following condition applies: - * - * All redistributions must retain an intact copy of this copyright notice - * and disclaimer. - */ -/* -Address all questions regarding this license to: - - Tom Wu - tjw@cs.Stanford.EDU -*/ -var forge$m = forge$D; - -forge$m.jsbn = forge$m.jsbn || {}; - -// Bits per digit -var dbits; - -// (public) Constructor -function BigInteger$4(a,b,c) { - this.data = []; - if(a != null) - if("number" == typeof a) this.fromNumber(a,b,c); - else if(b == null && "string" != typeof a) this.fromString(a,256); - else this.fromString(a,b); -} -forge$m.jsbn.BigInteger = BigInteger$4; - -// return new, unset BigInteger -function nbi() { return new BigInteger$4(null); } - -// am: Compute w_j += (x*this_i), propagate carries, -// c is initial carry, returns final carry. -// c < 3*dvalue, x < 2*dvalue, this_i < dvalue -// We need to select the fastest one that works in this environment. - -// am1: use a single mult and divide to get the high bits, -// max digit bits should be 26 because -// max internal value = 2*dvalue^2-2*dvalue (< 2^53) -function am1(i,x,w,j,c,n) { - while(--n >= 0) { - var v = x*this.data[i++]+w.data[j]+c; - c = Math.floor(v/0x4000000); - w.data[j++] = v&0x3ffffff; - } - return c; -} -// am2 avoids a big mult-and-extract completely. -// Max digit bits should be <= 30 because we do bitwise ops -// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) -function am2(i,x,w,j,c,n) { - var xl = x&0x7fff, xh = x>>15; - while(--n >= 0) { - var l = this.data[i]&0x7fff; - var h = this.data[i++]>>15; - var m = xh*l+h*xl; - l = xl*l+((m&0x7fff)<<15)+w.data[j]+(c&0x3fffffff); - c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); - w.data[j++] = l&0x3fffffff; - } - return c; -} -// Alternately, set max digit bits to 28 since some -// browsers slow down when dealing with 32-bit numbers. -function am3(i,x,w,j,c,n) { - var xl = x&0x3fff, xh = x>>14; - while(--n >= 0) { - var l = this.data[i]&0x3fff; - var h = this.data[i++]>>14; - var m = xh*l+h*xl; - l = xl*l+((m&0x3fff)<<14)+w.data[j]+c; - c = (l>>28)+(m>>14)+xh*h; - w.data[j++] = l&0xfffffff; - } - return c; -} - -// node.js (no browser) -if(typeof(navigator) === 'undefined') -{ - BigInteger$4.prototype.am = am3; - dbits = 28; -} else if((navigator.appName == "Microsoft Internet Explorer")) { - BigInteger$4.prototype.am = am2; - dbits = 30; -} else if((navigator.appName != "Netscape")) { - BigInteger$4.prototype.am = am1; - dbits = 26; -} else { // Mozilla/Netscape seems to prefer am3 - BigInteger$4.prototype.am = am3; - dbits = 28; -} - -BigInteger$4.prototype.DB = dbits; -BigInteger$4.prototype.DM = ((1<= 0; --i) r.data[i] = this.data[i]; - r.t = this.t; - r.s = this.s; -} - -// (protected) set from integer value x, -DV <= x < DV -function bnpFromInt(x) { - this.t = 1; - this.s = (x<0)?-1:0; - if(x > 0) this.data[0] = x; - else if(x < -1) this.data[0] = x+this.DV; - else this.t = 0; -} - -// return bigint initialized to value -function nbv(i) { var r = nbi(); r.fromInt(i); return r; } - -// (protected) set from string and radix -function bnpFromString(s,b) { - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 256) k = 8; // byte array - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else { this.fromRadix(s,b); return; } - this.t = 0; - this.s = 0; - var i = s.length, mi = false, sh = 0; - while(--i >= 0) { - var x = (k==8)?s[i]&0xff:intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-") mi = true; - continue; - } - mi = false; - if(sh == 0) - this.data[this.t++] = x; - else if(sh+k > this.DB) { - this.data[this.t-1] |= (x&((1<<(this.DB-sh))-1))<>(this.DB-sh)); - } else - this.data[this.t-1] |= x<= this.DB) sh -= this.DB; - } - if(k == 8 && (s[0]&0x80) != 0) { - this.s = -1; - if(sh > 0) this.data[this.t-1] |= ((1<<(this.DB-sh))-1)< 0 && this.data[this.t-1] == c) --this.t; -} - -// (public) return string representation in given radix -function bnToString(b) { - if(this.s < 0) return "-"+this.negate().toString(b); - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else return this.toRadix(b); - var km = (1< 0) { - if(p < this.DB && (d = this.data[i]>>p) > 0) { m = true; r = int2char(d); } - while(i >= 0) { - if(p < k) { - d = (this.data[i]&((1<>(p+=this.DB-k); - } else { - d = (this.data[i]>>(p-=k))&km; - if(p <= 0) { p += this.DB; --i; } - } - if(d > 0) m = true; - if(m) r += int2char(d); - } - } - return m?r:"0"; -} - -// (public) -this -function bnNegate() { var r = nbi(); BigInteger$4.ZERO.subTo(this,r); return r; } - -// (public) |this| -function bnAbs() { return (this.s<0)?this.negate():this; } - -// (public) return + if this > a, - if this < a, 0 if equal -function bnCompareTo(a) { - var r = this.s-a.s; - if(r != 0) return r; - var i = this.t; - r = i-a.t; - if(r != 0) return (this.s<0)?-r:r; - while(--i >= 0) if((r=this.data[i]-a.data[i]) != 0) return r; - return 0; -} - -// returns bit length of the integer x -function nbits(x) { - var r = 1, t; - if((t=x>>>16) != 0) { x = t; r += 16; } - if((t=x>>8) != 0) { x = t; r += 8; } - if((t=x>>4) != 0) { x = t; r += 4; } - if((t=x>>2) != 0) { x = t; r += 2; } - if((t=x>>1) != 0) { x = t; r += 1; } - return r; -} - -// (public) return the number of bits in "this" -function bnBitLength() { - if(this.t <= 0) return 0; - return this.DB*(this.t-1)+nbits(this.data[this.t-1]^(this.s&this.DM)); -} - -// (protected) r = this << n*DB -function bnpDLShiftTo(n,r) { - var i; - for(i = this.t-1; i >= 0; --i) r.data[i+n] = this.data[i]; - for(i = n-1; i >= 0; --i) r.data[i] = 0; - r.t = this.t+n; - r.s = this.s; -} - -// (protected) r = this >> n*DB -function bnpDRShiftTo(n,r) { - for(var i = n; i < this.t; ++i) r.data[i-n] = this.data[i]; - r.t = Math.max(this.t-n,0); - r.s = this.s; -} - -// (protected) r = this << n -function bnpLShiftTo(n,r) { - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<= 0; --i) { - r.data[i+ds+1] = (this.data[i]>>cbs)|c; - c = (this.data[i]&bm)<= 0; --i) r.data[i] = 0; - r.data[ds] = c; - r.t = this.t+ds+1; - r.s = this.s; - r.clamp(); -} - -// (protected) r = this >> n -function bnpRShiftTo(n,r) { - r.s = this.s; - var ds = Math.floor(n/this.DB); - if(ds >= this.t) { r.t = 0; return; } - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<>bs; - for(var i = ds+1; i < this.t; ++i) { - r.data[i-ds-1] |= (this.data[i]&bm)<>bs; - } - if(bs > 0) r.data[this.t-ds-1] |= (this.s&bm)<>= this.DB; - } - if(a.t < this.t) { - c -= a.s; - while(i < this.t) { - c += this.data[i]; - r.data[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } else { - c += this.s; - while(i < a.t) { - c -= a.data[i]; - r.data[i++] = c&this.DM; - c >>= this.DB; - } - c -= a.s; - } - r.s = (c<0)?-1:0; - if(c < -1) r.data[i++] = this.DV+c; - else if(c > 0) r.data[i++] = c; - r.t = i; - r.clamp(); -} - -// (protected) r = this * a, r != this,a (HAC 14.12) -// "this" should be the larger one if appropriate. -function bnpMultiplyTo(a,r) { - var x = this.abs(), y = a.abs(); - var i = x.t; - r.t = i+y.t; - while(--i >= 0) r.data[i] = 0; - for(i = 0; i < y.t; ++i) r.data[i+x.t] = x.am(0,y.data[i],r,i,0,x.t); - r.s = 0; - r.clamp(); - if(this.s != a.s) BigInteger$4.ZERO.subTo(r,r); -} - -// (protected) r = this^2, r != this (HAC 14.16) -function bnpSquareTo(r) { - var x = this.abs(); - var i = r.t = 2*x.t; - while(--i >= 0) r.data[i] = 0; - for(i = 0; i < x.t-1; ++i) { - var c = x.am(i,x.data[i],r,2*i,0,1); - if((r.data[i+x.t]+=x.am(i+1,2*x.data[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { - r.data[i+x.t] -= x.DV; - r.data[i+x.t+1] = 1; - } - } - if(r.t > 0) r.data[r.t-1] += x.am(i,x.data[i],r,2*i,0,1); - r.s = 0; - r.clamp(); -} - -// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) -// r != q, this != m. q or r may be null. -function bnpDivRemTo(m,q,r) { - var pm = m.abs(); - if(pm.t <= 0) return; - var pt = this.abs(); - if(pt.t < pm.t) { - if(q != null) q.fromInt(0); - if(r != null) this.copyTo(r); - return; - } - if(r == null) r = nbi(); - var y = nbi(), ts = this.s, ms = m.s; - var nsh = this.DB-nbits(pm.data[pm.t-1]); // normalize modulus - if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } else { pm.copyTo(y); pt.copyTo(r); } - var ys = y.t; - var y0 = y.data[ys-1]; - if(y0 == 0) return; - var yt = y0*(1<1)?y.data[ys-2]>>this.F2:0); - var d1 = this.FV/yt, d2 = (1<= 0) { - r.data[r.t++] = 1; - r.subTo(t,r); - } - BigInteger$4.ONE.dlShiftTo(ys,t); - t.subTo(y,y); // "negative" y so we can replace sub with am later - while(y.t < ys) y.data[y.t++] = 0; - while(--j >= 0) { - // Estimate quotient digit - var qd = (r.data[--i]==y0)?this.DM:Math.floor(r.data[i]*d1+(r.data[i-1]+e)*d2); - if((r.data[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out - y.dlShiftTo(j,t); - r.subTo(t,r); - while(r.data[i] < --qd) r.subTo(t,r); - } - } - if(q != null) { - r.drShiftTo(ys,q); - if(ts != ms) BigInteger$4.ZERO.subTo(q,q); - } - r.t = ys; - r.clamp(); - if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder - if(ts < 0) BigInteger$4.ZERO.subTo(r,r); -} - -// (public) this mod a -function bnMod(a) { - var r = nbi(); - this.abs().divRemTo(a,null,r); - if(this.s < 0 && r.compareTo(BigInteger$4.ZERO) > 0) a.subTo(r,r); - return r; -} - -// Modular reduction using "classic" algorithm -function Classic(m) { this.m = m; } -function cConvert(x) { - if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); - else return x; -} -function cRevert(x) { return x; } -function cReduce(x) { x.divRemTo(this.m,null,x); } -function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } -function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -Classic.prototype.convert = cConvert; -Classic.prototype.revert = cRevert; -Classic.prototype.reduce = cReduce; -Classic.prototype.mulTo = cMulTo; -Classic.prototype.sqrTo = cSqrTo; - -// (protected) return "-1/this % 2^DB"; useful for Mont. reduction -// justification: -// xy == 1 (mod m) -// xy = 1+km -// xy(2-xy) = (1+km)(1-km) -// x[y(2-xy)] = 1-k^2m^2 -// x[y(2-xy)] == 1 (mod m^2) -// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 -// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. -// JS multiply "overflows" differently from C/C++, so care is needed here. -function bnpInvDigit() { - if(this.t < 1) return 0; - var x = this.data[0]; - if((x&1) == 0) return 0; - var y = x&3; // y == 1/x mod 2^2 - y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 - y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 - y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 - // last step - calculate inverse mod DV directly; - // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints - y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits - // we really want the negative inverse, and -DV < y < DV - return (y>0)?this.DV-y:-y; -} - -// Montgomery reduction -function Montgomery(m) { - this.m = m; - this.mp = m.invDigit(); - this.mpl = this.mp&0x7fff; - this.mph = this.mp>>15; - this.um = (1<<(m.DB-15))-1; - this.mt2 = 2*m.t; -} - -// xR mod m -function montConvert(x) { - var r = nbi(); - x.abs().dlShiftTo(this.m.t,r); - r.divRemTo(this.m,null,r); - if(x.s < 0 && r.compareTo(BigInteger$4.ZERO) > 0) this.m.subTo(r,r); - return r; -} - -// x/R mod m -function montRevert(x) { - var r = nbi(); - x.copyTo(r); - this.reduce(r); - return r; -} - -// x = x/R mod m (HAC 14.32) -function montReduce(x) { - while(x.t <= this.mt2) // pad x so am has enough room later - x.data[x.t++] = 0; - for(var i = 0; i < this.m.t; ++i) { - // faster way of calculating u0 = x.data[i]*mp mod DV - var j = x.data[i]&0x7fff; - var u0 = (j*this.mpl+(((j*this.mph+(x.data[i]>>15)*this.mpl)&this.um)<<15))&x.DM; - // use am to combine the multiply-shift-add into one call - j = i+this.m.t; - x.data[j] += this.m.am(0,u0,x,i,0,this.m.t); - // propagate carry - while(x.data[j] >= x.DV) { x.data[j] -= x.DV; x.data[++j]++; } - } - x.clamp(); - x.drShiftTo(this.m.t,x); - if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = "x^2/R mod m"; x != r -function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = "xy/R mod m"; x,y != r -function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Montgomery.prototype.convert = montConvert; -Montgomery.prototype.revert = montRevert; -Montgomery.prototype.reduce = montReduce; -Montgomery.prototype.mulTo = montMulTo; -Montgomery.prototype.sqrTo = montSqrTo; - -// (protected) true iff this is even -function bnpIsEven() { return ((this.t>0)?(this.data[0]&1):this.s) == 0; } - -// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) -function bnpExp(e,z) { - if(e > 0xffffffff || e < 1) return BigInteger$4.ONE; - var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; - g.copyTo(r); - while(--i >= 0) { - z.sqrTo(r,r2); - if((e&(1< 0) z.mulTo(r2,g,r); - else { var t = r; r = r2; r2 = t; } - } - return z.revert(r); -} - -// (public) this^e % m, 0 <= e < 2^32 -function bnModPowInt(e,m) { - var z; - if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); - return this.exp(e,z); -} - -// protected -BigInteger$4.prototype.copyTo = bnpCopyTo; -BigInteger$4.prototype.fromInt = bnpFromInt; -BigInteger$4.prototype.fromString = bnpFromString; -BigInteger$4.prototype.clamp = bnpClamp; -BigInteger$4.prototype.dlShiftTo = bnpDLShiftTo; -BigInteger$4.prototype.drShiftTo = bnpDRShiftTo; -BigInteger$4.prototype.lShiftTo = bnpLShiftTo; -BigInteger$4.prototype.rShiftTo = bnpRShiftTo; -BigInteger$4.prototype.subTo = bnpSubTo; -BigInteger$4.prototype.multiplyTo = bnpMultiplyTo; -BigInteger$4.prototype.squareTo = bnpSquareTo; -BigInteger$4.prototype.divRemTo = bnpDivRemTo; -BigInteger$4.prototype.invDigit = bnpInvDigit; -BigInteger$4.prototype.isEven = bnpIsEven; -BigInteger$4.prototype.exp = bnpExp; - -// public -BigInteger$4.prototype.toString = bnToString; -BigInteger$4.prototype.negate = bnNegate; -BigInteger$4.prototype.abs = bnAbs; -BigInteger$4.prototype.compareTo = bnCompareTo; -BigInteger$4.prototype.bitLength = bnBitLength; -BigInteger$4.prototype.mod = bnMod; -BigInteger$4.prototype.modPowInt = bnModPowInt; - -// "constants" -BigInteger$4.ZERO = nbv(0); -BigInteger$4.ONE = nbv(1); - -// jsbn2 lib - -//Copyright (c) 2005-2009 Tom Wu -//All Rights Reserved. -//See "LICENSE" for details (See jsbn.js for LICENSE). - -//Extended JavaScript BN functions, required for RSA private ops. - -//Version 1.1: new BigInteger("0", 10) returns "proper" zero - -//(public) -function bnClone() { var r = nbi(); this.copyTo(r); return r; } - -//(public) return value as integer -function bnIntValue() { -if(this.s < 0) { - if(this.t == 1) return this.data[0]-this.DV; - else if(this.t == 0) return -1; -} else if(this.t == 1) return this.data[0]; -else if(this.t == 0) return 0; -// assumes 16 < DB < 32 -return ((this.data[1]&((1<<(32-this.DB))-1))<>24; } - -//(public) return value as short (assumes DB>=16) -function bnShortValue() { return (this.t==0)?this.s:(this.data[0]<<16)>>16; } - -//(protected) return x s.t. r^x < DV -function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } - -//(public) 0 if this == 0, 1 if this > 0 -function bnSigNum() { -if(this.s < 0) return -1; -else if(this.t <= 0 || (this.t == 1 && this.data[0] <= 0)) return 0; -else return 1; -} - -//(protected) convert to radix string -function bnpToRadix(b) { -if(b == null) b = 10; -if(this.signum() == 0 || b < 2 || b > 36) return "0"; -var cs = this.chunkSize(b); -var a = Math.pow(b,cs); -var d = nbv(a), y = nbi(), z = nbi(), r = ""; -this.divRemTo(d,y,z); -while(y.signum() > 0) { - r = (a+z.intValue()).toString(b).substr(1) + r; - y.divRemTo(d,y,z); -} -return z.intValue().toString(b) + r; -} - -//(protected) convert from radix string -function bnpFromRadix(s,b) { -this.fromInt(0); -if(b == null) b = 10; -var cs = this.chunkSize(b); -var d = Math.pow(b,cs), mi = false, j = 0, w = 0; -for(var i = 0; i < s.length; ++i) { - var x = intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-" && this.signum() == 0) mi = true; - continue; - } - w = b*w+x; - if(++j >= cs) { - this.dMultiply(d); - this.dAddOffset(w,0); - j = 0; - w = 0; - } -} -if(j > 0) { - this.dMultiply(Math.pow(b,j)); - this.dAddOffset(w,0); -} -if(mi) BigInteger$4.ZERO.subTo(this,this); -} - -//(protected) alternate constructor -function bnpFromNumber(a,b,c) { -if("number" == typeof b) { - // new BigInteger(int,int,RNG) - if(a < 2) this.fromInt(1); - else { - this.fromNumber(a,c); - if(!this.testBit(a-1)) // force MSB set - this.bitwiseTo(BigInteger$4.ONE.shiftLeft(a-1),op_or,this); - if(this.isEven()) this.dAddOffset(1,0); // force odd - while(!this.isProbablePrime(b)) { - this.dAddOffset(2,0); - if(this.bitLength() > a) this.subTo(BigInteger$4.ONE.shiftLeft(a-1),this); - } - } -} else { - // new BigInteger(int,RNG) - var x = new Array(), t = a&7; - x.length = (a>>3)+1; - b.nextBytes(x); - if(t > 0) x[0] &= ((1< 0) { - if(p < this.DB && (d = this.data[i]>>p) != (this.s&this.DM)>>p) - r[k++] = d|(this.s<<(this.DB-p)); - while(i >= 0) { - if(p < 8) { - d = (this.data[i]&((1<>(p+=this.DB-8); - } else { - d = (this.data[i]>>(p-=8))&0xff; - if(p <= 0) { p += this.DB; --i; } - } - if((d&0x80) != 0) d |= -256; - if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; - if(k > 0 || d != this.s) r[k++] = d; - } -} -return r; -} - -function bnEquals(a) { return(this.compareTo(a)==0); } -function bnMin(a) { return (this.compareTo(a)<0)?this:a; } -function bnMax(a) { return (this.compareTo(a)>0)?this:a; } - -//(protected) r = this op a (bitwise) -function bnpBitwiseTo(a,op,r) { -var i, f, m = Math.min(a.t,this.t); -for(i = 0; i < m; ++i) r.data[i] = op(this.data[i],a.data[i]); -if(a.t < this.t) { - f = a.s&this.DM; - for(i = m; i < this.t; ++i) r.data[i] = op(this.data[i],f); - r.t = this.t; -} else { - f = this.s&this.DM; - for(i = m; i < a.t; ++i) r.data[i] = op(f,a.data[i]); - r.t = a.t; -} -r.s = op(this.s,a.s); -r.clamp(); -} - -//(public) this & a -function op_and(x,y) { return x&y; } -function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } - -//(public) this | a -function op_or(x,y) { return x|y; } -function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } - -//(public) this ^ a -function op_xor(x,y) { return x^y; } -function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } - -//(public) this & ~a -function op_andnot(x,y) { return x&~y; } -function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } - -//(public) ~this -function bnNot() { -var r = nbi(); -for(var i = 0; i < this.t; ++i) r.data[i] = this.DM&~this.data[i]; -r.t = this.t; -r.s = ~this.s; -return r; -} - -//(public) this << n -function bnShiftLeft(n) { -var r = nbi(); -if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); -return r; -} - -//(public) this >> n -function bnShiftRight(n) { -var r = nbi(); -if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); -return r; -} - -//return index of lowest 1-bit in x, x < 2^31 -function lbit(x) { -if(x == 0) return -1; -var r = 0; -if((x&0xffff) == 0) { x >>= 16; r += 16; } -if((x&0xff) == 0) { x >>= 8; r += 8; } -if((x&0xf) == 0) { x >>= 4; r += 4; } -if((x&3) == 0) { x >>= 2; r += 2; } -if((x&1) == 0) ++r; -return r; -} - -//(public) returns index of lowest 1-bit (or -1 if none) -function bnGetLowestSetBit() { -for(var i = 0; i < this.t; ++i) - if(this.data[i] != 0) return i*this.DB+lbit(this.data[i]); -if(this.s < 0) return this.t*this.DB; -return -1; -} - -//return number of 1 bits in x -function cbit(x) { -var r = 0; -while(x != 0) { x &= x-1; ++r; } -return r; -} - -//(public) return number of set bits -function bnBitCount() { -var r = 0, x = this.s&this.DM; -for(var i = 0; i < this.t; ++i) r += cbit(this.data[i]^x); -return r; -} - -//(public) true iff nth bit is set -function bnTestBit(n) { -var j = Math.floor(n/this.DB); -if(j >= this.t) return(this.s!=0); -return((this.data[j]&(1<<(n%this.DB)))!=0); -} - -//(protected) this op (1<>= this.DB; -} -if(a.t < this.t) { - c += a.s; - while(i < this.t) { - c += this.data[i]; - r.data[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; -} else { - c += this.s; - while(i < a.t) { - c += a.data[i]; - r.data[i++] = c&this.DM; - c >>= this.DB; - } - c += a.s; -} -r.s = (c<0)?-1:0; -if(c > 0) r.data[i++] = c; -else if(c < -1) r.data[i++] = this.DV+c; -r.t = i; -r.clamp(); -} - -//(public) this + a -function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } - -//(public) this - a -function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } - -//(public) this * a -function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } - -//(public) this / a -function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } - -//(public) this % a -function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } - -//(public) [this/a,this%a] -function bnDivideAndRemainder(a) { -var q = nbi(), r = nbi(); -this.divRemTo(a,q,r); -return new Array(q,r); -} - -//(protected) this *= n, this >= 0, 1 < n < DV -function bnpDMultiply(n) { -this.data[this.t] = this.am(0,n-1,this,0,0,this.t); -++this.t; -this.clamp(); -} - -//(protected) this += n << w words, this >= 0 -function bnpDAddOffset(n,w) { -if(n == 0) return; -while(this.t <= w) this.data[this.t++] = 0; -this.data[w] += n; -while(this.data[w] >= this.DV) { - this.data[w] -= this.DV; - if(++w >= this.t) this.data[this.t++] = 0; - ++this.data[w]; -} -} - -//A "null" reducer -function NullExp() {} -function nNop(x) { return x; } -function nMulTo(x,y,r) { x.multiplyTo(y,r); } -function nSqrTo(x,r) { x.squareTo(r); } - -NullExp.prototype.convert = nNop; -NullExp.prototype.revert = nNop; -NullExp.prototype.mulTo = nMulTo; -NullExp.prototype.sqrTo = nSqrTo; - -//(public) this^e -function bnPow(e) { return this.exp(e,new NullExp()); } - -//(protected) r = lower n words of "this * a", a.t <= n -//"this" should be the larger one if appropriate. -function bnpMultiplyLowerTo(a,n,r) { -var i = Math.min(this.t+a.t,n); -r.s = 0; // assumes a,this >= 0 -r.t = i; -while(i > 0) r.data[--i] = 0; -var j; -for(j = r.t-this.t; i < j; ++i) r.data[i+this.t] = this.am(0,a.data[i],r,i,0,this.t); -for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a.data[i],r,i,0,n-i); -r.clamp(); -} - -//(protected) r = "this * a" without lower n words, n > 0 -//"this" should be the larger one if appropriate. -function bnpMultiplyUpperTo(a,n,r) { ---n; -var i = r.t = this.t+a.t-n; -r.s = 0; // assumes a,this >= 0 -while(--i >= 0) r.data[i] = 0; -for(i = Math.max(n-this.t,0); i < a.t; ++i) - r.data[this.t+i-n] = this.am(n-i,a.data[i],r,0,0,this.t+i-n); -r.clamp(); -r.drShiftTo(1,r); -} - -//Barrett modular reduction -function Barrett(m) { -// setup Barrett -this.r2 = nbi(); -this.q3 = nbi(); -BigInteger$4.ONE.dlShiftTo(2*m.t,this.r2); -this.mu = this.r2.divide(m); -this.m = m; -} - -function barrettConvert(x) { -if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); -else if(x.compareTo(this.m) < 0) return x; -else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } -} - -function barrettRevert(x) { return x; } - -//x = x mod m (HAC 14.42) -function barrettReduce(x) { -x.drShiftTo(this.m.t-1,this.r2); -if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } -this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); -this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); -while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); -x.subTo(this.r2,x); -while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -//r = x^2 mod m; x != r -function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -//r = x*y mod m; x,y != r -function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Barrett.prototype.convert = barrettConvert; -Barrett.prototype.revert = barrettRevert; -Barrett.prototype.reduce = barrettReduce; -Barrett.prototype.mulTo = barrettMulTo; -Barrett.prototype.sqrTo = barrettSqrTo; - -//(public) this^e % m (HAC 14.85) -function bnModPow(e,m) { -var i = e.bitLength(), k, r = nbv(1), z; -if(i <= 0) return r; -else if(i < 18) k = 1; -else if(i < 48) k = 3; -else if(i < 144) k = 4; -else if(i < 768) k = 5; -else k = 6; -if(i < 8) - z = new Classic(m); -else if(m.isEven()) - z = new Barrett(m); -else - z = new Montgomery(m); - -// precomputation -var g = new Array(), n = 3, k1 = k-1, km = (1< 1) { - var g2 = nbi(); - z.sqrTo(g[1],g2); - while(n <= km) { - g[n] = nbi(); - z.mulTo(g2,g[n-2],g[n]); - n += 2; - } -} - -var j = e.t-1, w, is1 = true, r2 = nbi(), t; -i = nbits(e.data[j])-1; -while(j >= 0) { - if(i >= k1) w = (e.data[j]>>(i-k1))&km; - else { - w = (e.data[j]&((1<<(i+1))-1))<<(k1-i); - if(j > 0) w |= e.data[j-1]>>(this.DB+i-k1); - } - - n = k; - while((w&1) == 0) { w >>= 1; --n; } - if((i -= n) < 0) { i += this.DB; --j; } - if(is1) { // ret == 1, don't bother squaring or multiplying it - g[w].copyTo(r); - is1 = false; - } else { - while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } - if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } - z.mulTo(r2,g[w],r); - } - - while(j >= 0 && (e.data[j]&(1< 0) { - x.rShiftTo(g,x); - y.rShiftTo(g,y); -} -while(x.signum() > 0) { - if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); - if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); - if(x.compareTo(y) >= 0) { - x.subTo(y,x); - x.rShiftTo(1,x); - } else { - y.subTo(x,y); - y.rShiftTo(1,y); - } -} -if(g > 0) y.lShiftTo(g,y); -return y; -} - -//(protected) this % n, n < 2^26 -function bnpModInt(n) { -if(n <= 0) return 0; -var d = this.DV%n, r = (this.s<0)?n-1:0; -if(this.t > 0) - if(d == 0) r = this.data[0]%n; - else for(var i = this.t-1; i >= 0; --i) r = (d*r+this.data[i])%n; -return r; -} - -//(public) 1/this % m (HAC 14.61) -function bnModInverse(m) { -var ac = m.isEven(); -if((this.isEven() && ac) || m.signum() == 0) return BigInteger$4.ZERO; -var u = m.clone(), v = this.clone(); -var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); -while(u.signum() != 0) { - while(u.isEven()) { - u.rShiftTo(1,u); - if(ac) { - if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } - a.rShiftTo(1,a); - } else if(!b.isEven()) b.subTo(m,b); - b.rShiftTo(1,b); - } - while(v.isEven()) { - v.rShiftTo(1,v); - if(ac) { - if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } - c.rShiftTo(1,c); - } else if(!d.isEven()) d.subTo(m,d); - d.rShiftTo(1,d); - } - if(u.compareTo(v) >= 0) { - u.subTo(v,u); - if(ac) a.subTo(c,a); - b.subTo(d,b); - } else { - v.subTo(u,v); - if(ac) c.subTo(a,c); - d.subTo(b,d); - } -} -if(v.compareTo(BigInteger$4.ONE) != 0) return BigInteger$4.ZERO; -if(d.compareTo(m) >= 0) return d.subtract(m); -if(d.signum() < 0) d.addTo(m,d); else return d; -if(d.signum() < 0) return d.add(m); else return d; -} - -var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509]; -var lplim = (1<<26)/lowprimes[lowprimes.length-1]; - -//(public) test primality with certainty >= 1-.5^t -function bnIsProbablePrime(t) { -var i, x = this.abs(); -if(x.t == 1 && x.data[0] <= lowprimes[lowprimes.length-1]) { - for(i = 0; i < lowprimes.length; ++i) - if(x.data[0] == lowprimes[i]) return true; - return false; -} -if(x.isEven()) return false; -i = 1; -while(i < lowprimes.length) { - var m = lowprimes[i], j = i+1; - while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; - m = x.modInt(m); - while(i < j) if(m%lowprimes[i++] == 0) return false; -} -return x.millerRabin(t); -} - -//(protected) true if probably prime (HAC 4.24, Miller-Rabin) -function bnpMillerRabin(t) { -var n1 = this.subtract(BigInteger$4.ONE); -var k = n1.getLowestSetBit(); -if(k <= 0) return false; -var r = n1.shiftRight(k); -var prng = bnGetPrng(); -var a; -for(var i = 0; i < t; ++i) { - // select witness 'a' at random from between 1 and n1 - do { - a = new BigInteger$4(this.bitLength(), prng); - } - while(a.compareTo(BigInteger$4.ONE) <= 0 || a.compareTo(n1) >= 0); - var y = a.modPow(r,this); - if(y.compareTo(BigInteger$4.ONE) != 0 && y.compareTo(n1) != 0) { - var j = 1; - while(j++ < k && y.compareTo(n1) != 0) { - y = y.modPowInt(2,this); - if(y.compareTo(BigInteger$4.ONE) == 0) return false; - } - if(y.compareTo(n1) != 0) return false; - } -} -return true; -} - -// get pseudo random number generator -function bnGetPrng() { - // create prng with api that matches BigInteger secure random - return { - // x is an array to fill with bytes - nextBytes: function(x) { - for(var i = 0; i < x.length; ++i) { - x[i] = Math.floor(Math.random() * 0x0100); - } - } - }; -} - -//protected -BigInteger$4.prototype.chunkSize = bnpChunkSize; -BigInteger$4.prototype.toRadix = bnpToRadix; -BigInteger$4.prototype.fromRadix = bnpFromRadix; -BigInteger$4.prototype.fromNumber = bnpFromNumber; -BigInteger$4.prototype.bitwiseTo = bnpBitwiseTo; -BigInteger$4.prototype.changeBit = bnpChangeBit; -BigInteger$4.prototype.addTo = bnpAddTo; -BigInteger$4.prototype.dMultiply = bnpDMultiply; -BigInteger$4.prototype.dAddOffset = bnpDAddOffset; -BigInteger$4.prototype.multiplyLowerTo = bnpMultiplyLowerTo; -BigInteger$4.prototype.multiplyUpperTo = bnpMultiplyUpperTo; -BigInteger$4.prototype.modInt = bnpModInt; -BigInteger$4.prototype.millerRabin = bnpMillerRabin; - -//public -BigInteger$4.prototype.clone = bnClone; -BigInteger$4.prototype.intValue = bnIntValue; -BigInteger$4.prototype.byteValue = bnByteValue; -BigInteger$4.prototype.shortValue = bnShortValue; -BigInteger$4.prototype.signum = bnSigNum; -BigInteger$4.prototype.toByteArray = bnToByteArray; -BigInteger$4.prototype.equals = bnEquals; -BigInteger$4.prototype.min = bnMin; -BigInteger$4.prototype.max = bnMax; -BigInteger$4.prototype.and = bnAnd; -BigInteger$4.prototype.or = bnOr; -BigInteger$4.prototype.xor = bnXor; -BigInteger$4.prototype.andNot = bnAndNot; -BigInteger$4.prototype.not = bnNot; -BigInteger$4.prototype.shiftLeft = bnShiftLeft; -BigInteger$4.prototype.shiftRight = bnShiftRight; -BigInteger$4.prototype.getLowestSetBit = bnGetLowestSetBit; -BigInteger$4.prototype.bitCount = bnBitCount; -BigInteger$4.prototype.testBit = bnTestBit; -BigInteger$4.prototype.setBit = bnSetBit; -BigInteger$4.prototype.clearBit = bnClearBit; -BigInteger$4.prototype.flipBit = bnFlipBit; -BigInteger$4.prototype.add = bnAdd; -BigInteger$4.prototype.subtract = bnSubtract; -BigInteger$4.prototype.multiply = bnMultiply; -BigInteger$4.prototype.divide = bnDivide; -BigInteger$4.prototype.remainder = bnRemainder; -BigInteger$4.prototype.divideAndRemainder = bnDivideAndRemainder; -BigInteger$4.prototype.modPow = bnModPow; -BigInteger$4.prototype.modInverse = bnModInverse; -BigInteger$4.prototype.pow = bnPow; -BigInteger$4.prototype.gcd = bnGCD; -BigInteger$4.prototype.isProbablePrime = bnIsProbablePrime; - -/** - * Secure Hash Algorithm with 160-bit digest (SHA-1) implementation. - * - * @author Dave Longley - * - * Copyright (c) 2010-2015 Digital Bazaar, Inc. - */ - -var forge$l = forge$D; - - - -var sha1 = forge$l.sha1 = forge$l.sha1 || {}; -forge$l.md.sha1 = forge$l.md.algorithms.sha1 = sha1; - -/** - * Creates a SHA-1 message digest object. - * - * @return a message digest object. - */ -sha1.create = function() { - // do initialization as necessary - if(!_initialized$1) { - _init$1(); - } - - // SHA-1 state contains five 32-bit integers - var _state = null; - - // input buffer - var _input = forge$l.util.createBuffer(); - - // used for word storage - var _w = new Array(80); - - // message digest object - var md = { - algorithm: 'sha1', - blockLength: 64, - digestLength: 20, - // 56-bit length of message so far (does not including padding) - messageLength: 0, - // true message length - fullMessageLength: null, - // size of message length in bytes - messageLengthSize: 8 - }; - - /** - * Starts the digest. - * - * @return this digest object. - */ - md.start = function() { - // up to 56-bit message length for convenience - md.messageLength = 0; - - // full message length (set md.messageLength64 for backwards-compatibility) - md.fullMessageLength = md.messageLength64 = []; - var int32s = md.messageLengthSize / 4; - for(var i = 0; i < int32s; ++i) { - md.fullMessageLength.push(0); - } - _input = forge$l.util.createBuffer(); - _state = { - h0: 0x67452301, - h1: 0xEFCDAB89, - h2: 0x98BADCFE, - h3: 0x10325476, - h4: 0xC3D2E1F0 - }; - return md; - }; - // start digest automatically for first time - md.start(); - - /** - * Updates the digest with the given message input. The given input can - * treated as raw input (no encoding will be applied) or an encoding of - * 'utf8' maybe given to encode the input using UTF-8. - * - * @param msg the message input to update with. - * @param encoding the encoding to use (default: 'raw', other: 'utf8'). - * - * @return this digest object. - */ - md.update = function(msg, encoding) { - if(encoding === 'utf8') { - msg = forge$l.util.encodeUtf8(msg); - } - - // update message length - var len = msg.length; - md.messageLength += len; - len = [(len / 0x100000000) >>> 0, len >>> 0]; - for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { - md.fullMessageLength[i] += len[1]; - len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0); - md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; - len[0] = ((len[1] / 0x100000000) >>> 0); - } - - // add bytes to input buffer - _input.putBytes(msg); - - // process bytes - _update$1(_state, _w, _input); - - // compact input buffer every 2K or if empty - if(_input.read > 2048 || _input.length() === 0) { - _input.compact(); - } - - return md; - }; - - /** - * Produces the digest. - * - * @return a byte buffer containing the digest value. - */ - md.digest = function() { - /* Note: Here we copy the remaining bytes in the input buffer and - add the appropriate SHA-1 padding. Then we do the final update - on a copy of the state so that if the user wants to get - intermediate digests they can do so. */ - - /* Determine the number of bytes that must be added to the message - to ensure its length is congruent to 448 mod 512. In other words, - the data to be digested must be a multiple of 512 bits (or 128 bytes). - This data includes the message, some padding, and the length of the - message. Since the length of the message will be encoded as 8 bytes (64 - bits), that means that the last segment of the data must have 56 bytes - (448 bits) of message and padding. Therefore, the length of the message - plus the padding must be congruent to 448 mod 512 because - 512 - 128 = 448. - - In order to fill up the message length it must be filled with - padding that begins with 1 bit followed by all 0 bits. Padding - must *always* be present, so if the message length is already - congruent to 448 mod 512, then 512 padding bits must be added. */ - - var finalBlock = forge$l.util.createBuffer(); - finalBlock.putBytes(_input.bytes()); - - // compute remaining size to be digested (include message length size) - var remaining = ( - md.fullMessageLength[md.fullMessageLength.length - 1] + - md.messageLengthSize); - - // add padding for overflow blockSize - overflow - // _padding starts with 1 byte with first bit is set (byte value 128), then - // there may be up to (blockSize - 1) other pad bytes - var overflow = remaining & (md.blockLength - 1); - finalBlock.putBytes(_padding$1.substr(0, md.blockLength - overflow)); - - // serialize message length in bits in big-endian order; since length - // is stored in bytes we multiply by 8 and add carry from next int - var next, carry; - var bits = md.fullMessageLength[0] * 8; - for(var i = 0; i < md.fullMessageLength.length - 1; ++i) { - next = md.fullMessageLength[i + 1] * 8; - carry = (next / 0x100000000) >>> 0; - bits += carry; - finalBlock.putInt32(bits >>> 0); - bits = next >>> 0; - } - finalBlock.putInt32(bits); - - var s2 = { - h0: _state.h0, - h1: _state.h1, - h2: _state.h2, - h3: _state.h3, - h4: _state.h4 - }; - _update$1(s2, _w, finalBlock); - var rval = forge$l.util.createBuffer(); - rval.putInt32(s2.h0); - rval.putInt32(s2.h1); - rval.putInt32(s2.h2); - rval.putInt32(s2.h3); - rval.putInt32(s2.h4); - return rval; - }; - - return md; -}; - -// sha-1 padding bytes not initialized yet -var _padding$1 = null; -var _initialized$1 = false; - -/** - * Initializes the constant tables. - */ -function _init$1() { - // create padding - _padding$1 = String.fromCharCode(128); - _padding$1 += forge$l.util.fillString(String.fromCharCode(0x00), 64); - - // now initialized - _initialized$1 = true; -} - -/** - * Updates a SHA-1 state with the given byte buffer. - * - * @param s the SHA-1 state to update. - * @param w the array to use to store words. - * @param bytes the byte buffer to update with. - */ -function _update$1(s, w, bytes) { - // consume 512 bit (64 byte) chunks - var t, a, b, c, d, e, f, i; - var len = bytes.length(); - while(len >= 64) { - // the w array will be populated with sixteen 32-bit big-endian words - // and then extended into 80 32-bit words according to SHA-1 algorithm - // and for 32-79 using Max Locktyukhin's optimization - - // initialize hash value for this chunk - a = s.h0; - b = s.h1; - c = s.h2; - d = s.h3; - e = s.h4; - - // round 1 - for(i = 0; i < 16; ++i) { - t = bytes.getInt32(); - w[i] = t; - f = d ^ (b & (c ^ d)); - t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t; - e = d; - d = c; - // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug - c = ((b << 30) | (b >>> 2)) >>> 0; - b = a; - a = t; - } - for(; i < 20; ++i) { - t = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]); - t = (t << 1) | (t >>> 31); - w[i] = t; - f = d ^ (b & (c ^ d)); - t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t; - e = d; - d = c; - // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug - c = ((b << 30) | (b >>> 2)) >>> 0; - b = a; - a = t; - } - // round 2 - for(; i < 32; ++i) { - t = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]); - t = (t << 1) | (t >>> 31); - w[i] = t; - f = b ^ c ^ d; - t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t; - e = d; - d = c; - // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug - c = ((b << 30) | (b >>> 2)) >>> 0; - b = a; - a = t; - } - for(; i < 40; ++i) { - t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); - t = (t << 2) | (t >>> 30); - w[i] = t; - f = b ^ c ^ d; - t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t; - e = d; - d = c; - // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug - c = ((b << 30) | (b >>> 2)) >>> 0; - b = a; - a = t; - } - // round 3 - for(; i < 60; ++i) { - t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); - t = (t << 2) | (t >>> 30); - w[i] = t; - f = (b & c) | (d & (b ^ c)); - t = ((a << 5) | (a >>> 27)) + f + e + 0x8F1BBCDC + t; - e = d; - d = c; - // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug - c = ((b << 30) | (b >>> 2)) >>> 0; - b = a; - a = t; - } - // round 4 - for(; i < 80; ++i) { - t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]); - t = (t << 2) | (t >>> 30); - w[i] = t; - f = b ^ c ^ d; - t = ((a << 5) | (a >>> 27)) + f + e + 0xCA62C1D6 + t; - e = d; - d = c; - // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug - c = ((b << 30) | (b >>> 2)) >>> 0; - b = a; - a = t; - } - - // update hash state - s.h0 = (s.h0 + a) | 0; - s.h1 = (s.h1 + b) | 0; - s.h2 = (s.h2 + c) | 0; - s.h3 = (s.h3 + d) | 0; - s.h4 = (s.h4 + e) | 0; - - len -= 64; - } -} - -/** - * Partial implementation of PKCS#1 v2.2: RSA-OEAP - * - * Modified but based on the following MIT and BSD licensed code: - * - * https://github.com/kjur/jsjws/blob/master/rsa.js: - * - * The 'jsjws'(JSON Web Signature JavaScript Library) License - * - * Copyright (c) 2012 Kenji Urushima - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * http://webrsa.cvs.sourceforge.net/viewvc/webrsa/Client/RSAES-OAEP.js?content-type=text%2Fplain: - * - * RSAES-OAEP.js - * $Id: RSAES-OAEP.js,v 1.1.1.1 2003/03/19 15:37:20 ellispritchard Exp $ - * JavaScript Implementation of PKCS #1 v2.1 RSA CRYPTOGRAPHY STANDARD (RSA Laboratories, June 14, 2002) - * Copyright (C) Ellis Pritchard, Guardian Unlimited 2003. - * Contact: ellis@nukinetics.com - * Distributed under the BSD License. - * - * Official documentation: http://www.rsa.com/rsalabs/node.asp?id=2125 - * - * @author Evan Jones (http://evanjones.ca/) - * @author Dave Longley - * - * Copyright (c) 2013-2014 Digital Bazaar, Inc. - */ - -var forge$k = forge$D; - - - - -// shortcut for PKCS#1 API -var pkcs1 = forge$k.pkcs1 = forge$k.pkcs1 || {}; - -/** - * Encode the given RSAES-OAEP message (M) using key, with optional label (L) - * and seed. - * - * This method does not perform RSA encryption, it only encodes the message - * using RSAES-OAEP. - * - * @param key the RSA key to use. - * @param message the message to encode. - * @param options the options to use: - * label an optional label to use. - * seed the seed to use. - * md the message digest object to use, undefined for SHA-1. - * mgf1 optional mgf1 parameters: - * md the message digest object to use for MGF1. - * - * @return the encoded message bytes. - */ -pkcs1.encode_rsa_oaep = function(key, message, options) { - // parse arguments - var label; - var seed; - var md; - var mgf1Md; - // legacy args (label, seed, md) - if(typeof options === 'string') { - label = options; - seed = arguments[3] || undefined; - md = arguments[4] || undefined; - } else if(options) { - label = options.label || undefined; - seed = options.seed || undefined; - md = options.md || undefined; - if(options.mgf1 && options.mgf1.md) { - mgf1Md = options.mgf1.md; - } - } - - // default OAEP to SHA-1 message digest - if(!md) { - md = forge$k.md.sha1.create(); - } else { - md.start(); - } - - // default MGF-1 to same as OAEP - if(!mgf1Md) { - mgf1Md = md; - } - - // compute length in bytes and check output - var keyLength = Math.ceil(key.n.bitLength() / 8); - var maxLength = keyLength - 2 * md.digestLength - 2; - if(message.length > maxLength) { - var error = new Error('RSAES-OAEP input message length is too long.'); - error.length = message.length; - error.maxLength = maxLength; - throw error; - } - - if(!label) { - label = ''; - } - md.update(label, 'raw'); - var lHash = md.digest(); - - var PS = ''; - var PS_length = maxLength - message.length; - for(var i = 0; i < PS_length; i++) { - PS += '\x00'; - } - - var DB = lHash.getBytes() + PS + '\x01' + message; - - if(!seed) { - seed = forge$k.random.getBytes(md.digestLength); - } else if(seed.length !== md.digestLength) { - var error = new Error('Invalid RSAES-OAEP seed. The seed length must ' + - 'match the digest length.'); - error.seedLength = seed.length; - error.digestLength = md.digestLength; - throw error; - } - - var dbMask = rsa_mgf1(seed, keyLength - md.digestLength - 1, mgf1Md); - var maskedDB = forge$k.util.xorBytes(DB, dbMask, DB.length); - - var seedMask = rsa_mgf1(maskedDB, md.digestLength, mgf1Md); - var maskedSeed = forge$k.util.xorBytes(seed, seedMask, seed.length); - - // return encoded message - return '\x00' + maskedSeed + maskedDB; -}; - -/** - * Decode the given RSAES-OAEP encoded message (EM) using key, with optional - * label (L). - * - * This method does not perform RSA decryption, it only decodes the message - * using RSAES-OAEP. - * - * @param key the RSA key to use. - * @param em the encoded message to decode. - * @param options the options to use: - * label an optional label to use. - * md the message digest object to use for OAEP, undefined for SHA-1. - * mgf1 optional mgf1 parameters: - * md the message digest object to use for MGF1. - * - * @return the decoded message bytes. - */ -pkcs1.decode_rsa_oaep = function(key, em, options) { - // parse args - var label; - var md; - var mgf1Md; - // legacy args - if(typeof options === 'string') { - label = options; - md = arguments[3] || undefined; - } else if(options) { - label = options.label || undefined; - md = options.md || undefined; - if(options.mgf1 && options.mgf1.md) { - mgf1Md = options.mgf1.md; - } - } - - // compute length in bytes - var keyLength = Math.ceil(key.n.bitLength() / 8); - - if(em.length !== keyLength) { - var error = new Error('RSAES-OAEP encoded message length is invalid.'); - error.length = em.length; - error.expectedLength = keyLength; - throw error; - } - - // default OAEP to SHA-1 message digest - if(md === undefined) { - md = forge$k.md.sha1.create(); - } else { - md.start(); - } - - // default MGF-1 to same as OAEP - if(!mgf1Md) { - mgf1Md = md; - } - - if(keyLength < 2 * md.digestLength + 2) { - throw new Error('RSAES-OAEP key is too short for the hash function.'); - } - - if(!label) { - label = ''; - } - md.update(label, 'raw'); - var lHash = md.digest().getBytes(); - - // split the message into its parts - var y = em.charAt(0); - var maskedSeed = em.substring(1, md.digestLength + 1); - var maskedDB = em.substring(1 + md.digestLength); - - var seedMask = rsa_mgf1(maskedDB, md.digestLength, mgf1Md); - var seed = forge$k.util.xorBytes(maskedSeed, seedMask, maskedSeed.length); - - var dbMask = rsa_mgf1(seed, keyLength - md.digestLength - 1, mgf1Md); - var db = forge$k.util.xorBytes(maskedDB, dbMask, maskedDB.length); - - var lHashPrime = db.substring(0, md.digestLength); - - // constant time check that all values match what is expected - var error = (y !== '\x00'); - - // constant time check lHash vs lHashPrime - for(var i = 0; i < md.digestLength; ++i) { - error |= (lHash.charAt(i) !== lHashPrime.charAt(i)); - } - - // "constant time" find the 0x1 byte separating the padding (zeros) from the - // message - // TODO: It must be possible to do this in a better/smarter way? - var in_ps = 1; - var index = md.digestLength; - for(var j = md.digestLength; j < db.length; j++) { - var code = db.charCodeAt(j); - - var is_0 = (code & 0x1) ^ 0x1; - - // non-zero if not 0 or 1 in the ps section - var error_mask = in_ps ? 0xfffe : 0x0000; - error |= (code & error_mask); - - // latch in_ps to zero after we find 0x1 - in_ps = in_ps & is_0; - index += in_ps; - } - - if(error || db.charCodeAt(index) !== 0x1) { - throw new Error('Invalid RSAES-OAEP padding.'); - } - - return db.substring(index + 1); -}; - -function rsa_mgf1(seed, maskLength, hash) { - // default to SHA-1 message digest - if(!hash) { - hash = forge$k.md.sha1.create(); - } - var t = ''; - var count = Math.ceil(maskLength / hash.digestLength); - for(var i = 0; i < count; ++i) { - var c = String.fromCharCode( - (i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF); - hash.start(); - hash.update(seed + c); - t += hash.digest().getBytes(); - } - return t.substring(0, maskLength); -} - -/** - * Prime number generation API. - * - * @author Dave Longley - * - * Copyright (c) 2014 Digital Bazaar, Inc. - */ - -var forge$j = forge$D; - - - - -(function() { - -// forge.prime already defined -if(forge$j.prime) { - forge$j.prime; - return; -} - -/* PRIME API */ -var prime = forge$j.prime = forge$j.prime || {}; - -var BigInteger = forge$j.jsbn.BigInteger; - -// primes are 30k+i for i = 1, 7, 11, 13, 17, 19, 23, 29 -var GCD_30_DELTA = [6, 4, 2, 4, 2, 4, 6, 2]; -var THIRTY = new BigInteger(null); -THIRTY.fromInt(30); -var op_or = function(x, y) {return x|y;}; - -/** - * Generates a random probable prime with the given number of bits. - * - * Alternative algorithms can be specified by name as a string or as an - * object with custom options like so: - * - * { - * name: 'PRIMEINC', - * options: { - * maxBlockTime: , - * millerRabinTests: , - * workerScript: , - * workers: . - * workLoad: the size of the work load, ie: number of possible prime - * numbers for each web worker to check per work assignment, - * (default: 100). - * } - * } - * - * @param bits the number of bits for the prime number. - * @param options the options to use. - * [algorithm] the algorithm to use (default: 'PRIMEINC'). - * [prng] a custom crypto-secure pseudo-random number generator to use, - * that must define "getBytesSync". - * - * @return callback(err, num) called once the operation completes. - */ -prime.generateProbablePrime = function(bits, options, callback) { - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - // default to PRIMEINC algorithm - var algorithm = options.algorithm || 'PRIMEINC'; - if(typeof algorithm === 'string') { - algorithm = {name: algorithm}; - } - algorithm.options = algorithm.options || {}; - - // create prng with api that matches BigInteger secure random - var prng = options.prng || forge$j.random; - var rng = { - // x is an array to fill with bytes - nextBytes: function(x) { - var b = prng.getBytesSync(x.length); - for(var i = 0; i < x.length; ++i) { - x[i] = b.charCodeAt(i); - } - } - }; - - if(algorithm.name === 'PRIMEINC') { - return primeincFindPrime(bits, rng, algorithm.options, callback); - } - - throw new Error('Invalid prime generation algorithm: ' + algorithm.name); -}; - -function primeincFindPrime(bits, rng, options, callback) { - if('workers' in options) { - return primeincFindPrimeWithWorkers(bits, rng, options, callback); - } - return primeincFindPrimeWithoutWorkers(bits, rng, options, callback); -} - -function primeincFindPrimeWithoutWorkers(bits, rng, options, callback) { - // initialize random number - var num = generateRandom(bits, rng); - - /* Note: All primes are of the form 30k+i for i < 30 and gcd(30, i)=1. The - number we are given is always aligned at 30k + 1. Each time the number is - determined not to be prime we add to get to the next 'i', eg: if the number - was at 30k + 1 we add 6. */ - var deltaIdx = 0; - - // get required number of MR tests - var mrTests = getMillerRabinTests(num.bitLength()); - if('millerRabinTests' in options) { - mrTests = options.millerRabinTests; - } - - // find prime nearest to 'num' for maxBlockTime ms - // 10 ms gives 5ms of leeway for other calculations before dropping - // below 60fps (1000/60 == 16.67), but in reality, the number will - // likely be higher due to an 'atomic' big int modPow - var maxBlockTime = 10; - if('maxBlockTime' in options) { - maxBlockTime = options.maxBlockTime; - } - - _primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback); -} - -function _primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback) { - var start = +new Date(); - do { - // overflow, regenerate random number - if(num.bitLength() > bits) { - num = generateRandom(bits, rng); - } - // do primality test - if(num.isProbablePrime(mrTests)) { - return callback(null, num); - } - // get next potential prime - num.dAddOffset(GCD_30_DELTA[deltaIdx++ % 8], 0); - } while(maxBlockTime < 0 || (+new Date() - start < maxBlockTime)); - - // keep trying later - forge$j.util.setImmediate(function() { - _primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback); - }); -} - -// NOTE: This algorithm is indeterminate in nature because workers -// run in parallel looking at different segments of numbers. Even if this -// algorithm is run twice with the same input from a predictable RNG, it -// may produce different outputs. -function primeincFindPrimeWithWorkers(bits, rng, options, callback) { - // web workers unavailable - if(typeof Worker === 'undefined') { - return primeincFindPrimeWithoutWorkers(bits, rng, options, callback); - } - - // initialize random number - var num = generateRandom(bits, rng); - - // use web workers to generate keys - var numWorkers = options.workers; - var workLoad = options.workLoad || 100; - var range = workLoad * 30 / 8; - var workerScript = options.workerScript || 'forge/prime.worker.js'; - if(numWorkers === -1) { - return forge$j.util.estimateCores(function(err, cores) { - if(err) { - // default to 2 - cores = 2; - } - numWorkers = cores - 1; - generate(); - }); - } - generate(); - - function generate() { - // require at least 1 worker - numWorkers = Math.max(1, numWorkers); - - // TODO: consider optimizing by starting workers outside getPrime() ... - // note that in order to clean up they will have to be made internally - // asynchronous which may actually be slower - - // start workers immediately - var workers = []; - for(var i = 0; i < numWorkers; ++i) { - // FIXME: fix path or use blob URLs - workers[i] = new Worker(workerScript); - } - - // listen for requests from workers and assign ranges to find prime - for(var i = 0; i < numWorkers; ++i) { - workers[i].addEventListener('message', workerMessage); - } - - /* Note: The distribution of random numbers is unknown. Therefore, each - web worker is continuously allocated a range of numbers to check for a - random number until one is found. - - Every 30 numbers will be checked just 8 times, because prime numbers - have the form: - - 30k+i, for i < 30 and gcd(30, i)=1 (there are 8 values of i for this) - - Therefore, if we want a web worker to run N checks before asking for - a new range of numbers, each range must contain N*30/8 numbers. - - For 100 checks (workLoad), this is a range of 375. */ - - var found = false; - function workerMessage(e) { - // ignore message, prime already found - if(found) { - return; - } - var data = e.data; - if(data.found) { - // terminate all workers - for(var i = 0; i < workers.length; ++i) { - workers[i].terminate(); - } - found = true; - return callback(null, new BigInteger(data.prime, 16)); - } - - // overflow, regenerate random number - if(num.bitLength() > bits) { - num = generateRandom(bits, rng); - } - - // assign new range to check - var hex = num.toString(16); - - // start prime search - e.target.postMessage({ - hex: hex, - workLoad: workLoad - }); - - num.dAddOffset(range, 0); - } - } -} - -/** - * Generates a random number using the given number of bits and RNG. - * - * @param bits the number of bits for the number. - * @param rng the random number generator to use. - * - * @return the random number. - */ -function generateRandom(bits, rng) { - var num = new BigInteger(bits, rng); - // force MSB set - var bits1 = bits - 1; - if(!num.testBit(bits1)) { - num.bitwiseTo(BigInteger.ONE.shiftLeft(bits1), op_or, num); - } - // align number on 30k+1 boundary - num.dAddOffset(31 - num.mod(THIRTY).byteValue(), 0); - return num; -} - -/** - * Returns the required number of Miller-Rabin tests to generate a - * prime with an error probability of (1/2)^80. - * - * See Handbook of Applied Cryptography Chapter 4, Table 4.4. - * - * @param bits the bit size. - * - * @return the required number of iterations. - */ -function getMillerRabinTests(bits) { - if(bits <= 100) return 27; - if(bits <= 150) return 18; - if(bits <= 200) return 15; - if(bits <= 250) return 12; - if(bits <= 300) return 9; - if(bits <= 350) return 8; - if(bits <= 400) return 7; - if(bits <= 500) return 6; - if(bits <= 600) return 5; - if(bits <= 800) return 4; - if(bits <= 1250) return 3; - return 2; -} - -})(); - -/** - * Javascript implementation of basic RSA algorithms. - * - * @author Dave Longley - * - * Copyright (c) 2010-2014 Digital Bazaar, Inc. - * - * The only algorithm currently supported for PKI is RSA. - * - * An RSA key is often stored in ASN.1 DER format. The SubjectPublicKeyInfo - * ASN.1 structure is composed of an algorithm of type AlgorithmIdentifier - * and a subjectPublicKey of type bit string. - * - * The AlgorithmIdentifier contains an Object Identifier (OID) and parameters - * for the algorithm, if any. In the case of RSA, there aren't any. - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING - * } - * - * AlgorithmIdentifer ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - * - * For an RSA public key, the subjectPublicKey is: - * - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL - * } - * - * Version ::= INTEGER - * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - * PrivateKey ::= OCTET STRING - * Attributes ::= SET OF Attribute - * - * An RSA private key as the following structure: - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER -- (inverse of q) mod p - * } - * - * Version ::= INTEGER - * - * The OID for the RSA key algorithm is: 1.2.840.113549.1.1.1 - */ - -var forge$i = forge$D; - - - - - - - - -if(typeof BigInteger$3 === 'undefined') { - var BigInteger$3 = forge$i.jsbn.BigInteger; -} - -var _crypto = forge$i.util.isNodejs ? require$$1$1 : null; - -// shortcut for asn.1 API -var asn1$7 = forge$i.asn1; - -// shortcut for util API -var util = forge$i.util; - -/* - * RSA encryption and decryption, see RFC 2313. - */ -forge$i.pki = forge$i.pki || {}; -forge$i.pki.rsa = forge$i.rsa = forge$i.rsa || {}; -var pki$4 = forge$i.pki; - -// for finding primes, which are 30k+i for i = 1, 7, 11, 13, 17, 19, 23, 29 -var GCD_30_DELTA = [6, 4, 2, 4, 2, 4, 6, 2]; - -// validator for a PrivateKeyInfo structure -var privateKeyValidator$1 = { - // PrivateKeyInfo - name: 'PrivateKeyInfo', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - value: [{ - // Version (INTEGER) - name: 'PrivateKeyInfo.version', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyVersion' - }, { - // privateKeyAlgorithm - name: 'PrivateKeyInfo.privateKeyAlgorithm', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'AlgorithmIdentifier.algorithm', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.OID, - constructed: false, - capture: 'privateKeyOid' - }] - }, { - // PrivateKey - name: 'PrivateKeyInfo', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.OCTETSTRING, - constructed: false, - capture: 'privateKey' - }] -}; - -// validator for an RSA private key -var rsaPrivateKeyValidator = { - // RSAPrivateKey - name: 'RSAPrivateKey', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - value: [{ - // Version (INTEGER) - name: 'RSAPrivateKey.version', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyVersion' - }, { - // modulus (n) - name: 'RSAPrivateKey.modulus', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyModulus' - }, { - // publicExponent (e) - name: 'RSAPrivateKey.publicExponent', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyPublicExponent' - }, { - // privateExponent (d) - name: 'RSAPrivateKey.privateExponent', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyPrivateExponent' - }, { - // prime1 (p) - name: 'RSAPrivateKey.prime1', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyPrime1' - }, { - // prime2 (q) - name: 'RSAPrivateKey.prime2', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyPrime2' - }, { - // exponent1 (d mod (p-1)) - name: 'RSAPrivateKey.exponent1', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyExponent1' - }, { - // exponent2 (d mod (q-1)) - name: 'RSAPrivateKey.exponent2', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyExponent2' - }, { - // coefficient ((inverse of q) mod p) - name: 'RSAPrivateKey.coefficient', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'privateKeyCoefficient' - }] -}; - -// validator for an RSA public key -var rsaPublicKeyValidator = { - // RSAPublicKey - name: 'RSAPublicKey', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - value: [{ - // modulus (n) - name: 'RSAPublicKey.modulus', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'publicKeyModulus' - }, { - // publicExponent (e) - name: 'RSAPublicKey.exponent', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.INTEGER, - constructed: false, - capture: 'publicKeyExponent' - }] -}; - -// validator for an SubjectPublicKeyInfo structure -// Note: Currently only works with an RSA public key -var publicKeyValidator$2 = forge$i.pki.rsa.publicKeyValidator = { - name: 'SubjectPublicKeyInfo', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - captureAsn1: 'subjectPublicKeyInfo', - value: [{ - name: 'SubjectPublicKeyInfo.AlgorithmIdentifier', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'AlgorithmIdentifier.algorithm', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.OID, - constructed: false, - capture: 'publicKeyOid' - }] - }, { - // subjectPublicKey - name: 'SubjectPublicKeyInfo.subjectPublicKey', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.BITSTRING, - constructed: false, - value: [{ - // RSAPublicKey - name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - optional: true, - captureAsn1: 'rsaPublicKey' - }] - }] -}; - -// validator for a DigestInfo structure -var digestInfoValidator = { - name: 'DigestInfo', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'DigestInfo.DigestAlgorithm', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'DigestInfo.DigestAlgorithm.algorithmIdentifier', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.OID, - constructed: false, - capture: 'algorithmIdentifier' - }, { - // NULL paramters - name: 'DigestInfo.DigestAlgorithm.parameters', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.NULL, - // captured only to check existence for md2 and md5 - capture: 'parameters', - optional: true, - constructed: false - }] - }, { - // digest - name: 'DigestInfo.digest', - tagClass: asn1$7.Class.UNIVERSAL, - type: asn1$7.Type.OCTETSTRING, - constructed: false, - capture: 'digest' - }] -}; - -/** - * Wrap digest in DigestInfo object. - * - * This function implements EMSA-PKCS1-v1_5-ENCODE as per RFC 3447. - * - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest - * } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * Digest ::= OCTET STRING - * - * @param md the message digest object with the hash to sign. - * - * @return the encoded message (ready for RSA encrytion) - */ -var emsaPkcs1v15encode = function(md) { - // get the oid for the algorithm - var oid; - if(md.algorithm in pki$4.oids) { - oid = pki$4.oids[md.algorithm]; - } else { - var error = new Error('Unknown message digest algorithm.'); - error.algorithm = md.algorithm; - throw error; - } - var oidBytes = asn1$7.oidToDer(oid).getBytes(); - - // create the digest info - var digestInfo = asn1$7.create( - asn1$7.Class.UNIVERSAL, asn1$7.Type.SEQUENCE, true, []); - var digestAlgorithm = asn1$7.create( - asn1$7.Class.UNIVERSAL, asn1$7.Type.SEQUENCE, true, []); - digestAlgorithm.value.push(asn1$7.create( - asn1$7.Class.UNIVERSAL, asn1$7.Type.OID, false, oidBytes)); - digestAlgorithm.value.push(asn1$7.create( - asn1$7.Class.UNIVERSAL, asn1$7.Type.NULL, false, '')); - var digest = asn1$7.create( - asn1$7.Class.UNIVERSAL, asn1$7.Type.OCTETSTRING, - false, md.digest().getBytes()); - digestInfo.value.push(digestAlgorithm); - digestInfo.value.push(digest); - - // encode digest info - return asn1$7.toDer(digestInfo).getBytes(); -}; - -/** - * Performs x^c mod n (RSA encryption or decryption operation). - * - * @param x the number to raise and mod. - * @param key the key to use. - * @param pub true if the key is public, false if private. - * - * @return the result of x^c mod n. - */ -var _modPow = function(x, key, pub) { - if(pub) { - return x.modPow(key.e, key.n); - } - - if(!key.p || !key.q) { - // allow calculation without CRT params (slow) - return x.modPow(key.d, key.n); - } - - // pre-compute dP, dQ, and qInv if necessary - if(!key.dP) { - key.dP = key.d.mod(key.p.subtract(BigInteger$3.ONE)); - } - if(!key.dQ) { - key.dQ = key.d.mod(key.q.subtract(BigInteger$3.ONE)); - } - if(!key.qInv) { - key.qInv = key.q.modInverse(key.p); - } - - /* Chinese remainder theorem (CRT) states: - - Suppose n1, n2, ..., nk are positive integers which are pairwise - coprime (n1 and n2 have no common factors other than 1). For any - integers x1, x2, ..., xk there exists an integer x solving the - system of simultaneous congruences (where ~= means modularly - congruent so a ~= b mod n means a mod n = b mod n): - - x ~= x1 mod n1 - x ~= x2 mod n2 - ... - x ~= xk mod nk - - This system of congruences has a single simultaneous solution x - between 0 and n - 1. Furthermore, each xk solution and x itself - is congruent modulo the product n = n1*n2*...*nk. - So x1 mod n = x2 mod n = xk mod n = x mod n. - - The single simultaneous solution x can be solved with the following - equation: - - x = sum(xi*ri*si) mod n where ri = n/ni and si = ri^-1 mod ni. - - Where x is less than n, xi = x mod ni. - - For RSA we are only concerned with k = 2. The modulus n = pq, where - p and q are coprime. The RSA decryption algorithm is: - - y = x^d mod n - - Given the above: - - x1 = x^d mod p - r1 = n/p = q - s1 = q^-1 mod p - x2 = x^d mod q - r2 = n/q = p - s2 = p^-1 mod q - - So y = (x1r1s1 + x2r2s2) mod n - = ((x^d mod p)q(q^-1 mod p) + (x^d mod q)p(p^-1 mod q)) mod n - - According to Fermat's Little Theorem, if the modulus P is prime, - for any integer A not evenly divisible by P, A^(P-1) ~= 1 mod P. - Since A is not divisible by P it follows that if: - N ~= M mod (P - 1), then A^N mod P = A^M mod P. Therefore: - - A^N mod P = A^(M mod (P - 1)) mod P. (The latter takes less effort - to calculate). In order to calculate x^d mod p more quickly the - exponent d mod (p - 1) is stored in the RSA private key (the same - is done for x^d mod q). These values are referred to as dP and dQ - respectively. Therefore we now have: - - y = ((x^dP mod p)q(q^-1 mod p) + (x^dQ mod q)p(p^-1 mod q)) mod n - - Since we'll be reducing x^dP by modulo p (same for q) we can also - reduce x by p (and q respectively) before hand. Therefore, let - - xp = ((x mod p)^dP mod p), and - xq = ((x mod q)^dQ mod q), yielding: - - y = (xp*q*(q^-1 mod p) + xq*p*(p^-1 mod q)) mod n - - This can be further reduced to a simple algorithm that only - requires 1 inverse (the q inverse is used) to be used and stored. - The algorithm is called Garner's algorithm. If qInv is the - inverse of q, we simply calculate: - - y = (qInv*(xp - xq) mod p) * q + xq - - However, there are two further complications. First, we need to - ensure that xp > xq to prevent signed BigIntegers from being used - so we add p until this is true (since we will be mod'ing with - p anyway). Then, there is a known timing attack on algorithms - using the CRT. To mitigate this risk, "cryptographic blinding" - should be used. This requires simply generating a random number r - between 0 and n-1 and its inverse and multiplying x by r^e before - calculating y and then multiplying y by r^-1 afterwards. Note that - r must be coprime with n (gcd(r, n) === 1) in order to have an - inverse. - */ - - // cryptographic blinding - var r; - do { - r = new BigInteger$3( - forge$i.util.bytesToHex(forge$i.random.getBytes(key.n.bitLength() / 8)), - 16); - } while(r.compareTo(key.n) >= 0 || !r.gcd(key.n).equals(BigInteger$3.ONE)); - x = x.multiply(r.modPow(key.e, key.n)).mod(key.n); - - // calculate xp and xq - var xp = x.mod(key.p).modPow(key.dP, key.p); - var xq = x.mod(key.q).modPow(key.dQ, key.q); - - // xp must be larger than xq to avoid signed bit usage - while(xp.compareTo(xq) < 0) { - xp = xp.add(key.p); - } - - // do last step - var y = xp.subtract(xq) - .multiply(key.qInv).mod(key.p) - .multiply(key.q).add(xq); - - // remove effect of random for cryptographic blinding - y = y.multiply(r.modInverse(key.n)).mod(key.n); - - return y; -}; - -/** - * NOTE: THIS METHOD IS DEPRECATED, use 'sign' on a private key object or - * 'encrypt' on a public key object instead. - * - * Performs RSA encryption. - * - * The parameter bt controls whether to put padding bytes before the - * message passed in. Set bt to either true or false to disable padding - * completely (in order to handle e.g. EMSA-PSS encoding seperately before), - * signaling whether the encryption operation is a public key operation - * (i.e. encrypting data) or not, i.e. private key operation (data signing). - * - * For PKCS#1 v1.5 padding pass in the block type to use, i.e. either 0x01 - * (for signing) or 0x02 (for encryption). The key operation mode (private - * or public) is derived from this flag in that case). - * - * @param m the message to encrypt as a byte string. - * @param key the RSA key to use. - * @param bt for PKCS#1 v1.5 padding, the block type to use - * (0x01 for private key, 0x02 for public), - * to disable padding: true = public key, false = private key. - * - * @return the encrypted bytes as a string. - */ -pki$4.rsa.encrypt = function(m, key, bt) { - var pub = bt; - var eb; - - // get the length of the modulus in bytes - var k = Math.ceil(key.n.bitLength() / 8); - - if(bt !== false && bt !== true) { - // legacy, default to PKCS#1 v1.5 padding - pub = (bt === 0x02); - eb = _encodePkcs1_v1_5(m, key, bt); - } else { - eb = forge$i.util.createBuffer(); - eb.putBytes(m); - } - - // load encryption block as big integer 'x' - // FIXME: hex conversion inefficient, get BigInteger w/byte strings - var x = new BigInteger$3(eb.toHex(), 16); - - // do RSA encryption - var y = _modPow(x, key, pub); - - // convert y into the encrypted data byte string, if y is shorter in - // bytes than k, then prepend zero bytes to fill up ed - // FIXME: hex conversion inefficient, get BigInteger w/byte strings - var yhex = y.toString(16); - var ed = forge$i.util.createBuffer(); - var zeros = k - Math.ceil(yhex.length / 2); - while(zeros > 0) { - ed.putByte(0x00); - --zeros; - } - ed.putBytes(forge$i.util.hexToBytes(yhex)); - return ed.getBytes(); -}; - -/** - * NOTE: THIS METHOD IS DEPRECATED, use 'decrypt' on a private key object or - * 'verify' on a public key object instead. - * - * Performs RSA decryption. - * - * The parameter ml controls whether to apply PKCS#1 v1.5 padding - * or not. Set ml = false to disable padding removal completely - * (in order to handle e.g. EMSA-PSS later on) and simply pass back - * the RSA encryption block. - * - * @param ed the encrypted data to decrypt in as a byte string. - * @param key the RSA key to use. - * @param pub true for a public key operation, false for private. - * @param ml the message length, if known, false to disable padding. - * - * @return the decrypted message as a byte string. - */ -pki$4.rsa.decrypt = function(ed, key, pub, ml) { - // get the length of the modulus in bytes - var k = Math.ceil(key.n.bitLength() / 8); - - // error if the length of the encrypted data ED is not k - if(ed.length !== k) { - var error = new Error('Encrypted message length is invalid.'); - error.length = ed.length; - error.expected = k; - throw error; - } - - // convert encrypted data into a big integer - // FIXME: hex conversion inefficient, get BigInteger w/byte strings - var y = new BigInteger$3(forge$i.util.createBuffer(ed).toHex(), 16); - - // y must be less than the modulus or it wasn't the result of - // a previous mod operation (encryption) using that modulus - if(y.compareTo(key.n) >= 0) { - throw new Error('Encrypted message is invalid.'); - } - - // do RSA decryption - var x = _modPow(y, key, pub); - - // create the encryption block, if x is shorter in bytes than k, then - // prepend zero bytes to fill up eb - // FIXME: hex conversion inefficient, get BigInteger w/byte strings - var xhex = x.toString(16); - var eb = forge$i.util.createBuffer(); - var zeros = k - Math.ceil(xhex.length / 2); - while(zeros > 0) { - eb.putByte(0x00); - --zeros; - } - eb.putBytes(forge$i.util.hexToBytes(xhex)); - - if(ml !== false) { - // legacy, default to PKCS#1 v1.5 padding - return _decodePkcs1_v1_5(eb.getBytes(), key, pub); - } - - // return message - return eb.getBytes(); -}; - -/** - * Creates an RSA key-pair generation state object. It is used to allow - * key-generation to be performed in steps. It also allows for a UI to - * display progress updates. - * - * @param bits the size for the private key in bits, defaults to 2048. - * @param e the public exponent to use, defaults to 65537 (0x10001). - * @param [options] the options to use. - * prng a custom crypto-secure pseudo-random number generator to use, - * that must define "getBytesSync". - * algorithm the algorithm to use (default: 'PRIMEINC'). - * - * @return the state object to use to generate the key-pair. - */ -pki$4.rsa.createKeyPairGenerationState = function(bits, e, options) { - // TODO: migrate step-based prime generation code to forge.prime - - // set default bits - if(typeof(bits) === 'string') { - bits = parseInt(bits, 10); - } - bits = bits || 2048; - - // create prng with api that matches BigInteger secure random - options = options || {}; - var prng = options.prng || forge$i.random; - var rng = { - // x is an array to fill with bytes - nextBytes: function(x) { - var b = prng.getBytesSync(x.length); - for(var i = 0; i < x.length; ++i) { - x[i] = b.charCodeAt(i); - } - } - }; - - var algorithm = options.algorithm || 'PRIMEINC'; - - // create PRIMEINC algorithm state - var rval; - if(algorithm === 'PRIMEINC') { - rval = { - algorithm: algorithm, - state: 0, - bits: bits, - rng: rng, - eInt: e || 65537, - e: new BigInteger$3(null), - p: null, - q: null, - qBits: bits >> 1, - pBits: bits - (bits >> 1), - pqState: 0, - num: null, - keys: null - }; - rval.e.fromInt(rval.eInt); - } else { - throw new Error('Invalid key generation algorithm: ' + algorithm); - } - - return rval; -}; - -/** - * Attempts to runs the key-generation algorithm for at most n seconds - * (approximately) using the given state. When key-generation has completed, - * the keys will be stored in state.keys. - * - * To use this function to update a UI while generating a key or to prevent - * causing browser lockups/warnings, set "n" to a value other than 0. A - * simple pattern for generating a key and showing a progress indicator is: - * - * var state = pki.rsa.createKeyPairGenerationState(2048); - * var step = function() { - * // step key-generation, run algorithm for 100 ms, repeat - * if(!forge.pki.rsa.stepKeyPairGenerationState(state, 100)) { - * setTimeout(step, 1); - * } else { - * // key-generation complete - * // TODO: turn off progress indicator here - * // TODO: use the generated key-pair in "state.keys" - * } - * }; - * // TODO: turn on progress indicator here - * setTimeout(step, 0); - * - * @param state the state to use. - * @param n the maximum number of milliseconds to run the algorithm for, 0 - * to run the algorithm to completion. - * - * @return true if the key-generation completed, false if not. - */ -pki$4.rsa.stepKeyPairGenerationState = function(state, n) { - // set default algorithm if not set - if(!('algorithm' in state)) { - state.algorithm = 'PRIMEINC'; - } - - // TODO: migrate step-based prime generation code to forge.prime - // TODO: abstract as PRIMEINC algorithm - - // do key generation (based on Tom Wu's rsa.js, see jsbn.js license) - // with some minor optimizations and designed to run in steps - - // local state vars - var THIRTY = new BigInteger$3(null); - THIRTY.fromInt(30); - var deltaIdx = 0; - var op_or = function(x, y) {return x | y;}; - - // keep stepping until time limit is reached or done - var t1 = +new Date(); - var t2; - var total = 0; - while(state.keys === null && (n <= 0 || total < n)) { - // generate p or q - if(state.state === 0) { - /* Note: All primes are of the form: - - 30k+i, for i < 30 and gcd(30, i)=1, where there are 8 values for i - - When we generate a random number, we always align it at 30k + 1. Each - time the number is determined not to be prime we add to get to the - next 'i', eg: if the number was at 30k + 1 we add 6. */ - var bits = (state.p === null) ? state.pBits : state.qBits; - var bits1 = bits - 1; - - // get a random number - if(state.pqState === 0) { - state.num = new BigInteger$3(bits, state.rng); - // force MSB set - if(!state.num.testBit(bits1)) { - state.num.bitwiseTo( - BigInteger$3.ONE.shiftLeft(bits1), op_or, state.num); - } - // align number on 30k+1 boundary - state.num.dAddOffset(31 - state.num.mod(THIRTY).byteValue(), 0); - deltaIdx = 0; - - ++state.pqState; - } else if(state.pqState === 1) { - // try to make the number a prime - if(state.num.bitLength() > bits) { - // overflow, try again - state.pqState = 0; - // do primality test - } else if(state.num.isProbablePrime( - _getMillerRabinTests(state.num.bitLength()))) { - ++state.pqState; - } else { - // get next potential prime - state.num.dAddOffset(GCD_30_DELTA[deltaIdx++ % 8], 0); - } - } else if(state.pqState === 2) { - // ensure number is coprime with e - state.pqState = - (state.num.subtract(BigInteger$3.ONE).gcd(state.e) - .compareTo(BigInteger$3.ONE) === 0) ? 3 : 0; - } else if(state.pqState === 3) { - // store p or q - state.pqState = 0; - if(state.p === null) { - state.p = state.num; - } else { - state.q = state.num; - } - - // advance state if both p and q are ready - if(state.p !== null && state.q !== null) { - ++state.state; - } - state.num = null; - } - } else if(state.state === 1) { - // ensure p is larger than q (swap them if not) - if(state.p.compareTo(state.q) < 0) { - state.num = state.p; - state.p = state.q; - state.q = state.num; - } - ++state.state; - } else if(state.state === 2) { - // compute phi: (p - 1)(q - 1) (Euler's totient function) - state.p1 = state.p.subtract(BigInteger$3.ONE); - state.q1 = state.q.subtract(BigInteger$3.ONE); - state.phi = state.p1.multiply(state.q1); - ++state.state; - } else if(state.state === 3) { - // ensure e and phi are coprime - if(state.phi.gcd(state.e).compareTo(BigInteger$3.ONE) === 0) { - // phi and e are coprime, advance - ++state.state; - } else { - // phi and e aren't coprime, so generate a new p and q - state.p = null; - state.q = null; - state.state = 0; - } - } else if(state.state === 4) { - // create n, ensure n is has the right number of bits - state.n = state.p.multiply(state.q); - - // ensure n is right number of bits - if(state.n.bitLength() === state.bits) { - // success, advance - ++state.state; - } else { - // failed, get new q - state.q = null; - state.state = 0; - } - } else if(state.state === 5) { - // set keys - var d = state.e.modInverse(state.phi); - state.keys = { - privateKey: pki$4.rsa.setPrivateKey( - state.n, state.e, d, state.p, state.q, - d.mod(state.p1), d.mod(state.q1), - state.q.modInverse(state.p)), - publicKey: pki$4.rsa.setPublicKey(state.n, state.e) - }; - } - - // update timing - t2 = +new Date(); - total += t2 - t1; - t1 = t2; - } - - return state.keys !== null; -}; - -/** - * Generates an RSA public-private key pair in a single call. - * - * To generate a key-pair in steps (to allow for progress updates and to - * prevent blocking or warnings in slow browsers) then use the key-pair - * generation state functions. - * - * To generate a key-pair asynchronously (either through web-workers, if - * available, or by breaking up the work on the main thread), pass a - * callback function. - * - * @param [bits] the size for the private key in bits, defaults to 2048. - * @param [e] the public exponent to use, defaults to 65537. - * @param [options] options for key-pair generation, if given then 'bits' - * and 'e' must *not* be given: - * bits the size for the private key in bits, (default: 2048). - * e the public exponent to use, (default: 65537 (0x10001)). - * workerScript the worker script URL. - * workers the number of web workers (if supported) to use, - * (default: 2). - * workLoad the size of the work load, ie: number of possible prime - * numbers for each web worker to check per work assignment, - * (default: 100). - * prng a custom crypto-secure pseudo-random number generator to use, - * that must define "getBytesSync". Disables use of native APIs. - * algorithm the algorithm to use (default: 'PRIMEINC'). - * @param [callback(err, keypair)] called once the operation completes. - * - * @return an object with privateKey and publicKey properties. - */ -pki$4.rsa.generateKeyPair = function(bits, e, options, callback) { - // (bits), (options), (callback) - if(arguments.length === 1) { - if(typeof bits === 'object') { - options = bits; - bits = undefined; - } else if(typeof bits === 'function') { - callback = bits; - bits = undefined; - } - } else if(arguments.length === 2) { - // (bits, e), (bits, options), (bits, callback), (options, callback) - if(typeof bits === 'number') { - if(typeof e === 'function') { - callback = e; - e = undefined; - } else if(typeof e !== 'number') { - options = e; - e = undefined; - } - } else { - options = bits; - callback = e; - bits = undefined; - e = undefined; - } - } else if(arguments.length === 3) { - // (bits, e, options), (bits, e, callback), (bits, options, callback) - if(typeof e === 'number') { - if(typeof options === 'function') { - callback = options; - options = undefined; - } - } else { - callback = options; - options = e; - e = undefined; - } - } - options = options || {}; - if(bits === undefined) { - bits = options.bits || 2048; - } - if(e === undefined) { - e = options.e || 0x10001; - } - - // use native code if permitted, available, and parameters are acceptable - if(!forge$i.options.usePureJavaScript && !options.prng && - bits >= 256 && bits <= 16384 && (e === 0x10001 || e === 3)) { - if(callback) { - // try native async - if(_detectNodeCrypto('generateKeyPair')) { - return _crypto.generateKeyPair('rsa', { - modulusLength: bits, - publicExponent: e, - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem' - } - }, function(err, pub, priv) { - if(err) { - return callback(err); - } - callback(null, { - privateKey: pki$4.privateKeyFromPem(priv), - publicKey: pki$4.publicKeyFromPem(pub) - }); - }); - } - if(_detectSubtleCrypto('generateKey') && - _detectSubtleCrypto('exportKey')) { - // use standard native generateKey - return util.globalScope.crypto.subtle.generateKey({ - name: 'RSASSA-PKCS1-v1_5', - modulusLength: bits, - publicExponent: _intToUint8Array(e), - hash: {name: 'SHA-256'} - }, true /* key can be exported*/, ['sign', 'verify']) - .then(function(pair) { - return util.globalScope.crypto.subtle.exportKey( - 'pkcs8', pair.privateKey); - // avoiding catch(function(err) {...}) to support IE <= 8 - }).then(undefined, function(err) { - callback(err); - }).then(function(pkcs8) { - if(pkcs8) { - var privateKey = pki$4.privateKeyFromAsn1( - asn1$7.fromDer(forge$i.util.createBuffer(pkcs8))); - callback(null, { - privateKey: privateKey, - publicKey: pki$4.setRsaPublicKey(privateKey.n, privateKey.e) - }); - } - }); - } - if(_detectSubtleMsCrypto('generateKey') && - _detectSubtleMsCrypto('exportKey')) { - var genOp = util.globalScope.msCrypto.subtle.generateKey({ - name: 'RSASSA-PKCS1-v1_5', - modulusLength: bits, - publicExponent: _intToUint8Array(e), - hash: {name: 'SHA-256'} - }, true /* key can be exported*/, ['sign', 'verify']); - genOp.oncomplete = function(e) { - var pair = e.target.result; - var exportOp = util.globalScope.msCrypto.subtle.exportKey( - 'pkcs8', pair.privateKey); - exportOp.oncomplete = function(e) { - var pkcs8 = e.target.result; - var privateKey = pki$4.privateKeyFromAsn1( - asn1$7.fromDer(forge$i.util.createBuffer(pkcs8))); - callback(null, { - privateKey: privateKey, - publicKey: pki$4.setRsaPublicKey(privateKey.n, privateKey.e) - }); - }; - exportOp.onerror = function(err) { - callback(err); - }; - }; - genOp.onerror = function(err) { - callback(err); - }; - return; - } - } else { - // try native sync - if(_detectNodeCrypto('generateKeyPairSync')) { - var keypair = _crypto.generateKeyPairSync('rsa', { - modulusLength: bits, - publicExponent: e, - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem' - } - }); - return { - privateKey: pki$4.privateKeyFromPem(keypair.privateKey), - publicKey: pki$4.publicKeyFromPem(keypair.publicKey) - }; - } - } - } - - // use JavaScript implementation - var state = pki$4.rsa.createKeyPairGenerationState(bits, e, options); - if(!callback) { - pki$4.rsa.stepKeyPairGenerationState(state, 0); - return state.keys; - } - _generateKeyPair(state, options, callback); -}; - -/** - * Sets an RSA public key from BigIntegers modulus and exponent. - * - * @param n the modulus. - * @param e the exponent. - * - * @return the public key. - */ -pki$4.setRsaPublicKey = pki$4.rsa.setPublicKey = function(n, e) { - var key = { - n: n, - e: e - }; - - /** - * Encrypts the given data with this public key. Newer applications - * should use the 'RSA-OAEP' decryption scheme, 'RSAES-PKCS1-V1_5' is for - * legacy applications. - * - * @param data the byte string to encrypt. - * @param scheme the encryption scheme to use: - * 'RSAES-PKCS1-V1_5' (default), - * 'RSA-OAEP', - * 'RAW', 'NONE', or null to perform raw RSA encryption, - * an object with an 'encode' property set to a function - * with the signature 'function(data, key)' that returns - * a binary-encoded string representing the encoded data. - * @param schemeOptions any scheme-specific options. - * - * @return the encrypted byte string. - */ - key.encrypt = function(data, scheme, schemeOptions) { - if(typeof scheme === 'string') { - scheme = scheme.toUpperCase(); - } else if(scheme === undefined) { - scheme = 'RSAES-PKCS1-V1_5'; - } - - if(scheme === 'RSAES-PKCS1-V1_5') { - scheme = { - encode: function(m, key, pub) { - return _encodePkcs1_v1_5(m, key, 0x02).getBytes(); - } - }; - } else if(scheme === 'RSA-OAEP' || scheme === 'RSAES-OAEP') { - scheme = { - encode: function(m, key) { - return forge$i.pkcs1.encode_rsa_oaep(key, m, schemeOptions); - } - }; - } else if(['RAW', 'NONE', 'NULL', null].indexOf(scheme) !== -1) { - scheme = {encode: function(e) {return e;}}; - } else if(typeof scheme === 'string') { - throw new Error('Unsupported encryption scheme: "' + scheme + '".'); - } - - // do scheme-based encoding then rsa encryption - var e = scheme.encode(data, key, true); - return pki$4.rsa.encrypt(e, key, true); - }; - - /** - * Verifies the given signature against the given digest. - * - * PKCS#1 supports multiple (currently two) signature schemes: - * RSASSA-PKCS1-V1_5 and RSASSA-PSS. - * - * By default this implementation uses the "old scheme", i.e. - * RSASSA-PKCS1-V1_5, in which case once RSA-decrypted, the - * signature is an OCTET STRING that holds a DigestInfo. - * - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest - * } - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * Digest ::= OCTET STRING - * - * To perform PSS signature verification, provide an instance - * of Forge PSS object as the scheme parameter. - * - * @param digest the message digest hash to compare against the signature, - * as a binary-encoded string. - * @param signature the signature to verify, as a binary-encoded string. - * @param scheme signature verification scheme to use: - * 'RSASSA-PKCS1-V1_5' or undefined for RSASSA PKCS#1 v1.5, - * a Forge PSS object for RSASSA-PSS, - * 'NONE' or null for none, DigestInfo will not be expected, but - * PKCS#1 v1.5 padding will still be used. - * @param options optional verify options - * _parseAllDigestBytes testing flag to control parsing of all - * digest bytes. Unsupported and not for general usage. - * (default: true) - * - * @return true if the signature was verified, false if not. - */ - key.verify = function(digest, signature, scheme, options) { - if(typeof scheme === 'string') { - scheme = scheme.toUpperCase(); - } else if(scheme === undefined) { - scheme = 'RSASSA-PKCS1-V1_5'; - } - if(options === undefined) { - options = { - _parseAllDigestBytes: true - }; - } - if(!('_parseAllDigestBytes' in options)) { - options._parseAllDigestBytes = true; - } - - if(scheme === 'RSASSA-PKCS1-V1_5') { - scheme = { - verify: function(digest, d) { - // remove padding - d = _decodePkcs1_v1_5(d, key, true); - // d is ASN.1 BER-encoded DigestInfo - var obj = asn1$7.fromDer(d, { - parseAllBytes: options._parseAllDigestBytes - }); - - // validate DigestInfo - var capture = {}; - var errors = []; - if(!asn1$7.validate(obj, digestInfoValidator, capture, errors)) { - var error = new Error( - 'ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 ' + - 'DigestInfo value.'); - error.errors = errors; - throw error; - } - // check hash algorithm identifier - // see PKCS1-v1-5DigestAlgorithms in RFC 8017 - // FIXME: add support to vaidator for strict value choices - var oid = asn1$7.derToOid(capture.algorithmIdentifier); - if(!(oid === forge$i.oids.md2 || - oid === forge$i.oids.md5 || - oid === forge$i.oids.sha1 || - oid === forge$i.oids.sha224 || - oid === forge$i.oids.sha256 || - oid === forge$i.oids.sha384 || - oid === forge$i.oids.sha512 || - oid === forge$i.oids['sha512-224'] || - oid === forge$i.oids['sha512-256'])) { - var error = new Error( - 'Unknown RSASSA-PKCS1-v1_5 DigestAlgorithm identifier.'); - error.oid = oid; - throw error; - } - - // special check for md2 and md5 that NULL parameters exist - if(oid === forge$i.oids.md2 || oid === forge$i.oids.md5) { - if(!('parameters' in capture)) { - throw new Error( - 'ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 ' + - 'DigestInfo value. ' + - 'Missing algorithm identifer NULL parameters.'); - } - } - - // compare the given digest to the decrypted one - return digest === capture.digest; - } - }; - } else if(scheme === 'NONE' || scheme === 'NULL' || scheme === null) { - scheme = { - verify: function(digest, d) { - // remove padding - d = _decodePkcs1_v1_5(d, key, true); - return digest === d; - } - }; - } - - // do rsa decryption w/o any decoding, then verify -- which does decoding - var d = pki$4.rsa.decrypt(signature, key, true, false); - return scheme.verify(digest, d, key.n.bitLength()); - }; - - return key; -}; - -/** - * Sets an RSA private key from BigIntegers modulus, exponent, primes, - * prime exponents, and modular multiplicative inverse. - * - * @param n the modulus. - * @param e the public exponent. - * @param d the private exponent ((inverse of e) mod n). - * @param p the first prime. - * @param q the second prime. - * @param dP exponent1 (d mod (p-1)). - * @param dQ exponent2 (d mod (q-1)). - * @param qInv ((inverse of q) mod p) - * - * @return the private key. - */ -pki$4.setRsaPrivateKey = pki$4.rsa.setPrivateKey = function( - n, e, d, p, q, dP, dQ, qInv) { - var key = { - n: n, - e: e, - d: d, - p: p, - q: q, - dP: dP, - dQ: dQ, - qInv: qInv - }; - - /** - * Decrypts the given data with this private key. The decryption scheme - * must match the one used to encrypt the data. - * - * @param data the byte string to decrypt. - * @param scheme the decryption scheme to use: - * 'RSAES-PKCS1-V1_5' (default), - * 'RSA-OAEP', - * 'RAW', 'NONE', or null to perform raw RSA decryption. - * @param schemeOptions any scheme-specific options. - * - * @return the decrypted byte string. - */ - key.decrypt = function(data, scheme, schemeOptions) { - if(typeof scheme === 'string') { - scheme = scheme.toUpperCase(); - } else if(scheme === undefined) { - scheme = 'RSAES-PKCS1-V1_5'; - } - - // do rsa decryption w/o any decoding - var d = pki$4.rsa.decrypt(data, key, false, false); - - if(scheme === 'RSAES-PKCS1-V1_5') { - scheme = {decode: _decodePkcs1_v1_5}; - } else if(scheme === 'RSA-OAEP' || scheme === 'RSAES-OAEP') { - scheme = { - decode: function(d, key) { - return forge$i.pkcs1.decode_rsa_oaep(key, d, schemeOptions); - } - }; - } else if(['RAW', 'NONE', 'NULL', null].indexOf(scheme) !== -1) { - scheme = {decode: function(d) {return d;}}; - } else { - throw new Error('Unsupported encryption scheme: "' + scheme + '".'); - } - - // decode according to scheme - return scheme.decode(d, key, false); - }; - - /** - * Signs the given digest, producing a signature. - * - * PKCS#1 supports multiple (currently two) signature schemes: - * RSASSA-PKCS1-V1_5 and RSASSA-PSS. - * - * By default this implementation uses the "old scheme", i.e. - * RSASSA-PKCS1-V1_5. In order to generate a PSS signature, provide - * an instance of Forge PSS object as the scheme parameter. - * - * @param md the message digest object with the hash to sign. - * @param scheme the signature scheme to use: - * 'RSASSA-PKCS1-V1_5' or undefined for RSASSA PKCS#1 v1.5, - * a Forge PSS object for RSASSA-PSS, - * 'NONE' or null for none, DigestInfo will not be used but - * PKCS#1 v1.5 padding will still be used. - * - * @return the signature as a byte string. - */ - key.sign = function(md, scheme) { - /* Note: The internal implementation of RSA operations is being - transitioned away from a PKCS#1 v1.5 hard-coded scheme. Some legacy - code like the use of an encoding block identifier 'bt' will eventually - be removed. */ - - // private key operation - var bt = false; - - if(typeof scheme === 'string') { - scheme = scheme.toUpperCase(); - } - - if(scheme === undefined || scheme === 'RSASSA-PKCS1-V1_5') { - scheme = {encode: emsaPkcs1v15encode}; - bt = 0x01; - } else if(scheme === 'NONE' || scheme === 'NULL' || scheme === null) { - scheme = {encode: function() {return md;}}; - bt = 0x01; - } - - // encode and then encrypt - var d = scheme.encode(md, key.n.bitLength()); - return pki$4.rsa.encrypt(d, key, bt); - }; - - return key; -}; - -/** - * Wraps an RSAPrivateKey ASN.1 object in an ASN.1 PrivateKeyInfo object. - * - * @param rsaKey the ASN.1 RSAPrivateKey. - * - * @return the ASN.1 PrivateKeyInfo. - */ -pki$4.wrapRsaPrivateKey = function(rsaKey) { - // PrivateKeyInfo - return asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.SEQUENCE, true, [ - // version (0) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - asn1$7.integerToDer(0).getBytes()), - // privateKeyAlgorithm - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.SEQUENCE, true, [ - asn1$7.create( - asn1$7.Class.UNIVERSAL, asn1$7.Type.OID, false, - asn1$7.oidToDer(pki$4.oids.rsaEncryption).getBytes()), - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.NULL, false, '') - ]), - // PrivateKey - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.OCTETSTRING, false, - asn1$7.toDer(rsaKey).getBytes()) - ]); -}; - -/** - * Converts a private key from an ASN.1 object. - * - * @param obj the ASN.1 representation of a PrivateKeyInfo containing an - * RSAPrivateKey or an RSAPrivateKey. - * - * @return the private key. - */ -pki$4.privateKeyFromAsn1 = function(obj) { - // get PrivateKeyInfo - var capture = {}; - var errors = []; - if(asn1$7.validate(obj, privateKeyValidator$1, capture, errors)) { - obj = asn1$7.fromDer(forge$i.util.createBuffer(capture.privateKey)); - } - - // get RSAPrivateKey - capture = {}; - errors = []; - if(!asn1$7.validate(obj, rsaPrivateKeyValidator, capture, errors)) { - var error = new Error('Cannot read private key. ' + - 'ASN.1 object does not contain an RSAPrivateKey.'); - error.errors = errors; - throw error; - } - - // Note: Version is currently ignored. - // capture.privateKeyVersion - // FIXME: inefficient, get a BigInteger that uses byte strings - var n, e, d, p, q, dP, dQ, qInv; - n = forge$i.util.createBuffer(capture.privateKeyModulus).toHex(); - e = forge$i.util.createBuffer(capture.privateKeyPublicExponent).toHex(); - d = forge$i.util.createBuffer(capture.privateKeyPrivateExponent).toHex(); - p = forge$i.util.createBuffer(capture.privateKeyPrime1).toHex(); - q = forge$i.util.createBuffer(capture.privateKeyPrime2).toHex(); - dP = forge$i.util.createBuffer(capture.privateKeyExponent1).toHex(); - dQ = forge$i.util.createBuffer(capture.privateKeyExponent2).toHex(); - qInv = forge$i.util.createBuffer(capture.privateKeyCoefficient).toHex(); - - // set private key - return pki$4.setRsaPrivateKey( - new BigInteger$3(n, 16), - new BigInteger$3(e, 16), - new BigInteger$3(d, 16), - new BigInteger$3(p, 16), - new BigInteger$3(q, 16), - new BigInteger$3(dP, 16), - new BigInteger$3(dQ, 16), - new BigInteger$3(qInv, 16)); -}; - -/** - * Converts a private key to an ASN.1 RSAPrivateKey. - * - * @param key the private key. - * - * @return the ASN.1 representation of an RSAPrivateKey. - */ -pki$4.privateKeyToAsn1 = pki$4.privateKeyToRSAPrivateKey = function(key) { - // RSAPrivateKey - return asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.SEQUENCE, true, [ - // version (0 = only 2 primes, 1 multiple primes) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - asn1$7.integerToDer(0).getBytes()), - // modulus (n) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.n)), - // publicExponent (e) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.e)), - // privateExponent (d) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.d)), - // privateKeyPrime1 (p) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.p)), - // privateKeyPrime2 (q) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.q)), - // privateKeyExponent1 (dP) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.dP)), - // privateKeyExponent2 (dQ) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.dQ)), - // coefficient (qInv) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.qInv)) - ]); -}; - -/** - * Converts a public key from an ASN.1 SubjectPublicKeyInfo or RSAPublicKey. - * - * @param obj the asn1 representation of a SubjectPublicKeyInfo or RSAPublicKey. - * - * @return the public key. - */ -pki$4.publicKeyFromAsn1 = function(obj) { - // get SubjectPublicKeyInfo - var capture = {}; - var errors = []; - if(asn1$7.validate(obj, publicKeyValidator$2, capture, errors)) { - // get oid - var oid = asn1$7.derToOid(capture.publicKeyOid); - if(oid !== pki$4.oids.rsaEncryption) { - var error = new Error('Cannot read public key. Unknown OID.'); - error.oid = oid; - throw error; - } - obj = capture.rsaPublicKey; - } - - // get RSA params - errors = []; - if(!asn1$7.validate(obj, rsaPublicKeyValidator, capture, errors)) { - var error = new Error('Cannot read public key. ' + - 'ASN.1 object does not contain an RSAPublicKey.'); - error.errors = errors; - throw error; - } - - // FIXME: inefficient, get a BigInteger that uses byte strings - var n = forge$i.util.createBuffer(capture.publicKeyModulus).toHex(); - var e = forge$i.util.createBuffer(capture.publicKeyExponent).toHex(); - - // set public key - return pki$4.setRsaPublicKey( - new BigInteger$3(n, 16), - new BigInteger$3(e, 16)); -}; - -/** - * Converts a public key to an ASN.1 SubjectPublicKeyInfo. - * - * @param key the public key. - * - * @return the asn1 representation of a SubjectPublicKeyInfo. - */ -pki$4.publicKeyToAsn1 = pki$4.publicKeyToSubjectPublicKeyInfo = function(key) { - // SubjectPublicKeyInfo - return asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.SEQUENCE, true, [ - // AlgorithmIdentifier - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.SEQUENCE, true, [ - // algorithm - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.OID, false, - asn1$7.oidToDer(pki$4.oids.rsaEncryption).getBytes()), - // parameters (null) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.NULL, false, '') - ]), - // subjectPublicKey - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.BITSTRING, false, [ - pki$4.publicKeyToRSAPublicKey(key) - ]) - ]); -}; - -/** - * Converts a public key to an ASN.1 RSAPublicKey. - * - * @param key the public key. - * - * @return the asn1 representation of a RSAPublicKey. - */ -pki$4.publicKeyToRSAPublicKey = function(key) { - // RSAPublicKey - return asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.SEQUENCE, true, [ - // modulus (n) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.n)), - // publicExponent (e) - asn1$7.create(asn1$7.Class.UNIVERSAL, asn1$7.Type.INTEGER, false, - _bnToBytes(key.e)) - ]); -}; - -/** - * Encodes a message using PKCS#1 v1.5 padding. - * - * @param m the message to encode. - * @param key the RSA key to use. - * @param bt the block type to use, i.e. either 0x01 (for signing) or 0x02 - * (for encryption). - * - * @return the padded byte buffer. - */ -function _encodePkcs1_v1_5(m, key, bt) { - var eb = forge$i.util.createBuffer(); - - // get the length of the modulus in bytes - var k = Math.ceil(key.n.bitLength() / 8); - - /* use PKCS#1 v1.5 padding */ - if(m.length > (k - 11)) { - var error = new Error('Message is too long for PKCS#1 v1.5 padding.'); - error.length = m.length; - error.max = k - 11; - throw error; - } - - /* A block type BT, a padding string PS, and the data D shall be - formatted into an octet string EB, the encryption block: - - EB = 00 || BT || PS || 00 || D - - The block type BT shall be a single octet indicating the structure of - the encryption block. For this version of the document it shall have - value 00, 01, or 02. For a private-key operation, the block type - shall be 00 or 01. For a public-key operation, it shall be 02. - - The padding string PS shall consist of k-3-||D|| octets. For block - type 00, the octets shall have value 00; for block type 01, they - shall have value FF; and for block type 02, they shall be - pseudorandomly generated and nonzero. This makes the length of the - encryption block EB equal to k. */ - - // build the encryption block - eb.putByte(0x00); - eb.putByte(bt); - - // create the padding - var padNum = k - 3 - m.length; - var padByte; - // private key op - if(bt === 0x00 || bt === 0x01) { - padByte = (bt === 0x00) ? 0x00 : 0xFF; - for(var i = 0; i < padNum; ++i) { - eb.putByte(padByte); - } - } else { - // public key op - // pad with random non-zero values - while(padNum > 0) { - var numZeros = 0; - var padBytes = forge$i.random.getBytes(padNum); - for(var i = 0; i < padNum; ++i) { - padByte = padBytes.charCodeAt(i); - if(padByte === 0) { - ++numZeros; - } else { - eb.putByte(padByte); - } - } - padNum = numZeros; - } - } - - // zero followed by message - eb.putByte(0x00); - eb.putBytes(m); - - return eb; -} - -/** - * Decodes a message using PKCS#1 v1.5 padding. - * - * @param em the message to decode. - * @param key the RSA key to use. - * @param pub true if the key is a public key, false if it is private. - * @param ml the message length, if specified. - * - * @return the decoded bytes. - */ -function _decodePkcs1_v1_5(em, key, pub, ml) { - // get the length of the modulus in bytes - var k = Math.ceil(key.n.bitLength() / 8); - - /* It is an error if any of the following conditions occurs: - - 1. The encryption block EB cannot be parsed unambiguously. - 2. The padding string PS consists of fewer than eight octets - or is inconsisent with the block type BT. - 3. The decryption process is a public-key operation and the block - type BT is not 00 or 01, or the decryption process is a - private-key operation and the block type is not 02. - */ - - // parse the encryption block - var eb = forge$i.util.createBuffer(em); - var first = eb.getByte(); - var bt = eb.getByte(); - if(first !== 0x00 || - (pub && bt !== 0x00 && bt !== 0x01) || - (!pub && bt != 0x02) || - (pub && bt === 0x00 && typeof(ml) === 'undefined')) { - throw new Error('Encryption block is invalid.'); - } - - var padNum = 0; - if(bt === 0x00) { - // check all padding bytes for 0x00 - padNum = k - 3 - ml; - for(var i = 0; i < padNum; ++i) { - if(eb.getByte() !== 0x00) { - throw new Error('Encryption block is invalid.'); - } - } - } else if(bt === 0x01) { - // find the first byte that isn't 0xFF, should be after all padding - padNum = 0; - while(eb.length() > 1) { - if(eb.getByte() !== 0xFF) { - --eb.read; - break; - } - ++padNum; - } - } else if(bt === 0x02) { - // look for 0x00 byte - padNum = 0; - while(eb.length() > 1) { - if(eb.getByte() === 0x00) { - --eb.read; - break; - } - ++padNum; - } - } - - // zero must be 0x00 and padNum must be (k - 3 - message length) - var zero = eb.getByte(); - if(zero !== 0x00 || padNum !== (k - 3 - eb.length())) { - throw new Error('Encryption block is invalid.'); - } - - return eb.getBytes(); -} - -/** - * Runs the key-generation algorithm asynchronously, either in the background - * via Web Workers, or using the main thread and setImmediate. - * - * @param state the key-pair generation state. - * @param [options] options for key-pair generation: - * workerScript the worker script URL. - * workers the number of web workers (if supported) to use, - * (default: 2, -1 to use estimated cores minus one). - * workLoad the size of the work load, ie: number of possible prime - * numbers for each web worker to check per work assignment, - * (default: 100). - * @param callback(err, keypair) called once the operation completes. - */ -function _generateKeyPair(state, options, callback) { - if(typeof options === 'function') { - callback = options; - options = {}; - } - options = options || {}; - - var opts = { - algorithm: { - name: options.algorithm || 'PRIMEINC', - options: { - workers: options.workers || 2, - workLoad: options.workLoad || 100, - workerScript: options.workerScript - } - } - }; - if('prng' in options) { - opts.prng = options.prng; - } - - generate(); - - function generate() { - // find p and then q (done in series to simplify) - getPrime(state.pBits, function(err, num) { - if(err) { - return callback(err); - } - state.p = num; - if(state.q !== null) { - return finish(err, state.q); - } - getPrime(state.qBits, finish); - }); - } - - function getPrime(bits, callback) { - forge$i.prime.generateProbablePrime(bits, opts, callback); - } - - function finish(err, num) { - if(err) { - return callback(err); - } - - // set q - state.q = num; - - // ensure p is larger than q (swap them if not) - if(state.p.compareTo(state.q) < 0) { - var tmp = state.p; - state.p = state.q; - state.q = tmp; - } - - // ensure p is coprime with e - if(state.p.subtract(BigInteger$3.ONE).gcd(state.e) - .compareTo(BigInteger$3.ONE) !== 0) { - state.p = null; - generate(); - return; - } - - // ensure q is coprime with e - if(state.q.subtract(BigInteger$3.ONE).gcd(state.e) - .compareTo(BigInteger$3.ONE) !== 0) { - state.q = null; - getPrime(state.qBits, finish); - return; - } - - // compute phi: (p - 1)(q - 1) (Euler's totient function) - state.p1 = state.p.subtract(BigInteger$3.ONE); - state.q1 = state.q.subtract(BigInteger$3.ONE); - state.phi = state.p1.multiply(state.q1); - - // ensure e and phi are coprime - if(state.phi.gcd(state.e).compareTo(BigInteger$3.ONE) !== 0) { - // phi and e aren't coprime, so generate a new p and q - state.p = state.q = null; - generate(); - return; - } - - // create n, ensure n is has the right number of bits - state.n = state.p.multiply(state.q); - if(state.n.bitLength() !== state.bits) { - // failed, get new q - state.q = null; - getPrime(state.qBits, finish); - return; - } - - // set keys - var d = state.e.modInverse(state.phi); - state.keys = { - privateKey: pki$4.rsa.setPrivateKey( - state.n, state.e, d, state.p, state.q, - d.mod(state.p1), d.mod(state.q1), - state.q.modInverse(state.p)), - publicKey: pki$4.rsa.setPublicKey(state.n, state.e) - }; - - callback(null, state.keys); - } -} - -/** - * Converts a positive BigInteger into 2's-complement big-endian bytes. - * - * @param b the big integer to convert. - * - * @return the bytes. - */ -function _bnToBytes(b) { - // prepend 0x00 if first byte >= 0x80 - var hex = b.toString(16); - if(hex[0] >= '8') { - hex = '00' + hex; - } - var bytes = forge$i.util.hexToBytes(hex); - - // ensure integer is minimally-encoded - if(bytes.length > 1 && - // leading 0x00 for positive integer - ((bytes.charCodeAt(0) === 0 && - (bytes.charCodeAt(1) & 0x80) === 0) || - // leading 0xFF for negative integer - (bytes.charCodeAt(0) === 0xFF && - (bytes.charCodeAt(1) & 0x80) === 0x80))) { - return bytes.substr(1); - } - return bytes; -} - -/** - * Returns the required number of Miller-Rabin tests to generate a - * prime with an error probability of (1/2)^80. - * - * See Handbook of Applied Cryptography Chapter 4, Table 4.4. - * - * @param bits the bit size. - * - * @return the required number of iterations. - */ -function _getMillerRabinTests(bits) { - if(bits <= 100) return 27; - if(bits <= 150) return 18; - if(bits <= 200) return 15; - if(bits <= 250) return 12; - if(bits <= 300) return 9; - if(bits <= 350) return 8; - if(bits <= 400) return 7; - if(bits <= 500) return 6; - if(bits <= 600) return 5; - if(bits <= 800) return 4; - if(bits <= 1250) return 3; - return 2; -} - -/** - * Performs feature detection on the Node crypto interface. - * - * @param fn the feature (function) to detect. - * - * @return true if detected, false if not. - */ -function _detectNodeCrypto(fn) { - return forge$i.util.isNodejs && typeof _crypto[fn] === 'function'; -} - -/** - * Performs feature detection on the SubtleCrypto interface. - * - * @param fn the feature (function) to detect. - * - * @return true if detected, false if not. - */ -function _detectSubtleCrypto(fn) { - return (typeof util.globalScope !== 'undefined' && - typeof util.globalScope.crypto === 'object' && - typeof util.globalScope.crypto.subtle === 'object' && - typeof util.globalScope.crypto.subtle[fn] === 'function'); -} - -/** - * Performs feature detection on the deprecated Microsoft Internet Explorer - * outdated SubtleCrypto interface. This function should only be used after - * checking for the modern, standard SubtleCrypto interface. - * - * @param fn the feature (function) to detect. - * - * @return true if detected, false if not. - */ -function _detectSubtleMsCrypto(fn) { - return (typeof util.globalScope !== 'undefined' && - typeof util.globalScope.msCrypto === 'object' && - typeof util.globalScope.msCrypto.subtle === 'object' && - typeof util.globalScope.msCrypto.subtle[fn] === 'function'); -} - -function _intToUint8Array(x) { - var bytes = forge$i.util.hexToBytes(x.toString(16)); - var buffer = new Uint8Array(bytes.length); - for(var i = 0; i < bytes.length; ++i) { - buffer[i] = bytes.charCodeAt(i); - } - return buffer; -} - -/** - * Password-based encryption functions. - * - * @author Dave Longley - * @author Stefan Siegl - * - * Copyright (c) 2010-2013 Digital Bazaar, Inc. - * Copyright (c) 2012 Stefan Siegl - * - * An EncryptedPrivateKeyInfo: - * - * EncryptedPrivateKeyInfo ::= SEQUENCE { - * encryptionAlgorithm EncryptionAlgorithmIdentifier, - * encryptedData EncryptedData } - * - * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * EncryptedData ::= OCTET STRING - */ - -var forge$h = forge$D; - - - - - - - - - - - - -if(typeof BigInteger$2 === 'undefined') { - var BigInteger$2 = forge$h.jsbn.BigInteger; -} - -// shortcut for asn.1 API -var asn1$6 = forge$h.asn1; - -/* Password-based encryption implementation. */ -var pki$3 = forge$h.pki = forge$h.pki || {}; -pki$3.pbe = forge$h.pbe = forge$h.pbe || {}; -var oids$1 = pki$3.oids; - -// validator for an EncryptedPrivateKeyInfo structure -// Note: Currently only works w/algorithm params -var encryptedPrivateKeyValidator = { - name: 'EncryptedPrivateKeyInfo', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'EncryptedPrivateKeyInfo.encryptionAlgorithm', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'AlgorithmIdentifier.algorithm', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.OID, - constructed: false, - capture: 'encryptionOid' - }, { - name: 'AlgorithmIdentifier.parameters', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - captureAsn1: 'encryptionParams' - }] - }, { - // encryptedData - name: 'EncryptedPrivateKeyInfo.encryptedData', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.OCTETSTRING, - constructed: false, - capture: 'encryptedData' - }] -}; - -// validator for a PBES2Algorithms structure -// Note: Currently only works w/PBKDF2 + AES encryption schemes -var PBES2AlgorithmsValidator = { - name: 'PBES2Algorithms', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'PBES2Algorithms.keyDerivationFunc', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'PBES2Algorithms.keyDerivationFunc.oid', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.OID, - constructed: false, - capture: 'kdfOid' - }, { - name: 'PBES2Algorithms.params', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'PBES2Algorithms.params.salt', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.OCTETSTRING, - constructed: false, - capture: 'kdfSalt' - }, { - name: 'PBES2Algorithms.params.iterationCount', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.INTEGER, - constructed: false, - capture: 'kdfIterationCount' - }, { - name: 'PBES2Algorithms.params.keyLength', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.INTEGER, - constructed: false, - optional: true, - capture: 'keyLength' - }, { - // prf - name: 'PBES2Algorithms.params.prf', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - optional: true, - value: [{ - name: 'PBES2Algorithms.params.prf.algorithm', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.OID, - constructed: false, - capture: 'prfOid' - }] - }] - }] - }, { - name: 'PBES2Algorithms.encryptionScheme', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'PBES2Algorithms.encryptionScheme.oid', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.OID, - constructed: false, - capture: 'encOid' - }, { - name: 'PBES2Algorithms.encryptionScheme.iv', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.OCTETSTRING, - constructed: false, - capture: 'encIv' - }] - }] -}; - -var pkcs12PbeParamsValidator = { - name: 'pkcs-12PbeParams', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'pkcs-12PbeParams.salt', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.OCTETSTRING, - constructed: false, - capture: 'salt' - }, { - name: 'pkcs-12PbeParams.iterations', - tagClass: asn1$6.Class.UNIVERSAL, - type: asn1$6.Type.INTEGER, - constructed: false, - capture: 'iterations' - }] -}; - -/** - * Encrypts a ASN.1 PrivateKeyInfo object, producing an EncryptedPrivateKeyInfo. - * - * PBES2Algorithms ALGORITHM-IDENTIFIER ::= - * { {PBES2-params IDENTIFIED BY id-PBES2}, ...} - * - * id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} - * - * PBES2-params ::= SEQUENCE { - * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, - * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} - * } - * - * PBES2-KDFs ALGORITHM-IDENTIFIER ::= - * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... } - * - * PBES2-Encs ALGORITHM-IDENTIFIER ::= { ... } - * - * PBKDF2-params ::= SEQUENCE { - * salt CHOICE { - * specified OCTET STRING, - * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} - * }, - * iterationCount INTEGER (1..MAX), - * keyLength INTEGER (1..MAX) OPTIONAL, - * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 - * } - * - * @param obj the ASN.1 PrivateKeyInfo object. - * @param password the password to encrypt with. - * @param options: - * algorithm the encryption algorithm to use - * ('aes128', 'aes192', 'aes256', '3des'), defaults to 'aes128'. - * count the iteration count to use. - * saltSize the salt size to use. - * prfAlgorithm the PRF message digest algorithm to use - * ('sha1', 'sha224', 'sha256', 'sha384', 'sha512') - * - * @return the ASN.1 EncryptedPrivateKeyInfo. - */ -pki$3.encryptPrivateKeyInfo = function(obj, password, options) { - // set default options - options = options || {}; - options.saltSize = options.saltSize || 8; - options.count = options.count || 2048; - options.algorithm = options.algorithm || 'aes128'; - options.prfAlgorithm = options.prfAlgorithm || 'sha1'; - - // generate PBE params - var salt = forge$h.random.getBytesSync(options.saltSize); - var count = options.count; - var countBytes = asn1$6.integerToDer(count); - var dkLen; - var encryptionAlgorithm; - var encryptedData; - if(options.algorithm.indexOf('aes') === 0 || options.algorithm === 'des') { - // do PBES2 - var ivLen, encOid, cipherFn; - switch(options.algorithm) { - case 'aes128': - dkLen = 16; - ivLen = 16; - encOid = oids$1['aes128-CBC']; - cipherFn = forge$h.aes.createEncryptionCipher; - break; - case 'aes192': - dkLen = 24; - ivLen = 16; - encOid = oids$1['aes192-CBC']; - cipherFn = forge$h.aes.createEncryptionCipher; - break; - case 'aes256': - dkLen = 32; - ivLen = 16; - encOid = oids$1['aes256-CBC']; - cipherFn = forge$h.aes.createEncryptionCipher; - break; - case 'des': - dkLen = 8; - ivLen = 8; - encOid = oids$1['desCBC']; - cipherFn = forge$h.des.createEncryptionCipher; - break; - default: - var error = new Error('Cannot encrypt private key. Unknown encryption algorithm.'); - error.algorithm = options.algorithm; - throw error; - } - - // get PRF message digest - var prfAlgorithm = 'hmacWith' + options.prfAlgorithm.toUpperCase(); - var md = prfAlgorithmToMessageDigest(prfAlgorithm); - - // encrypt private key using pbe SHA-1 and AES/DES - var dk = forge$h.pkcs5.pbkdf2(password, salt, count, dkLen, md); - var iv = forge$h.random.getBytesSync(ivLen); - var cipher = cipherFn(dk); - cipher.start(iv); - cipher.update(asn1$6.toDer(obj)); - cipher.finish(); - encryptedData = cipher.output.getBytes(); - - // get PBKDF2-params - var params = createPbkdf2Params(salt, countBytes, dkLen, prfAlgorithm); - - encryptionAlgorithm = asn1$6.create( - asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.OID, false, - asn1$6.oidToDer(oids$1['pkcs5PBES2']).getBytes()), - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - // keyDerivationFunc - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.OID, false, - asn1$6.oidToDer(oids$1['pkcs5PBKDF2']).getBytes()), - // PBKDF2-params - params - ]), - // encryptionScheme - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.OID, false, - asn1$6.oidToDer(encOid).getBytes()), - // iv - asn1$6.create( - asn1$6.Class.UNIVERSAL, asn1$6.Type.OCTETSTRING, false, iv) - ]) - ]) - ]); - } else if(options.algorithm === '3des') { - // Do PKCS12 PBE - dkLen = 24; - - var saltBytes = new forge$h.util.ByteBuffer(salt); - var dk = pki$3.pbe.generatePkcs12Key(password, saltBytes, 1, count, dkLen); - var iv = pki$3.pbe.generatePkcs12Key(password, saltBytes, 2, count, dkLen); - var cipher = forge$h.des.createEncryptionCipher(dk); - cipher.start(iv); - cipher.update(asn1$6.toDer(obj)); - cipher.finish(); - encryptedData = cipher.output.getBytes(); - - encryptionAlgorithm = asn1$6.create( - asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.OID, false, - asn1$6.oidToDer(oids$1['pbeWithSHAAnd3-KeyTripleDES-CBC']).getBytes()), - // pkcs-12PbeParams - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - // salt - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.OCTETSTRING, false, salt), - // iteration count - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.INTEGER, false, - countBytes.getBytes()) - ]) - ]); - } else { - var error = new Error('Cannot encrypt private key. Unknown encryption algorithm.'); - error.algorithm = options.algorithm; - throw error; - } - - // EncryptedPrivateKeyInfo - var rval = asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - // encryptionAlgorithm - encryptionAlgorithm, - // encryptedData - asn1$6.create( - asn1$6.Class.UNIVERSAL, asn1$6.Type.OCTETSTRING, false, encryptedData) - ]); - return rval; -}; - -/** - * Decrypts a ASN.1 PrivateKeyInfo object. - * - * @param obj the ASN.1 EncryptedPrivateKeyInfo object. - * @param password the password to decrypt with. - * - * @return the ASN.1 PrivateKeyInfo on success, null on failure. - */ -pki$3.decryptPrivateKeyInfo = function(obj, password) { - var rval = null; - - // get PBE params - var capture = {}; - var errors = []; - if(!asn1$6.validate(obj, encryptedPrivateKeyValidator, capture, errors)) { - var error = new Error('Cannot read encrypted private key. ' + - 'ASN.1 object is not a supported EncryptedPrivateKeyInfo.'); - error.errors = errors; - throw error; - } - - // get cipher - var oid = asn1$6.derToOid(capture.encryptionOid); - var cipher = pki$3.pbe.getCipher(oid, capture.encryptionParams, password); - - // get encrypted data - var encrypted = forge$h.util.createBuffer(capture.encryptedData); - - cipher.update(encrypted); - if(cipher.finish()) { - rval = asn1$6.fromDer(cipher.output); - } - - return rval; -}; - -/** - * Converts a EncryptedPrivateKeyInfo to PEM format. - * - * @param epki the EncryptedPrivateKeyInfo. - * @param maxline the maximum characters per line, defaults to 64. - * - * @return the PEM-formatted encrypted private key. - */ -pki$3.encryptedPrivateKeyToPem = function(epki, maxline) { - // convert to DER, then PEM-encode - var msg = { - type: 'ENCRYPTED PRIVATE KEY', - body: asn1$6.toDer(epki).getBytes() - }; - return forge$h.pem.encode(msg, {maxline: maxline}); -}; - -/** - * Converts a PEM-encoded EncryptedPrivateKeyInfo to ASN.1 format. Decryption - * is not performed. - * - * @param pem the EncryptedPrivateKeyInfo in PEM-format. - * - * @return the ASN.1 EncryptedPrivateKeyInfo. - */ -pki$3.encryptedPrivateKeyFromPem = function(pem) { - var msg = forge$h.pem.decode(pem)[0]; - - if(msg.type !== 'ENCRYPTED PRIVATE KEY') { - var error = new Error('Could not convert encrypted private key from PEM; ' + - 'PEM header type is "ENCRYPTED PRIVATE KEY".'); - error.headerType = msg.type; - throw error; - } - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - throw new Error('Could not convert encrypted private key from PEM; ' + - 'PEM is encrypted.'); - } - - // convert DER to ASN.1 object - return asn1$6.fromDer(msg.body); -}; - -/** - * Encrypts an RSA private key. By default, the key will be wrapped in - * a PrivateKeyInfo and encrypted to produce a PKCS#8 EncryptedPrivateKeyInfo. - * This is the standard, preferred way to encrypt a private key. - * - * To produce a non-standard PEM-encrypted private key that uses encapsulated - * headers to indicate the encryption algorithm (old-style non-PKCS#8 OpenSSL - * private key encryption), set the 'legacy' option to true. Note: Using this - * option will cause the iteration count to be forced to 1. - * - * Note: The 'des' algorithm is supported, but it is not considered to be - * secure because it only uses a single 56-bit key. If possible, it is highly - * recommended that a different algorithm be used. - * - * @param rsaKey the RSA key to encrypt. - * @param password the password to use. - * @param options: - * algorithm: the encryption algorithm to use - * ('aes128', 'aes192', 'aes256', '3des', 'des'). - * count: the iteration count to use. - * saltSize: the salt size to use. - * legacy: output an old non-PKCS#8 PEM-encrypted+encapsulated - * headers (DEK-Info) private key. - * - * @return the PEM-encoded ASN.1 EncryptedPrivateKeyInfo. - */ -pki$3.encryptRsaPrivateKey = function(rsaKey, password, options) { - // standard PKCS#8 - options = options || {}; - if(!options.legacy) { - // encrypt PrivateKeyInfo - var rval = pki$3.wrapRsaPrivateKey(pki$3.privateKeyToAsn1(rsaKey)); - rval = pki$3.encryptPrivateKeyInfo(rval, password, options); - return pki$3.encryptedPrivateKeyToPem(rval); - } - - // legacy non-PKCS#8 - var algorithm; - var iv; - var dkLen; - var cipherFn; - switch(options.algorithm) { - case 'aes128': - algorithm = 'AES-128-CBC'; - dkLen = 16; - iv = forge$h.random.getBytesSync(16); - cipherFn = forge$h.aes.createEncryptionCipher; - break; - case 'aes192': - algorithm = 'AES-192-CBC'; - dkLen = 24; - iv = forge$h.random.getBytesSync(16); - cipherFn = forge$h.aes.createEncryptionCipher; - break; - case 'aes256': - algorithm = 'AES-256-CBC'; - dkLen = 32; - iv = forge$h.random.getBytesSync(16); - cipherFn = forge$h.aes.createEncryptionCipher; - break; - case '3des': - algorithm = 'DES-EDE3-CBC'; - dkLen = 24; - iv = forge$h.random.getBytesSync(8); - cipherFn = forge$h.des.createEncryptionCipher; - break; - case 'des': - algorithm = 'DES-CBC'; - dkLen = 8; - iv = forge$h.random.getBytesSync(8); - cipherFn = forge$h.des.createEncryptionCipher; - break; - default: - var error = new Error('Could not encrypt RSA private key; unsupported ' + - 'encryption algorithm "' + options.algorithm + '".'); - error.algorithm = options.algorithm; - throw error; - } - - // encrypt private key using OpenSSL legacy key derivation - var dk = forge$h.pbe.opensslDeriveBytes(password, iv.substr(0, 8), dkLen); - var cipher = cipherFn(dk); - cipher.start(iv); - cipher.update(asn1$6.toDer(pki$3.privateKeyToAsn1(rsaKey))); - cipher.finish(); - - var msg = { - type: 'RSA PRIVATE KEY', - procType: { - version: '4', - type: 'ENCRYPTED' - }, - dekInfo: { - algorithm: algorithm, - parameters: forge$h.util.bytesToHex(iv).toUpperCase() - }, - body: cipher.output.getBytes() - }; - return forge$h.pem.encode(msg); -}; - -/** - * Decrypts an RSA private key. - * - * @param pem the PEM-formatted EncryptedPrivateKeyInfo to decrypt. - * @param password the password to use. - * - * @return the RSA key on success, null on failure. - */ -pki$3.decryptRsaPrivateKey = function(pem, password) { - var rval = null; - - var msg = forge$h.pem.decode(pem)[0]; - - if(msg.type !== 'ENCRYPTED PRIVATE KEY' && - msg.type !== 'PRIVATE KEY' && - msg.type !== 'RSA PRIVATE KEY') { - var error = new Error('Could not convert private key from PEM; PEM header type ' + - 'is not "ENCRYPTED PRIVATE KEY", "PRIVATE KEY", or "RSA PRIVATE KEY".'); - error.headerType = error; - throw error; - } - - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - var dkLen; - var cipherFn; - switch(msg.dekInfo.algorithm) { - case 'DES-CBC': - dkLen = 8; - cipherFn = forge$h.des.createDecryptionCipher; - break; - case 'DES-EDE3-CBC': - dkLen = 24; - cipherFn = forge$h.des.createDecryptionCipher; - break; - case 'AES-128-CBC': - dkLen = 16; - cipherFn = forge$h.aes.createDecryptionCipher; - break; - case 'AES-192-CBC': - dkLen = 24; - cipherFn = forge$h.aes.createDecryptionCipher; - break; - case 'AES-256-CBC': - dkLen = 32; - cipherFn = forge$h.aes.createDecryptionCipher; - break; - case 'RC2-40-CBC': - dkLen = 5; - cipherFn = function(key) { - return forge$h.rc2.createDecryptionCipher(key, 40); - }; - break; - case 'RC2-64-CBC': - dkLen = 8; - cipherFn = function(key) { - return forge$h.rc2.createDecryptionCipher(key, 64); - }; - break; - case 'RC2-128-CBC': - dkLen = 16; - cipherFn = function(key) { - return forge$h.rc2.createDecryptionCipher(key, 128); - }; - break; - default: - var error = new Error('Could not decrypt private key; unsupported ' + - 'encryption algorithm "' + msg.dekInfo.algorithm + '".'); - error.algorithm = msg.dekInfo.algorithm; - throw error; - } - - // use OpenSSL legacy key derivation - var iv = forge$h.util.hexToBytes(msg.dekInfo.parameters); - var dk = forge$h.pbe.opensslDeriveBytes(password, iv.substr(0, 8), dkLen); - var cipher = cipherFn(dk); - cipher.start(iv); - cipher.update(forge$h.util.createBuffer(msg.body)); - if(cipher.finish()) { - rval = cipher.output.getBytes(); - } else { - return rval; - } - } else { - rval = msg.body; - } - - if(msg.type === 'ENCRYPTED PRIVATE KEY') { - rval = pki$3.decryptPrivateKeyInfo(asn1$6.fromDer(rval), password); - } else { - // decryption already performed above - rval = asn1$6.fromDer(rval); - } - - if(rval !== null) { - rval = pki$3.privateKeyFromAsn1(rval); - } - - return rval; -}; - -/** - * Derives a PKCS#12 key. - * - * @param password the password to derive the key material from, null or - * undefined for none. - * @param salt the salt, as a ByteBuffer, to use. - * @param id the PKCS#12 ID byte (1 = key material, 2 = IV, 3 = MAC). - * @param iter the iteration count. - * @param n the number of bytes to derive from the password. - * @param md the message digest to use, defaults to SHA-1. - * - * @return a ByteBuffer with the bytes derived from the password. - */ -pki$3.pbe.generatePkcs12Key = function(password, salt, id, iter, n, md) { - var j, l; - - if(typeof md === 'undefined' || md === null) { - if(!('sha1' in forge$h.md)) { - throw new Error('"sha1" hash algorithm unavailable.'); - } - md = forge$h.md.sha1.create(); - } - - var u = md.digestLength; - var v = md.blockLength; - var result = new forge$h.util.ByteBuffer(); - - /* Convert password to Unicode byte buffer + trailing 0-byte. */ - var passBuf = new forge$h.util.ByteBuffer(); - if(password !== null && password !== undefined) { - for(l = 0; l < password.length; l++) { - passBuf.putInt16(password.charCodeAt(l)); - } - passBuf.putInt16(0); - } - - /* Length of salt and password in BYTES. */ - var p = passBuf.length(); - var s = salt.length(); - - /* 1. Construct a string, D (the "diversifier"), by concatenating - v copies of ID. */ - var D = new forge$h.util.ByteBuffer(); - D.fillWithByte(id, v); - - /* 2. Concatenate copies of the salt together to create a string S of length - v * ceil(s / v) bytes (the final copy of the salt may be trunacted - to create S). - Note that if the salt is the empty string, then so is S. */ - var Slen = v * Math.ceil(s / v); - var S = new forge$h.util.ByteBuffer(); - for(l = 0; l < Slen; l++) { - S.putByte(salt.at(l % s)); - } - - /* 3. Concatenate copies of the password together to create a string P of - length v * ceil(p / v) bytes (the final copy of the password may be - truncated to create P). - Note that if the password is the empty string, then so is P. */ - var Plen = v * Math.ceil(p / v); - var P = new forge$h.util.ByteBuffer(); - for(l = 0; l < Plen; l++) { - P.putByte(passBuf.at(l % p)); - } - - /* 4. Set I=S||P to be the concatenation of S and P. */ - var I = S; - I.putBuffer(P); - - /* 5. Set c=ceil(n / u). */ - var c = Math.ceil(n / u); - - /* 6. For i=1, 2, ..., c, do the following: */ - for(var i = 1; i <= c; i++) { - /* a) Set Ai=H^r(D||I). (l.e. the rth hash of D||I, H(H(H(...H(D||I)))) */ - var buf = new forge$h.util.ByteBuffer(); - buf.putBytes(D.bytes()); - buf.putBytes(I.bytes()); - for(var round = 0; round < iter; round++) { - md.start(); - md.update(buf.getBytes()); - buf = md.digest(); - } - - /* b) Concatenate copies of Ai to create a string B of length v bytes (the - final copy of Ai may be truncated to create B). */ - var B = new forge$h.util.ByteBuffer(); - for(l = 0; l < v; l++) { - B.putByte(buf.at(l % u)); - } - - /* c) Treating I as a concatenation I0, I1, ..., Ik-1 of v-byte blocks, - where k=ceil(s / v) + ceil(p / v), modify I by setting - Ij=(Ij+B+1) mod 2v for each j. */ - var k = Math.ceil(s / v) + Math.ceil(p / v); - var Inew = new forge$h.util.ByteBuffer(); - for(j = 0; j < k; j++) { - var chunk = new forge$h.util.ByteBuffer(I.getBytes(v)); - var x = 0x1ff; - for(l = B.length() - 1; l >= 0; l--) { - x = x >> 8; - x += B.at(l) + chunk.at(l); - chunk.setAt(l, x & 0xff); - } - Inew.putBuffer(chunk); - } - I = Inew; - - /* Add Ai to A. */ - result.putBuffer(buf); - } - - result.truncate(result.length() - n); - return result; -}; - -/** - * Get new Forge cipher object instance. - * - * @param oid the OID (in string notation). - * @param params the ASN.1 params object. - * @param password the password to decrypt with. - * - * @return new cipher object instance. - */ -pki$3.pbe.getCipher = function(oid, params, password) { - switch(oid) { - case pki$3.oids['pkcs5PBES2']: - return pki$3.pbe.getCipherForPBES2(oid, params, password); - - case pki$3.oids['pbeWithSHAAnd3-KeyTripleDES-CBC']: - case pki$3.oids['pbewithSHAAnd40BitRC2-CBC']: - return pki$3.pbe.getCipherForPKCS12PBE(oid, params, password); - - default: - var error = new Error('Cannot read encrypted PBE data block. Unsupported OID.'); - error.oid = oid; - error.supportedOids = [ - 'pkcs5PBES2', - 'pbeWithSHAAnd3-KeyTripleDES-CBC', - 'pbewithSHAAnd40BitRC2-CBC' - ]; - throw error; - } -}; - -/** - * Get new Forge cipher object instance according to PBES2 params block. - * - * The returned cipher instance is already started using the IV - * from PBES2 parameter block. - * - * @param oid the PKCS#5 PBKDF2 OID (in string notation). - * @param params the ASN.1 PBES2-params object. - * @param password the password to decrypt with. - * - * @return new cipher object instance. - */ -pki$3.pbe.getCipherForPBES2 = function(oid, params, password) { - // get PBE params - var capture = {}; - var errors = []; - if(!asn1$6.validate(params, PBES2AlgorithmsValidator, capture, errors)) { - var error = new Error('Cannot read password-based-encryption algorithm ' + - 'parameters. ASN.1 object is not a supported EncryptedPrivateKeyInfo.'); - error.errors = errors; - throw error; - } - - // check oids - oid = asn1$6.derToOid(capture.kdfOid); - if(oid !== pki$3.oids['pkcs5PBKDF2']) { - var error = new Error('Cannot read encrypted private key. ' + - 'Unsupported key derivation function OID.'); - error.oid = oid; - error.supportedOids = ['pkcs5PBKDF2']; - throw error; - } - oid = asn1$6.derToOid(capture.encOid); - if(oid !== pki$3.oids['aes128-CBC'] && - oid !== pki$3.oids['aes192-CBC'] && - oid !== pki$3.oids['aes256-CBC'] && - oid !== pki$3.oids['des-EDE3-CBC'] && - oid !== pki$3.oids['desCBC']) { - var error = new Error('Cannot read encrypted private key. ' + - 'Unsupported encryption scheme OID.'); - error.oid = oid; - error.supportedOids = [ - 'aes128-CBC', 'aes192-CBC', 'aes256-CBC', 'des-EDE3-CBC', 'desCBC']; - throw error; - } - - // set PBE params - var salt = capture.kdfSalt; - var count = forge$h.util.createBuffer(capture.kdfIterationCount); - count = count.getInt(count.length() << 3); - var dkLen; - var cipherFn; - switch(pki$3.oids[oid]) { - case 'aes128-CBC': - dkLen = 16; - cipherFn = forge$h.aes.createDecryptionCipher; - break; - case 'aes192-CBC': - dkLen = 24; - cipherFn = forge$h.aes.createDecryptionCipher; - break; - case 'aes256-CBC': - dkLen = 32; - cipherFn = forge$h.aes.createDecryptionCipher; - break; - case 'des-EDE3-CBC': - dkLen = 24; - cipherFn = forge$h.des.createDecryptionCipher; - break; - case 'desCBC': - dkLen = 8; - cipherFn = forge$h.des.createDecryptionCipher; - break; - } - - // get PRF message digest - var md = prfOidToMessageDigest(capture.prfOid); - - // decrypt private key using pbe with chosen PRF and AES/DES - var dk = forge$h.pkcs5.pbkdf2(password, salt, count, dkLen, md); - var iv = capture.encIv; - var cipher = cipherFn(dk); - cipher.start(iv); - - return cipher; -}; - -/** - * Get new Forge cipher object instance for PKCS#12 PBE. - * - * The returned cipher instance is already started using the key & IV - * derived from the provided password and PKCS#12 PBE salt. - * - * @param oid The PKCS#12 PBE OID (in string notation). - * @param params The ASN.1 PKCS#12 PBE-params object. - * @param password The password to decrypt with. - * - * @return the new cipher object instance. - */ -pki$3.pbe.getCipherForPKCS12PBE = function(oid, params, password) { - // get PBE params - var capture = {}; - var errors = []; - if(!asn1$6.validate(params, pkcs12PbeParamsValidator, capture, errors)) { - var error = new Error('Cannot read password-based-encryption algorithm ' + - 'parameters. ASN.1 object is not a supported EncryptedPrivateKeyInfo.'); - error.errors = errors; - throw error; - } - - var salt = forge$h.util.createBuffer(capture.salt); - var count = forge$h.util.createBuffer(capture.iterations); - count = count.getInt(count.length() << 3); - - var dkLen, dIvLen, cipherFn; - switch(oid) { - case pki$3.oids['pbeWithSHAAnd3-KeyTripleDES-CBC']: - dkLen = 24; - dIvLen = 8; - cipherFn = forge$h.des.startDecrypting; - break; - - case pki$3.oids['pbewithSHAAnd40BitRC2-CBC']: - dkLen = 5; - dIvLen = 8; - cipherFn = function(key, iv) { - var cipher = forge$h.rc2.createDecryptionCipher(key, 40); - cipher.start(iv, null); - return cipher; - }; - break; - - default: - var error = new Error('Cannot read PKCS #12 PBE data block. Unsupported OID.'); - error.oid = oid; - throw error; - } - - // get PRF message digest - var md = prfOidToMessageDigest(capture.prfOid); - var key = pki$3.pbe.generatePkcs12Key(password, salt, 1, count, dkLen, md); - md.start(); - var iv = pki$3.pbe.generatePkcs12Key(password, salt, 2, count, dIvLen, md); - - return cipherFn(key, iv); -}; - -/** - * OpenSSL's legacy key derivation function. - * - * See: http://www.openssl.org/docs/crypto/EVP_BytesToKey.html - * - * @param password the password to derive the key from. - * @param salt the salt to use, null for none. - * @param dkLen the number of bytes needed for the derived key. - * @param [options] the options to use: - * [md] an optional message digest object to use. - */ -pki$3.pbe.opensslDeriveBytes = function(password, salt, dkLen, md) { - if(typeof md === 'undefined' || md === null) { - if(!('md5' in forge$h.md)) { - throw new Error('"md5" hash algorithm unavailable.'); - } - md = forge$h.md.md5.create(); - } - if(salt === null) { - salt = ''; - } - var digests = [hash(md, password + salt)]; - for(var length = 16, i = 1; length < dkLen; ++i, length += 16) { - digests.push(hash(md, digests[i - 1] + password + salt)); - } - return digests.join('').substr(0, dkLen); -}; - -function hash(md, bytes) { - return md.start().update(bytes).digest().getBytes(); -} - -function prfOidToMessageDigest(prfOid) { - // get PRF algorithm, default to SHA-1 - var prfAlgorithm; - if(!prfOid) { - prfAlgorithm = 'hmacWithSHA1'; - } else { - prfAlgorithm = pki$3.oids[asn1$6.derToOid(prfOid)]; - if(!prfAlgorithm) { - var error = new Error('Unsupported PRF OID.'); - error.oid = prfOid; - error.supported = [ - 'hmacWithSHA1', 'hmacWithSHA224', 'hmacWithSHA256', 'hmacWithSHA384', - 'hmacWithSHA512']; - throw error; - } - } - return prfAlgorithmToMessageDigest(prfAlgorithm); -} - -function prfAlgorithmToMessageDigest(prfAlgorithm) { - var factory = forge$h.md; - switch(prfAlgorithm) { - case 'hmacWithSHA224': - factory = forge$h.md.sha512; - case 'hmacWithSHA1': - case 'hmacWithSHA256': - case 'hmacWithSHA384': - case 'hmacWithSHA512': - prfAlgorithm = prfAlgorithm.substr(8).toLowerCase(); - break; - default: - var error = new Error('Unsupported PRF algorithm.'); - error.algorithm = prfAlgorithm; - error.supported = [ - 'hmacWithSHA1', 'hmacWithSHA224', 'hmacWithSHA256', 'hmacWithSHA384', - 'hmacWithSHA512']; - throw error; - } - if(!factory || !(prfAlgorithm in factory)) { - throw new Error('Unknown hash algorithm: ' + prfAlgorithm); - } - return factory[prfAlgorithm].create(); -} - -function createPbkdf2Params(salt, countBytes, dkLen, prfAlgorithm) { - var params = asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - // salt - asn1$6.create( - asn1$6.Class.UNIVERSAL, asn1$6.Type.OCTETSTRING, false, salt), - // iteration count - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.INTEGER, false, - countBytes.getBytes()) - ]); - // when PRF algorithm is not SHA-1 default, add key length and PRF algorithm - if(prfAlgorithm !== 'hmacWithSHA1') { - params.value.push( - // key length - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.INTEGER, false, - forge$h.util.hexToBytes(dkLen.toString(16))), - // AlgorithmIdentifier - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.SEQUENCE, true, [ - // algorithm - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.OID, false, - asn1$6.oidToDer(pki$3.oids[prfAlgorithm]).getBytes()), - // parameters (null) - asn1$6.create(asn1$6.Class.UNIVERSAL, asn1$6.Type.NULL, false, '') - ])); - } - return params; -} - -/** - * Javascript implementation of ASN.1 validators for PKCS#7 v1.5. - * - * @author Dave Longley - * @author Stefan Siegl - * - * Copyright (c) 2012-2015 Digital Bazaar, Inc. - * Copyright (c) 2012 Stefan Siegl - * - * The ASN.1 representation of PKCS#7 is as follows - * (see RFC #2315 for details, http://www.ietf.org/rfc/rfc2315.txt): - * - * A PKCS#7 message consists of a ContentInfo on root level, which may - * contain any number of further ContentInfo nested into it. - * - * ContentInfo ::= SEQUENCE { - * contentType ContentType, - * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL - * } - * - * ContentType ::= OBJECT IDENTIFIER - * - * EnvelopedData ::= SEQUENCE { - * version Version, - * recipientInfos RecipientInfos, - * encryptedContentInfo EncryptedContentInfo - * } - * - * EncryptedData ::= SEQUENCE { - * version Version, - * encryptedContentInfo EncryptedContentInfo - * } - * - * id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) - * us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 } - * - * SignedData ::= SEQUENCE { - * version INTEGER, - * digestAlgorithms DigestAlgorithmIdentifiers, - * contentInfo ContentInfo, - * certificates [0] IMPLICIT Certificates OPTIONAL, - * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, - * signerInfos SignerInfos - * } - * - * SignerInfos ::= SET OF SignerInfo - * - * SignerInfo ::= SEQUENCE { - * version Version, - * issuerAndSerialNumber IssuerAndSerialNumber, - * digestAlgorithm DigestAlgorithmIdentifier, - * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL, - * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, - * encryptedDigest EncryptedDigest, - * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL - * } - * - * EncryptedDigest ::= OCTET STRING - * - * Attributes ::= SET OF Attribute - * - * Attribute ::= SEQUENCE { - * attrType OBJECT IDENTIFIER, - * attrValues SET OF AttributeValue - * } - * - * AttributeValue ::= ANY - * - * Version ::= INTEGER - * - * RecipientInfos ::= SET OF RecipientInfo - * - * EncryptedContentInfo ::= SEQUENCE { - * contentType ContentType, - * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, - * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL - * } - * - * ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * The AlgorithmIdentifier contains an Object Identifier (OID) and parameters - * for the algorithm, if any. In the case of AES and DES3, there is only one, - * the IV. - * - * AlgorithmIdentifer ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - * - * EncryptedContent ::= OCTET STRING - * - * RecipientInfo ::= SEQUENCE { - * version Version, - * issuerAndSerialNumber IssuerAndSerialNumber, - * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, - * encryptedKey EncryptedKey - * } - * - * IssuerAndSerialNumber ::= SEQUENCE { - * issuer Name, - * serialNumber CertificateSerialNumber - * } - * - * CertificateSerialNumber ::= INTEGER - * - * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * EncryptedKey ::= OCTET STRING - */ - -var forge$g = forge$D; - - - -// shortcut for ASN.1 API -var asn1$5 = forge$g.asn1; - -// shortcut for PKCS#7 API -var p7v = forge$g.pkcs7asn1 = forge$g.pkcs7asn1 || {}; -forge$g.pkcs7 = forge$g.pkcs7 || {}; -forge$g.pkcs7.asn1 = p7v; - -var contentInfoValidator$1 = { - name: 'ContentInfo', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'ContentInfo.ContentType', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.OID, - constructed: false, - capture: 'contentType' - }, { - name: 'ContentInfo.content', - tagClass: asn1$5.Class.CONTEXT_SPECIFIC, - type: 0, - constructed: true, - optional: true, - captureAsn1: 'content' - }] -}; -p7v.contentInfoValidator = contentInfoValidator$1; - -var encryptedContentInfoValidator = { - name: 'EncryptedContentInfo', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'EncryptedContentInfo.contentType', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.OID, - constructed: false, - capture: 'contentType' - }, { - name: 'EncryptedContentInfo.contentEncryptionAlgorithm', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'EncryptedContentInfo.contentEncryptionAlgorithm.algorithm', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.OID, - constructed: false, - capture: 'encAlgorithm' - }, { - name: 'EncryptedContentInfo.contentEncryptionAlgorithm.parameter', - tagClass: asn1$5.Class.UNIVERSAL, - captureAsn1: 'encParameter' - }] - }, { - name: 'EncryptedContentInfo.encryptedContent', - tagClass: asn1$5.Class.CONTEXT_SPECIFIC, - type: 0, - /* The PKCS#7 structure output by OpenSSL somewhat differs from what - * other implementations do generate. - * - * OpenSSL generates a structure like this: - * SEQUENCE { - * ... - * [0] - * 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38 - * C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45 - * ... - * } - * - * Whereas other implementations (and this PKCS#7 module) generate: - * SEQUENCE { - * ... - * [0] { - * OCTET STRING - * 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38 - * C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45 - * ... - * } - * } - * - * In order to support both, we just capture the context specific - * field here. The OCTET STRING bit is removed below. - */ - capture: 'encryptedContent', - captureAsn1: 'encryptedContentAsn1' - }] -}; - -p7v.envelopedDataValidator = { - name: 'EnvelopedData', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'EnvelopedData.Version', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.INTEGER, - constructed: false, - capture: 'version' - }, { - name: 'EnvelopedData.RecipientInfos', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SET, - constructed: true, - captureAsn1: 'recipientInfos' - }].concat(encryptedContentInfoValidator) -}; - -p7v.encryptedDataValidator = { - name: 'EncryptedData', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'EncryptedData.Version', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.INTEGER, - constructed: false, - capture: 'version' - }].concat(encryptedContentInfoValidator) -}; - -var signerValidator = { - name: 'SignerInfo', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'SignerInfo.version', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.INTEGER, - constructed: false - }, { - name: 'SignerInfo.issuerAndSerialNumber', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'SignerInfo.issuerAndSerialNumber.issuer', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - captureAsn1: 'issuer' - }, { - name: 'SignerInfo.issuerAndSerialNumber.serialNumber', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.INTEGER, - constructed: false, - capture: 'serial' - }] - }, { - name: 'SignerInfo.digestAlgorithm', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'SignerInfo.digestAlgorithm.algorithm', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.OID, - constructed: false, - capture: 'digestAlgorithm' - }, { - name: 'SignerInfo.digestAlgorithm.parameter', - tagClass: asn1$5.Class.UNIVERSAL, - constructed: false, - captureAsn1: 'digestParameter', - optional: true - }] - }, { - name: 'SignerInfo.authenticatedAttributes', - tagClass: asn1$5.Class.CONTEXT_SPECIFIC, - type: 0, - constructed: true, - optional: true, - capture: 'authenticatedAttributes' - }, { - name: 'SignerInfo.digestEncryptionAlgorithm', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - capture: 'signatureAlgorithm' - }, { - name: 'SignerInfo.encryptedDigest', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.OCTETSTRING, - constructed: false, - capture: 'signature' - }, { - name: 'SignerInfo.unauthenticatedAttributes', - tagClass: asn1$5.Class.CONTEXT_SPECIFIC, - type: 1, - constructed: true, - optional: true, - capture: 'unauthenticatedAttributes' - }] -}; - -p7v.signedDataValidator = { - name: 'SignedData', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'SignedData.Version', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.INTEGER, - constructed: false, - capture: 'version' - }, { - name: 'SignedData.DigestAlgorithms', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SET, - constructed: true, - captureAsn1: 'digestAlgorithms' - }, - contentInfoValidator$1, - { - name: 'SignedData.Certificates', - tagClass: asn1$5.Class.CONTEXT_SPECIFIC, - type: 0, - optional: true, - captureAsn1: 'certificates' - }, { - name: 'SignedData.CertificateRevocationLists', - tagClass: asn1$5.Class.CONTEXT_SPECIFIC, - type: 1, - optional: true, - captureAsn1: 'crls' - }, { - name: 'SignedData.SignerInfos', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SET, - capture: 'signerInfos', - optional: true, - value: [signerValidator] - }] -}; - -p7v.recipientInfoValidator = { - name: 'RecipientInfo', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'RecipientInfo.version', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.INTEGER, - constructed: false, - capture: 'version' - }, { - name: 'RecipientInfo.issuerAndSerial', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'RecipientInfo.issuerAndSerial.issuer', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - captureAsn1: 'issuer' - }, { - name: 'RecipientInfo.issuerAndSerial.serialNumber', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.INTEGER, - constructed: false, - capture: 'serial' - }] - }, { - name: 'RecipientInfo.keyEncryptionAlgorithm', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'RecipientInfo.keyEncryptionAlgorithm.algorithm', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.OID, - constructed: false, - capture: 'encAlgorithm' - }, { - name: 'RecipientInfo.keyEncryptionAlgorithm.parameter', - tagClass: asn1$5.Class.UNIVERSAL, - constructed: false, - captureAsn1: 'encParameter', - optional: true - }] - }, { - name: 'RecipientInfo.encryptedKey', - tagClass: asn1$5.Class.UNIVERSAL, - type: asn1$5.Type.OCTETSTRING, - constructed: false, - capture: 'encKey' - }] -}; - -/** - * Javascript implementation of mask generation function MGF1. - * - * @author Stefan Siegl - * @author Dave Longley - * - * Copyright (c) 2012 Stefan Siegl - * Copyright (c) 2014 Digital Bazaar, Inc. - */ - -var forge$f = forge$D; - - -forge$f.mgf = forge$f.mgf || {}; -var mgf1 = forge$f.mgf.mgf1 = forge$f.mgf1 = forge$f.mgf1 || {}; - -/** - * Creates a MGF1 mask generation function object. - * - * @param md the message digest API to use (eg: forge.md.sha1.create()). - * - * @return a mask generation function object. - */ -mgf1.create = function(md) { - var mgf = { - /** - * Generate mask of specified length. - * - * @param {String} seed The seed for mask generation. - * @param maskLen Number of bytes to generate. - * @return {String} The generated mask. - */ - generate: function(seed, maskLen) { - /* 2. Let T be the empty octet string. */ - var t = new forge$f.util.ByteBuffer(); - - /* 3. For counter from 0 to ceil(maskLen / hLen), do the following: */ - var len = Math.ceil(maskLen / md.digestLength); - for(var i = 0; i < len; i++) { - /* a. Convert counter to an octet string C of length 4 octets */ - var c = new forge$f.util.ByteBuffer(); - c.putInt32(i); - - /* b. Concatenate the hash of the seed mgfSeed and C to the octet - * string T: */ - md.start(); - md.update(seed + c.getBytes()); - t.putBuffer(md.digest()); - } - - /* Output the leading maskLen octets of T as the octet string mask. */ - t.truncate(t.length() - maskLen); - return t.getBytes(); - } - }; - - return mgf; -}; - -/** - * Node.js module for Forge mask generation functions. - * - * @author Stefan Siegl - * - * Copyright 2012 Stefan Siegl - */ - -var forge$e = forge$D; - - -forge$e.mgf = forge$e.mgf || {}; -forge$e.mgf.mgf1 = forge$e.mgf1; - -/** - * Javascript implementation of PKCS#1 PSS signature padding. - * - * @author Stefan Siegl - * - * Copyright (c) 2012 Stefan Siegl - */ - -var forge$d = forge$D; - - - -// shortcut for PSS API -var pss = forge$d.pss = forge$d.pss || {}; - -/** - * Creates a PSS signature scheme object. - * - * There are several ways to provide a salt for encoding: - * - * 1. Specify the saltLength only and the built-in PRNG will generate it. - * 2. Specify the saltLength and a custom PRNG with 'getBytesSync' defined that - * will be used. - * 3. Specify the salt itself as a forge.util.ByteBuffer. - * - * @param options the options to use: - * md the message digest object to use, a forge md instance. - * mgf the mask generation function to use, a forge mgf instance. - * [saltLength] the length of the salt in octets. - * [prng] the pseudo-random number generator to use to produce a salt. - * [salt] the salt to use when encoding. - * - * @return a signature scheme object. - */ -pss.create = function(options) { - // backwards compatibility w/legacy args: hash, mgf, sLen - if(arguments.length === 3) { - options = { - md: arguments[0], - mgf: arguments[1], - saltLength: arguments[2] - }; - } - - var hash = options.md; - var mgf = options.mgf; - var hLen = hash.digestLength; - - var salt_ = options.salt || null; - if(typeof salt_ === 'string') { - // assume binary-encoded string - salt_ = forge$d.util.createBuffer(salt_); - } - - var sLen; - if('saltLength' in options) { - sLen = options.saltLength; - } else if(salt_ !== null) { - sLen = salt_.length(); - } else { - throw new Error('Salt length not specified or specific salt not given.'); - } - - if(salt_ !== null && salt_.length() !== sLen) { - throw new Error('Given salt length does not match length of given salt.'); - } - - var prng = options.prng || forge$d.random; - - var pssobj = {}; - - /** - * Encodes a PSS signature. - * - * This function implements EMSA-PSS-ENCODE as per RFC 3447, section 9.1.1. - * - * @param md the message digest object with the hash to sign. - * @param modsBits the length of the RSA modulus in bits. - * - * @return the encoded message as a binary-encoded string of length - * ceil((modBits - 1) / 8). - */ - pssobj.encode = function(md, modBits) { - var i; - var emBits = modBits - 1; - var emLen = Math.ceil(emBits / 8); - - /* 2. Let mHash = Hash(M), an octet string of length hLen. */ - var mHash = md.digest().getBytes(); - - /* 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. */ - if(emLen < hLen + sLen + 2) { - throw new Error('Message is too long to encrypt.'); - } - - /* 4. Generate a random octet string salt of length sLen; if sLen = 0, - * then salt is the empty string. */ - var salt; - if(salt_ === null) { - salt = prng.getBytesSync(sLen); - } else { - salt = salt_.bytes(); - } - - /* 5. Let M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; */ - var m_ = new forge$d.util.ByteBuffer(); - m_.fillWithByte(0, 8); - m_.putBytes(mHash); - m_.putBytes(salt); - - /* 6. Let H = Hash(M'), an octet string of length hLen. */ - hash.start(); - hash.update(m_.getBytes()); - var h = hash.digest().getBytes(); - - /* 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 - * zero octets. The length of PS may be 0. */ - var ps = new forge$d.util.ByteBuffer(); - ps.fillWithByte(0, emLen - sLen - hLen - 2); - - /* 8. Let DB = PS || 0x01 || salt; DB is an octet string of length - * emLen - hLen - 1. */ - ps.putByte(0x01); - ps.putBytes(salt); - var db = ps.getBytes(); - - /* 9. Let dbMask = MGF(H, emLen - hLen - 1). */ - var maskLen = emLen - hLen - 1; - var dbMask = mgf.generate(h, maskLen); - - /* 10. Let maskedDB = DB \xor dbMask. */ - var maskedDB = ''; - for(i = 0; i < maskLen; i++) { - maskedDB += String.fromCharCode(db.charCodeAt(i) ^ dbMask.charCodeAt(i)); - } - - /* 11. Set the leftmost 8emLen - emBits bits of the leftmost octet in - * maskedDB to zero. */ - var mask = (0xFF00 >> (8 * emLen - emBits)) & 0xFF; - maskedDB = String.fromCharCode(maskedDB.charCodeAt(0) & ~mask) + - maskedDB.substr(1); - - /* 12. Let EM = maskedDB || H || 0xbc. - * 13. Output EM. */ - return maskedDB + h + String.fromCharCode(0xbc); - }; - - /** - * Verifies a PSS signature. - * - * This function implements EMSA-PSS-VERIFY as per RFC 3447, section 9.1.2. - * - * @param mHash the message digest hash, as a binary-encoded string, to - * compare against the signature. - * @param em the encoded message, as a binary-encoded string - * (RSA decryption result). - * @param modsBits the length of the RSA modulus in bits. - * - * @return true if the signature was verified, false if not. - */ - pssobj.verify = function(mHash, em, modBits) { - var i; - var emBits = modBits - 1; - var emLen = Math.ceil(emBits / 8); - - /* c. Convert the message representative m to an encoded message EM - * of length emLen = ceil((modBits - 1) / 8) octets, where modBits - * is the length in bits of the RSA modulus n */ - em = em.substr(-emLen); - - /* 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. */ - if(emLen < hLen + sLen + 2) { - throw new Error('Inconsistent parameters to PSS signature verification.'); - } - - /* 4. If the rightmost octet of EM does not have hexadecimal value - * 0xbc, output "inconsistent" and stop. */ - if(em.charCodeAt(emLen - 1) !== 0xbc) { - throw new Error('Encoded message does not end in 0xBC.'); - } - - /* 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and - * let H be the next hLen octets. */ - var maskLen = emLen - hLen - 1; - var maskedDB = em.substr(0, maskLen); - var h = em.substr(maskLen, hLen); - - /* 6. If the leftmost 8emLen - emBits bits of the leftmost octet in - * maskedDB are not all equal to zero, output "inconsistent" and stop. */ - var mask = (0xFF00 >> (8 * emLen - emBits)) & 0xFF; - if((maskedDB.charCodeAt(0) & mask) !== 0) { - throw new Error('Bits beyond keysize not zero as expected.'); - } - - /* 7. Let dbMask = MGF(H, emLen - hLen - 1). */ - var dbMask = mgf.generate(h, maskLen); - - /* 8. Let DB = maskedDB \xor dbMask. */ - var db = ''; - for(i = 0; i < maskLen; i++) { - db += String.fromCharCode(maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i)); - } - - /* 9. Set the leftmost 8emLen - emBits bits of the leftmost octet - * in DB to zero. */ - db = String.fromCharCode(db.charCodeAt(0) & ~mask) + db.substr(1); - - /* 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero - * or if the octet at position emLen - hLen - sLen - 1 (the leftmost - * position is "position 1") does not have hexadecimal value 0x01, - * output "inconsistent" and stop. */ - var checkLen = emLen - hLen - sLen - 2; - for(i = 0; i < checkLen; i++) { - if(db.charCodeAt(i) !== 0x00) { - throw new Error('Leftmost octets not zero as expected'); - } - } - - if(db.charCodeAt(checkLen) !== 0x01) { - throw new Error('Inconsistent PSS signature, 0x01 marker not found'); - } - - /* 11. Let salt be the last sLen octets of DB. */ - var salt = db.substr(-sLen); - - /* 12. Let M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt */ - var m_ = new forge$d.util.ByteBuffer(); - m_.fillWithByte(0, 8); - m_.putBytes(mHash); - m_.putBytes(salt); - - /* 13. Let H' = Hash(M'), an octet string of length hLen. */ - hash.start(); - hash.update(m_.getBytes()); - var h_ = hash.digest().getBytes(); - - /* 14. If H = H', output "consistent." Otherwise, output "inconsistent." */ - return h === h_; - }; - - return pssobj; -}; - -/** - * Javascript implementation of X.509 and related components (such as - * Certification Signing Requests) of a Public Key Infrastructure. - * - * @author Dave Longley - * - * Copyright (c) 2010-2014 Digital Bazaar, Inc. - * - * The ASN.1 representation of an X.509v3 certificate is as follows - * (see RFC 2459): - * - * Certificate ::= SEQUENCE { - * tbsCertificate TBSCertificate, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - * } - * - * TBSCertificate ::= SEQUENCE { - * version [0] EXPLICIT Version DEFAULT v1, - * serialNumber CertificateSerialNumber, - * signature AlgorithmIdentifier, - * issuer Name, - * validity Validity, - * subject Name, - * subjectPublicKeyInfo SubjectPublicKeyInfo, - * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * extensions [3] EXPLICIT Extensions OPTIONAL - * -- If present, version shall be v3 - * } - * - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - * - * CertificateSerialNumber ::= INTEGER - * - * Name ::= CHOICE { - * // only one possible choice for now - * RDNSequence - * } - * - * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName - * - * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue - * - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue - * } - * AttributeType ::= OBJECT IDENTIFIER - * AttributeValue ::= ANY DEFINED BY AttributeType - * - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time - * } - * - * Time ::= CHOICE { - * utcTime UTCTime, - * generalTime GeneralizedTime - * } - * - * UniqueIdentifier ::= BIT STRING - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING - * } - * - * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension - * - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING - * } - * - * The only key algorithm currently supported for PKI is RSA. - * - * RSASSA-PSS signatures are described in RFC 3447 and RFC 4055. - * - * PKCS#10 v1.7 describes certificate signing requests: - * - * CertificationRequestInfo: - * - * CertificationRequestInfo ::= SEQUENCE { - * version INTEGER { v1(0) } (v1,...), - * subject Name, - * subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, - * attributes [0] Attributes{{ CRIAttributes }} - * } - * - * Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }} - * - * CRIAttributes ATTRIBUTE ::= { - * ... -- add any locally defined attributes here -- } - * - * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE { - * type ATTRIBUTE.&id({IOSet}), - * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) - * } - * - * CertificationRequest ::= SEQUENCE { - * certificationRequestInfo CertificationRequestInfo, - * signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, - * signature BIT STRING - * } - */ - -var forge$c = forge$D; - - - - - - - - - - - -// shortcut for asn.1 API -var asn1$4 = forge$c.asn1; - -/* Public Key Infrastructure (PKI) implementation. */ -var pki$2 = forge$c.pki = forge$c.pki || {}; -var oids = pki$2.oids; - -// short name OID mappings -var _shortNames = {}; -_shortNames['CN'] = oids['commonName']; -_shortNames['commonName'] = 'CN'; -_shortNames['C'] = oids['countryName']; -_shortNames['countryName'] = 'C'; -_shortNames['L'] = oids['localityName']; -_shortNames['localityName'] = 'L'; -_shortNames['ST'] = oids['stateOrProvinceName']; -_shortNames['stateOrProvinceName'] = 'ST'; -_shortNames['O'] = oids['organizationName']; -_shortNames['organizationName'] = 'O'; -_shortNames['OU'] = oids['organizationalUnitName']; -_shortNames['organizationalUnitName'] = 'OU'; -_shortNames['E'] = oids['emailAddress']; -_shortNames['emailAddress'] = 'E'; - -// validator for an SubjectPublicKeyInfo structure -// Note: Currently only works with an RSA public key -var publicKeyValidator$1 = forge$c.pki.rsa.publicKeyValidator; - -// validator for an X.509v3 certificate -var x509CertificateValidator = { - name: 'Certificate', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'Certificate.TBSCertificate', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - captureAsn1: 'tbsCertificate', - value: [{ - name: 'Certificate.TBSCertificate.version', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 0, - constructed: true, - optional: true, - value: [{ - name: 'Certificate.TBSCertificate.version.integer', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.INTEGER, - constructed: false, - capture: 'certVersion' - }] - }, { - name: 'Certificate.TBSCertificate.serialNumber', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.INTEGER, - constructed: false, - capture: 'certSerialNumber' - }, { - name: 'Certificate.TBSCertificate.signature', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'Certificate.TBSCertificate.signature.algorithm', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.OID, - constructed: false, - capture: 'certinfoSignatureOid' - }, { - name: 'Certificate.TBSCertificate.signature.parameters', - tagClass: asn1$4.Class.UNIVERSAL, - optional: true, - captureAsn1: 'certinfoSignatureParams' - }] - }, { - name: 'Certificate.TBSCertificate.issuer', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - captureAsn1: 'certIssuer' - }, { - name: 'Certificate.TBSCertificate.validity', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - // Note: UTC and generalized times may both appear so the capture - // names are based on their detected order, the names used below - // are only for the common case, which validity time really means - // "notBefore" and which means "notAfter" will be determined by order - value: [{ - // notBefore (Time) (UTC time case) - name: 'Certificate.TBSCertificate.validity.notBefore (utc)', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.UTCTIME, - constructed: false, - optional: true, - capture: 'certValidity1UTCTime' - }, { - // notBefore (Time) (generalized time case) - name: 'Certificate.TBSCertificate.validity.notBefore (generalized)', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.GENERALIZEDTIME, - constructed: false, - optional: true, - capture: 'certValidity2GeneralizedTime' - }, { - // notAfter (Time) (only UTC time is supported) - name: 'Certificate.TBSCertificate.validity.notAfter (utc)', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.UTCTIME, - constructed: false, - optional: true, - capture: 'certValidity3UTCTime' - }, { - // notAfter (Time) (only UTC time is supported) - name: 'Certificate.TBSCertificate.validity.notAfter (generalized)', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.GENERALIZEDTIME, - constructed: false, - optional: true, - capture: 'certValidity4GeneralizedTime' - }] - }, { - // Name (subject) (RDNSequence) - name: 'Certificate.TBSCertificate.subject', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - captureAsn1: 'certSubject' - }, - // SubjectPublicKeyInfo - publicKeyValidator$1, - { - // issuerUniqueID (optional) - name: 'Certificate.TBSCertificate.issuerUniqueID', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 1, - constructed: true, - optional: true, - value: [{ - name: 'Certificate.TBSCertificate.issuerUniqueID.id', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.BITSTRING, - constructed: false, - // TODO: support arbitrary bit length ids - captureBitStringValue: 'certIssuerUniqueId' - }] - }, { - // subjectUniqueID (optional) - name: 'Certificate.TBSCertificate.subjectUniqueID', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 2, - constructed: true, - optional: true, - value: [{ - name: 'Certificate.TBSCertificate.subjectUniqueID.id', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.BITSTRING, - constructed: false, - // TODO: support arbitrary bit length ids - captureBitStringValue: 'certSubjectUniqueId' - }] - }, { - // Extensions (optional) - name: 'Certificate.TBSCertificate.extensions', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 3, - constructed: true, - captureAsn1: 'certExtensions', - optional: true - }] - }, { - // AlgorithmIdentifier (signature algorithm) - name: 'Certificate.signatureAlgorithm', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - value: [{ - // algorithm - name: 'Certificate.signatureAlgorithm.algorithm', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.OID, - constructed: false, - capture: 'certSignatureOid' - }, { - name: 'Certificate.TBSCertificate.signature.parameters', - tagClass: asn1$4.Class.UNIVERSAL, - optional: true, - captureAsn1: 'certSignatureParams' - }] - }, { - // SignatureValue - name: 'Certificate.signatureValue', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.BITSTRING, - constructed: false, - captureBitStringValue: 'certSignature' - }] -}; - -var rsassaPssParameterValidator = { - name: 'rsapss', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'rsapss.hashAlgorithm', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 0, - constructed: true, - value: [{ - name: 'rsapss.hashAlgorithm.AlgorithmIdentifier', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Class.SEQUENCE, - constructed: true, - optional: true, - value: [{ - name: 'rsapss.hashAlgorithm.AlgorithmIdentifier.algorithm', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.OID, - constructed: false, - capture: 'hashOid' - /* parameter block omitted, for SHA1 NULL anyhow. */ - }] - }] - }, { - name: 'rsapss.maskGenAlgorithm', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 1, - constructed: true, - value: [{ - name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Class.SEQUENCE, - constructed: true, - optional: true, - value: [{ - name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.algorithm', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.OID, - constructed: false, - capture: 'maskGenOid' - }, { - name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.params', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'rsapss.maskGenAlgorithm.AlgorithmIdentifier.params.algorithm', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.OID, - constructed: false, - capture: 'maskGenHashOid' - /* parameter block omitted, for SHA1 NULL anyhow. */ - }] - }] - }] - }, { - name: 'rsapss.saltLength', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 2, - optional: true, - value: [{ - name: 'rsapss.saltLength.saltLength', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Class.INTEGER, - constructed: false, - capture: 'saltLength' - }] - }, { - name: 'rsapss.trailerField', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 3, - optional: true, - value: [{ - name: 'rsapss.trailer.trailer', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Class.INTEGER, - constructed: false, - capture: 'trailer' - }] - }] -}; - -// validator for a CertificationRequestInfo structure -var certificationRequestInfoValidator = { - name: 'CertificationRequestInfo', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - captureAsn1: 'certificationRequestInfo', - value: [{ - name: 'CertificationRequestInfo.integer', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.INTEGER, - constructed: false, - capture: 'certificationRequestInfoVersion' - }, { - // Name (subject) (RDNSequence) - name: 'CertificationRequestInfo.subject', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - captureAsn1: 'certificationRequestInfoSubject' - }, - // SubjectPublicKeyInfo - publicKeyValidator$1, - { - name: 'CertificationRequestInfo.attributes', - tagClass: asn1$4.Class.CONTEXT_SPECIFIC, - type: 0, - constructed: true, - optional: true, - capture: 'certificationRequestInfoAttributes', - value: [{ - name: 'CertificationRequestInfo.attributes', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'CertificationRequestInfo.attributes.type', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.OID, - constructed: false - }, { - name: 'CertificationRequestInfo.attributes.value', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SET, - constructed: true - }] - }] - }] -}; - -// validator for a CertificationRequest structure -var certificationRequestValidator = { - name: 'CertificationRequest', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - captureAsn1: 'csr', - value: [ - certificationRequestInfoValidator, { - // AlgorithmIdentifier (signature algorithm) - name: 'CertificationRequest.signatureAlgorithm', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.SEQUENCE, - constructed: true, - value: [{ - // algorithm - name: 'CertificationRequest.signatureAlgorithm.algorithm', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.OID, - constructed: false, - capture: 'csrSignatureOid' - }, { - name: 'CertificationRequest.signatureAlgorithm.parameters', - tagClass: asn1$4.Class.UNIVERSAL, - optional: true, - captureAsn1: 'csrSignatureParams' - }] - }, { - // signature - name: 'CertificationRequest.signature', - tagClass: asn1$4.Class.UNIVERSAL, - type: asn1$4.Type.BITSTRING, - constructed: false, - captureBitStringValue: 'csrSignature' - } - ] -}; - -/** - * Converts an RDNSequence of ASN.1 DER-encoded RelativeDistinguishedName - * sets into an array with objects that have type and value properties. - * - * @param rdn the RDNSequence to convert. - * @param md a message digest to append type and value to if provided. - */ -pki$2.RDNAttributesAsArray = function(rdn, md) { - var rval = []; - - // each value in 'rdn' in is a SET of RelativeDistinguishedName - var set, attr, obj; - for(var si = 0; si < rdn.value.length; ++si) { - // get the RelativeDistinguishedName set - set = rdn.value[si]; - - // each value in the SET is an AttributeTypeAndValue sequence - // containing first a type (an OID) and second a value (defined by - // the OID) - for(var i = 0; i < set.value.length; ++i) { - obj = {}; - attr = set.value[i]; - obj.type = asn1$4.derToOid(attr.value[0].value); - obj.value = attr.value[1].value; - obj.valueTagClass = attr.value[1].type; - // if the OID is known, get its name and short name - if(obj.type in oids) { - obj.name = oids[obj.type]; - if(obj.name in _shortNames) { - obj.shortName = _shortNames[obj.name]; - } - } - if(md) { - md.update(obj.type); - md.update(obj.value); - } - rval.push(obj); - } - } - - return rval; -}; - -/** - * Converts ASN.1 CRIAttributes into an array with objects that have type and - * value properties. - * - * @param attributes the CRIAttributes to convert. - */ -pki$2.CRIAttributesAsArray = function(attributes) { - var rval = []; - - // each value in 'attributes' in is a SEQUENCE with an OID and a SET - for(var si = 0; si < attributes.length; ++si) { - // get the attribute sequence - var seq = attributes[si]; - - // each value in the SEQUENCE containing first a type (an OID) and - // second a set of values (defined by the OID) - var type = asn1$4.derToOid(seq.value[0].value); - var values = seq.value[1].value; - for(var vi = 0; vi < values.length; ++vi) { - var obj = {}; - obj.type = type; - obj.value = values[vi].value; - obj.valueTagClass = values[vi].type; - // if the OID is known, get its name and short name - if(obj.type in oids) { - obj.name = oids[obj.type]; - if(obj.name in _shortNames) { - obj.shortName = _shortNames[obj.name]; - } - } - // parse extensions - if(obj.type === oids.extensionRequest) { - obj.extensions = []; - for(var ei = 0; ei < obj.value.length; ++ei) { - obj.extensions.push(pki$2.certificateExtensionFromAsn1(obj.value[ei])); - } - } - rval.push(obj); - } - } - - return rval; -}; - -/** - * Gets an issuer or subject attribute from its name, type, or short name. - * - * @param obj the issuer or subject object. - * @param options a short name string or an object with: - * shortName the short name for the attribute. - * name the name for the attribute. - * type the type for the attribute. - * - * @return the attribute. - */ -function _getAttribute(obj, options) { - if(typeof options === 'string') { - options = {shortName: options}; - } - - var rval = null; - var attr; - for(var i = 0; rval === null && i < obj.attributes.length; ++i) { - attr = obj.attributes[i]; - if(options.type && options.type === attr.type) { - rval = attr; - } else if(options.name && options.name === attr.name) { - rval = attr; - } else if(options.shortName && options.shortName === attr.shortName) { - rval = attr; - } - } - return rval; -} - -/** - * Converts signature parameters from ASN.1 structure. - * - * Currently only RSASSA-PSS supported. The PKCS#1 v1.5 signature scheme had - * no parameters. - * - * RSASSA-PSS-params ::= SEQUENCE { - * hashAlgorithm [0] HashAlgorithm DEFAULT - * sha1Identifier, - * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT - * mgf1SHA1Identifier, - * saltLength [2] INTEGER DEFAULT 20, - * trailerField [3] INTEGER DEFAULT 1 - * } - * - * HashAlgorithm ::= AlgorithmIdentifier - * - * MaskGenAlgorithm ::= AlgorithmIdentifier - * - * AlgorithmIdentifer ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - * - * @param oid The OID specifying the signature algorithm - * @param obj The ASN.1 structure holding the parameters - * @param fillDefaults Whether to use return default values where omitted - * @return signature parameter object - */ -var _readSignatureParameters = function(oid, obj, fillDefaults) { - var params = {}; - - if(oid !== oids['RSASSA-PSS']) { - return params; - } - - if(fillDefaults) { - params = { - hash: { - algorithmOid: oids['sha1'] - }, - mgf: { - algorithmOid: oids['mgf1'], - hash: { - algorithmOid: oids['sha1'] - } - }, - saltLength: 20 - }; - } - - var capture = {}; - var errors = []; - if(!asn1$4.validate(obj, rsassaPssParameterValidator, capture, errors)) { - var error = new Error('Cannot read RSASSA-PSS parameter block.'); - error.errors = errors; - throw error; - } - - if(capture.hashOid !== undefined) { - params.hash = params.hash || {}; - params.hash.algorithmOid = asn1$4.derToOid(capture.hashOid); - } - - if(capture.maskGenOid !== undefined) { - params.mgf = params.mgf || {}; - params.mgf.algorithmOid = asn1$4.derToOid(capture.maskGenOid); - params.mgf.hash = params.mgf.hash || {}; - params.mgf.hash.algorithmOid = asn1$4.derToOid(capture.maskGenHashOid); - } - - if(capture.saltLength !== undefined) { - params.saltLength = capture.saltLength.charCodeAt(0); - } - - return params; -}; - -/** - * Create signature digest for OID. - * - * @param options - * signatureOid: the OID specifying the signature algorithm. - * type: a human readable type for error messages - * @return a created md instance. throws if unknown oid. - */ -var _createSignatureDigest = function(options) { - switch(oids[options.signatureOid]) { - case 'sha1WithRSAEncryption': - // deprecated alias - case 'sha1WithRSASignature': - return forge$c.md.sha1.create(); - case 'md5WithRSAEncryption': - return forge$c.md.md5.create(); - case 'sha256WithRSAEncryption': - return forge$c.md.sha256.create(); - case 'sha384WithRSAEncryption': - return forge$c.md.sha384.create(); - case 'sha512WithRSAEncryption': - return forge$c.md.sha512.create(); - case 'RSASSA-PSS': - return forge$c.md.sha256.create(); - default: - var error = new Error( - 'Could not compute ' + options.type + ' digest. ' + - 'Unknown signature OID.'); - error.signatureOid = options.signatureOid; - throw error; - } -}; - -/** - * Verify signature on certificate or CSR. - * - * @param options: - * certificate the certificate or CSR to verify. - * md the signature digest. - * signature the signature - * @return a created md instance. throws if unknown oid. - */ -var _verifySignature = function(options) { - var cert = options.certificate; - var scheme; - - switch(cert.signatureOid) { - case oids.sha1WithRSAEncryption: - // deprecated alias - case oids.sha1WithRSASignature: - /* use PKCS#1 v1.5 padding scheme */ - break; - case oids['RSASSA-PSS']: - var hash, mgf; - - /* initialize mgf */ - hash = oids[cert.signatureParameters.mgf.hash.algorithmOid]; - if(hash === undefined || forge$c.md[hash] === undefined) { - var error = new Error('Unsupported MGF hash function.'); - error.oid = cert.signatureParameters.mgf.hash.algorithmOid; - error.name = hash; - throw error; - } - - mgf = oids[cert.signatureParameters.mgf.algorithmOid]; - if(mgf === undefined || forge$c.mgf[mgf] === undefined) { - var error = new Error('Unsupported MGF function.'); - error.oid = cert.signatureParameters.mgf.algorithmOid; - error.name = mgf; - throw error; - } - - mgf = forge$c.mgf[mgf].create(forge$c.md[hash].create()); - - /* initialize hash function */ - hash = oids[cert.signatureParameters.hash.algorithmOid]; - if(hash === undefined || forge$c.md[hash] === undefined) { - var error = new Error('Unsupported RSASSA-PSS hash function.'); - error.oid = cert.signatureParameters.hash.algorithmOid; - error.name = hash; - throw error; - } - - scheme = forge$c.pss.create( - forge$c.md[hash].create(), mgf, cert.signatureParameters.saltLength - ); - break; - } - - // verify signature on cert using public key - return cert.publicKey.verify( - options.md.digest().getBytes(), options.signature, scheme - ); -}; - -/** - * Converts an X.509 certificate from PEM format. - * - * Note: If the certificate is to be verified then compute hash should - * be set to true. This will scan the TBSCertificate part of the ASN.1 - * object while it is converted so it doesn't need to be converted back - * to ASN.1-DER-encoding later. - * - * @param pem the PEM-formatted certificate. - * @param computeHash true to compute the hash for verification. - * @param strict true to be strict when checking ASN.1 value lengths, false to - * allow truncated values (default: true). - * - * @return the certificate. - */ -pki$2.certificateFromPem = function(pem, computeHash, strict) { - var msg = forge$c.pem.decode(pem)[0]; - - if(msg.type !== 'CERTIFICATE' && - msg.type !== 'X509 CERTIFICATE' && - msg.type !== 'TRUSTED CERTIFICATE') { - var error = new Error( - 'Could not convert certificate from PEM; PEM header type ' + - 'is not "CERTIFICATE", "X509 CERTIFICATE", or "TRUSTED CERTIFICATE".'); - error.headerType = msg.type; - throw error; - } - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - throw new Error( - 'Could not convert certificate from PEM; PEM is encrypted.'); - } - - // convert DER to ASN.1 object - var obj = asn1$4.fromDer(msg.body, strict); - - return pki$2.certificateFromAsn1(obj, computeHash); -}; - -/** - * Converts an X.509 certificate to PEM format. - * - * @param cert the certificate. - * @param maxline the maximum characters per line, defaults to 64. - * - * @return the PEM-formatted certificate. - */ -pki$2.certificateToPem = function(cert, maxline) { - // convert to ASN.1, then DER, then PEM-encode - var msg = { - type: 'CERTIFICATE', - body: asn1$4.toDer(pki$2.certificateToAsn1(cert)).getBytes() - }; - return forge$c.pem.encode(msg, {maxline: maxline}); -}; - -/** - * Converts an RSA public key from PEM format. - * - * @param pem the PEM-formatted public key. - * - * @return the public key. - */ -pki$2.publicKeyFromPem = function(pem) { - var msg = forge$c.pem.decode(pem)[0]; - - if(msg.type !== 'PUBLIC KEY' && msg.type !== 'RSA PUBLIC KEY') { - var error = new Error('Could not convert public key from PEM; PEM header ' + - 'type is not "PUBLIC KEY" or "RSA PUBLIC KEY".'); - error.headerType = msg.type; - throw error; - } - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - throw new Error('Could not convert public key from PEM; PEM is encrypted.'); - } - - // convert DER to ASN.1 object - var obj = asn1$4.fromDer(msg.body); - - return pki$2.publicKeyFromAsn1(obj); -}; - -/** - * Converts an RSA public key to PEM format (using a SubjectPublicKeyInfo). - * - * @param key the public key. - * @param maxline the maximum characters per line, defaults to 64. - * - * @return the PEM-formatted public key. - */ -pki$2.publicKeyToPem = function(key, maxline) { - // convert to ASN.1, then DER, then PEM-encode - var msg = { - type: 'PUBLIC KEY', - body: asn1$4.toDer(pki$2.publicKeyToAsn1(key)).getBytes() - }; - return forge$c.pem.encode(msg, {maxline: maxline}); -}; - -/** - * Converts an RSA public key to PEM format (using an RSAPublicKey). - * - * @param key the public key. - * @param maxline the maximum characters per line, defaults to 64. - * - * @return the PEM-formatted public key. - */ -pki$2.publicKeyToRSAPublicKeyPem = function(key, maxline) { - // convert to ASN.1, then DER, then PEM-encode - var msg = { - type: 'RSA PUBLIC KEY', - body: asn1$4.toDer(pki$2.publicKeyToRSAPublicKey(key)).getBytes() - }; - return forge$c.pem.encode(msg, {maxline: maxline}); -}; - -/** - * Gets a fingerprint for the given public key. - * - * @param options the options to use. - * [md] the message digest object to use (defaults to forge.md.sha1). - * [type] the type of fingerprint, such as 'RSAPublicKey', - * 'SubjectPublicKeyInfo' (defaults to 'RSAPublicKey'). - * [encoding] an alternative output encoding, such as 'hex' - * (defaults to none, outputs a byte buffer). - * [delimiter] the delimiter to use between bytes for 'hex' encoded - * output, eg: ':' (defaults to none). - * - * @return the fingerprint as a byte buffer or other encoding based on options. - */ -pki$2.getPublicKeyFingerprint = function(key, options) { - options = options || {}; - var md = options.md || forge$c.md.sha1.create(); - var type = options.type || 'RSAPublicKey'; - - var bytes; - switch(type) { - case 'RSAPublicKey': - bytes = asn1$4.toDer(pki$2.publicKeyToRSAPublicKey(key)).getBytes(); - break; - case 'SubjectPublicKeyInfo': - bytes = asn1$4.toDer(pki$2.publicKeyToAsn1(key)).getBytes(); - break; - default: - throw new Error('Unknown fingerprint type "' + options.type + '".'); - } - - // hash public key bytes - md.start(); - md.update(bytes); - var digest = md.digest(); - if(options.encoding === 'hex') { - var hex = digest.toHex(); - if(options.delimiter) { - return hex.match(/.{2}/g).join(options.delimiter); - } - return hex; - } else if(options.encoding === 'binary') { - return digest.getBytes(); - } else if(options.encoding) { - throw new Error('Unknown encoding "' + options.encoding + '".'); - } - return digest; -}; - -/** - * Converts a PKCS#10 certification request (CSR) from PEM format. - * - * Note: If the certification request is to be verified then compute hash - * should be set to true. This will scan the CertificationRequestInfo part of - * the ASN.1 object while it is converted so it doesn't need to be converted - * back to ASN.1-DER-encoding later. - * - * @param pem the PEM-formatted certificate. - * @param computeHash true to compute the hash for verification. - * @param strict true to be strict when checking ASN.1 value lengths, false to - * allow truncated values (default: true). - * - * @return the certification request (CSR). - */ -pki$2.certificationRequestFromPem = function(pem, computeHash, strict) { - var msg = forge$c.pem.decode(pem)[0]; - - if(msg.type !== 'CERTIFICATE REQUEST') { - var error = new Error('Could not convert certification request from PEM; ' + - 'PEM header type is not "CERTIFICATE REQUEST".'); - error.headerType = msg.type; - throw error; - } - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - throw new Error('Could not convert certification request from PEM; ' + - 'PEM is encrypted.'); - } - - // convert DER to ASN.1 object - var obj = asn1$4.fromDer(msg.body, strict); - - return pki$2.certificationRequestFromAsn1(obj, computeHash); -}; - -/** - * Converts a PKCS#10 certification request (CSR) to PEM format. - * - * @param csr the certification request. - * @param maxline the maximum characters per line, defaults to 64. - * - * @return the PEM-formatted certification request. - */ -pki$2.certificationRequestToPem = function(csr, maxline) { - // convert to ASN.1, then DER, then PEM-encode - var msg = { - type: 'CERTIFICATE REQUEST', - body: asn1$4.toDer(pki$2.certificationRequestToAsn1(csr)).getBytes() - }; - return forge$c.pem.encode(msg, {maxline: maxline}); -}; - -/** - * Creates an empty X.509v3 RSA certificate. - * - * @return the certificate. - */ -pki$2.createCertificate = function() { - var cert = {}; - cert.version = 0x02; - cert.serialNumber = '00'; - cert.signatureOid = null; - cert.signature = null; - cert.siginfo = {}; - cert.siginfo.algorithmOid = null; - cert.validity = {}; - cert.validity.notBefore = new Date(); - cert.validity.notAfter = new Date(); - - cert.issuer = {}; - cert.issuer.getField = function(sn) { - return _getAttribute(cert.issuer, sn); - }; - cert.issuer.addField = function(attr) { - _fillMissingFields([attr]); - cert.issuer.attributes.push(attr); - }; - cert.issuer.attributes = []; - cert.issuer.hash = null; - - cert.subject = {}; - cert.subject.getField = function(sn) { - return _getAttribute(cert.subject, sn); - }; - cert.subject.addField = function(attr) { - _fillMissingFields([attr]); - cert.subject.attributes.push(attr); - }; - cert.subject.attributes = []; - cert.subject.hash = null; - - cert.extensions = []; - cert.publicKey = null; - cert.md = null; - - /** - * Sets the subject of this certificate. - * - * @param attrs the array of subject attributes to use. - * @param uniqueId an optional a unique ID to use. - */ - cert.setSubject = function(attrs, uniqueId) { - // set new attributes, clear hash - _fillMissingFields(attrs); - cert.subject.attributes = attrs; - delete cert.subject.uniqueId; - if(uniqueId) { - // TODO: support arbitrary bit length ids - cert.subject.uniqueId = uniqueId; - } - cert.subject.hash = null; - }; - - /** - * Sets the issuer of this certificate. - * - * @param attrs the array of issuer attributes to use. - * @param uniqueId an optional a unique ID to use. - */ - cert.setIssuer = function(attrs, uniqueId) { - // set new attributes, clear hash - _fillMissingFields(attrs); - cert.issuer.attributes = attrs; - delete cert.issuer.uniqueId; - if(uniqueId) { - // TODO: support arbitrary bit length ids - cert.issuer.uniqueId = uniqueId; - } - cert.issuer.hash = null; - }; - - /** - * Sets the extensions of this certificate. - * - * @param exts the array of extensions to use. - */ - cert.setExtensions = function(exts) { - for(var i = 0; i < exts.length; ++i) { - _fillMissingExtensionFields(exts[i], {cert: cert}); - } - // set new extensions - cert.extensions = exts; - }; - - /** - * Gets an extension by its name or id. - * - * @param options the name to use or an object with: - * name the name to use. - * id the id to use. - * - * @return the extension or null if not found. - */ - cert.getExtension = function(options) { - if(typeof options === 'string') { - options = {name: options}; - } - - var rval = null; - var ext; - for(var i = 0; rval === null && i < cert.extensions.length; ++i) { - ext = cert.extensions[i]; - if(options.id && ext.id === options.id) { - rval = ext; - } else if(options.name && ext.name === options.name) { - rval = ext; - } - } - return rval; - }; - - /** - * Signs this certificate using the given private key. - * - * @param key the private key to sign with. - * @param md the message digest object to use (defaults to forge.md.sha1). - */ - cert.sign = function(key, md) { - // TODO: get signature OID from private key - cert.md = md || forge$c.md.sha1.create(); - var algorithmOid = oids[cert.md.algorithm + 'WithRSAEncryption']; - if(!algorithmOid) { - var error = new Error('Could not compute certificate digest. ' + - 'Unknown message digest algorithm OID.'); - error.algorithm = cert.md.algorithm; - throw error; - } - cert.signatureOid = cert.siginfo.algorithmOid = algorithmOid; - - // get TBSCertificate, convert to DER - cert.tbsCertificate = pki$2.getTBSCertificate(cert); - var bytes = asn1$4.toDer(cert.tbsCertificate); - - // digest and sign - cert.md.update(bytes.getBytes()); - cert.signature = key.sign(cert.md); - }; - - /** - * Attempts verify the signature on the passed certificate using this - * certificate's public key. - * - * @param child the certificate to verify. - * - * @return true if verified, false if not. - */ - cert.verify = function(child) { - var rval = false; - - if(!cert.issued(child)) { - var issuer = child.issuer; - var subject = cert.subject; - var error = new Error( - 'The parent certificate did not issue the given child ' + - 'certificate; the child certificate\'s issuer does not match the ' + - 'parent\'s subject.'); - error.expectedIssuer = subject.attributes; - error.actualIssuer = issuer.attributes; - throw error; - } - - var md = child.md; - if(md === null) { - // create digest for OID signature types - md = _createSignatureDigest({ - signatureOid: child.signatureOid, - type: 'certificate' - }); - - // produce DER formatted TBSCertificate and digest it - var tbsCertificate = child.tbsCertificate || pki$2.getTBSCertificate(child); - var bytes = asn1$4.toDer(tbsCertificate); - md.update(bytes.getBytes()); - } - - if(md !== null) { - rval = _verifySignature({ - certificate: cert, md: md, signature: child.signature - }); - } - - return rval; - }; - - /** - * Returns true if this certificate's issuer matches the passed - * certificate's subject. Note that no signature check is performed. - * - * @param parent the certificate to check. - * - * @return true if this certificate's issuer matches the passed certificate's - * subject. - */ - cert.isIssuer = function(parent) { - var rval = false; - - var i = cert.issuer; - var s = parent.subject; - - // compare hashes if present - if(i.hash && s.hash) { - rval = (i.hash === s.hash); - } else if(i.attributes.length === s.attributes.length) { - // all attributes are the same so issuer matches subject - rval = true; - var iattr, sattr; - for(var n = 0; rval && n < i.attributes.length; ++n) { - iattr = i.attributes[n]; - sattr = s.attributes[n]; - if(iattr.type !== sattr.type || iattr.value !== sattr.value) { - // attribute mismatch - rval = false; - } - } - } - - return rval; - }; - - /** - * Returns true if this certificate's subject matches the issuer of the - * given certificate). Note that not signature check is performed. - * - * @param child the certificate to check. - * - * @return true if this certificate's subject matches the passed - * certificate's issuer. - */ - cert.issued = function(child) { - return child.isIssuer(cert); - }; - - /** - * Generates the subjectKeyIdentifier for this certificate as byte buffer. - * - * @return the subjectKeyIdentifier for this certificate as byte buffer. - */ - cert.generateSubjectKeyIdentifier = function() { - /* See: 4.2.1.2 section of the the RFC3280, keyIdentifier is either: - - (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the - value of the BIT STRING subjectPublicKey (excluding the tag, - length, and number of unused bits). - - (2) The keyIdentifier is composed of a four bit type field with - the value 0100 followed by the least significant 60 bits of the - SHA-1 hash of the value of the BIT STRING subjectPublicKey - (excluding the tag, length, and number of unused bit string bits). - */ - - // skipping the tag, length, and number of unused bits is the same - // as just using the RSAPublicKey (for RSA keys, which are the - // only ones supported) - return pki$2.getPublicKeyFingerprint(cert.publicKey, {type: 'RSAPublicKey'}); - }; - - /** - * Verifies the subjectKeyIdentifier extension value for this certificate - * against its public key. If no extension is found, false will be - * returned. - * - * @return true if verified, false if not. - */ - cert.verifySubjectKeyIdentifier = function() { - var oid = oids['subjectKeyIdentifier']; - for(var i = 0; i < cert.extensions.length; ++i) { - var ext = cert.extensions[i]; - if(ext.id === oid) { - var ski = cert.generateSubjectKeyIdentifier().getBytes(); - return (forge$c.util.hexToBytes(ext.subjectKeyIdentifier) === ski); - } - } - return false; - }; - - return cert; -}; - -/** - * Converts an X.509v3 RSA certificate from an ASN.1 object. - * - * Note: If the certificate is to be verified then compute hash should - * be set to true. There is currently no implementation for converting - * a certificate back to ASN.1 so the TBSCertificate part of the ASN.1 - * object needs to be scanned before the cert object is created. - * - * @param obj the asn1 representation of an X.509v3 RSA certificate. - * @param computeHash true to compute the hash for verification. - * - * @return the certificate. - */ -pki$2.certificateFromAsn1 = function(obj, computeHash) { - // validate certificate and capture data - var capture = {}; - var errors = []; - if(!asn1$4.validate(obj, x509CertificateValidator, capture, errors)) { - var error = new Error('Cannot read X.509 certificate. ' + - 'ASN.1 object is not an X509v3 Certificate.'); - error.errors = errors; - throw error; - } - - // get oid - var oid = asn1$4.derToOid(capture.publicKeyOid); - if(oid !== pki$2.oids.rsaEncryption) { - throw new Error('Cannot read public key. OID is not RSA.'); - } - - // create certificate - var cert = pki$2.createCertificate(); - cert.version = capture.certVersion ? - capture.certVersion.charCodeAt(0) : 0; - var serial = forge$c.util.createBuffer(capture.certSerialNumber); - cert.serialNumber = serial.toHex(); - cert.signatureOid = forge$c.asn1.derToOid(capture.certSignatureOid); - cert.signatureParameters = _readSignatureParameters( - cert.signatureOid, capture.certSignatureParams, true); - cert.siginfo.algorithmOid = forge$c.asn1.derToOid(capture.certinfoSignatureOid); - cert.siginfo.parameters = _readSignatureParameters(cert.siginfo.algorithmOid, - capture.certinfoSignatureParams, false); - cert.signature = capture.certSignature; - - var validity = []; - if(capture.certValidity1UTCTime !== undefined) { - validity.push(asn1$4.utcTimeToDate(capture.certValidity1UTCTime)); - } - if(capture.certValidity2GeneralizedTime !== undefined) { - validity.push(asn1$4.generalizedTimeToDate( - capture.certValidity2GeneralizedTime)); - } - if(capture.certValidity3UTCTime !== undefined) { - validity.push(asn1$4.utcTimeToDate(capture.certValidity3UTCTime)); - } - if(capture.certValidity4GeneralizedTime !== undefined) { - validity.push(asn1$4.generalizedTimeToDate( - capture.certValidity4GeneralizedTime)); - } - if(validity.length > 2) { - throw new Error('Cannot read notBefore/notAfter validity times; more ' + - 'than two times were provided in the certificate.'); - } - if(validity.length < 2) { - throw new Error('Cannot read notBefore/notAfter validity times; they ' + - 'were not provided as either UTCTime or GeneralizedTime.'); - } - cert.validity.notBefore = validity[0]; - cert.validity.notAfter = validity[1]; - - // keep TBSCertificate to preserve signature when exporting - cert.tbsCertificate = capture.tbsCertificate; - - if(computeHash) { - // create digest for OID signature type - cert.md = _createSignatureDigest({ - signatureOid: cert.signatureOid, - type: 'certificate' - }); - - // produce DER formatted TBSCertificate and digest it - var bytes = asn1$4.toDer(cert.tbsCertificate); - cert.md.update(bytes.getBytes()); - } - - // handle issuer, build issuer message digest - var imd = forge$c.md.sha1.create(); - var ibytes = asn1$4.toDer(capture.certIssuer); - imd.update(ibytes.getBytes()); - cert.issuer.getField = function(sn) { - return _getAttribute(cert.issuer, sn); - }; - cert.issuer.addField = function(attr) { - _fillMissingFields([attr]); - cert.issuer.attributes.push(attr); - }; - cert.issuer.attributes = pki$2.RDNAttributesAsArray(capture.certIssuer); - if(capture.certIssuerUniqueId) { - cert.issuer.uniqueId = capture.certIssuerUniqueId; - } - cert.issuer.hash = imd.digest().toHex(); - - // handle subject, build subject message digest - var smd = forge$c.md.sha1.create(); - var sbytes = asn1$4.toDer(capture.certSubject); - smd.update(sbytes.getBytes()); - cert.subject.getField = function(sn) { - return _getAttribute(cert.subject, sn); - }; - cert.subject.addField = function(attr) { - _fillMissingFields([attr]); - cert.subject.attributes.push(attr); - }; - cert.subject.attributes = pki$2.RDNAttributesAsArray(capture.certSubject); - if(capture.certSubjectUniqueId) { - cert.subject.uniqueId = capture.certSubjectUniqueId; - } - cert.subject.hash = smd.digest().toHex(); - - // handle extensions - if(capture.certExtensions) { - cert.extensions = pki$2.certificateExtensionsFromAsn1(capture.certExtensions); - } else { - cert.extensions = []; - } - - // convert RSA public key from ASN.1 - cert.publicKey = pki$2.publicKeyFromAsn1(capture.subjectPublicKeyInfo); - - return cert; -}; - -/** - * Converts an ASN.1 extensions object (with extension sequences as its - * values) into an array of extension objects with types and values. - * - * Supported extensions: - * - * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } - * KeyUsage ::= BIT STRING { - * digitalSignature (0), - * nonRepudiation (1), - * keyEncipherment (2), - * dataEncipherment (3), - * keyAgreement (4), - * keyCertSign (5), - * cRLSign (6), - * encipherOnly (7), - * decipherOnly (8) - * } - * - * id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL - * } - * - * subjectAltName EXTENSION ::= { - * SYNTAX GeneralNames - * IDENTIFIED BY id-ce-subjectAltName - * } - * - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] INSTANCE OF OTHER-NAME, - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * IPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER - * } - * - * OTHER-NAME ::= TYPE-IDENTIFIER - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString {ub-name} OPTIONAL, - * partyName [1] DirectoryString {ub-name} - * } - * - * @param exts the extensions ASN.1 with extension sequences to parse. - * - * @return the array. - */ -pki$2.certificateExtensionsFromAsn1 = function(exts) { - var rval = []; - for(var i = 0; i < exts.value.length; ++i) { - // get extension sequence - var extseq = exts.value[i]; - for(var ei = 0; ei < extseq.value.length; ++ei) { - rval.push(pki$2.certificateExtensionFromAsn1(extseq.value[ei])); - } - } - - return rval; -}; - -/** - * Parses a single certificate extension from ASN.1. - * - * @param ext the extension in ASN.1 format. - * - * @return the parsed extension as an object. - */ -pki$2.certificateExtensionFromAsn1 = function(ext) { - // an extension has: - // [0] extnID OBJECT IDENTIFIER - // [1] critical BOOLEAN DEFAULT FALSE - // [2] extnValue OCTET STRING - var e = {}; - e.id = asn1$4.derToOid(ext.value[0].value); - e.critical = false; - if(ext.value[1].type === asn1$4.Type.BOOLEAN) { - e.critical = (ext.value[1].value.charCodeAt(0) !== 0x00); - e.value = ext.value[2].value; - } else { - e.value = ext.value[1].value; - } - // if the oid is known, get its name - if(e.id in oids) { - e.name = oids[e.id]; - - // handle key usage - if(e.name === 'keyUsage') { - // get value as BIT STRING - var ev = asn1$4.fromDer(e.value); - var b2 = 0x00; - var b3 = 0x00; - if(ev.value.length > 1) { - // skip first byte, just indicates unused bits which - // will be padded with 0s anyway - // get bytes with flag bits - b2 = ev.value.charCodeAt(1); - b3 = ev.value.length > 2 ? ev.value.charCodeAt(2) : 0; - } - // set flags - e.digitalSignature = (b2 & 0x80) === 0x80; - e.nonRepudiation = (b2 & 0x40) === 0x40; - e.keyEncipherment = (b2 & 0x20) === 0x20; - e.dataEncipherment = (b2 & 0x10) === 0x10; - e.keyAgreement = (b2 & 0x08) === 0x08; - e.keyCertSign = (b2 & 0x04) === 0x04; - e.cRLSign = (b2 & 0x02) === 0x02; - e.encipherOnly = (b2 & 0x01) === 0x01; - e.decipherOnly = (b3 & 0x80) === 0x80; - } else if(e.name === 'basicConstraints') { - // handle basic constraints - // get value as SEQUENCE - var ev = asn1$4.fromDer(e.value); - // get cA BOOLEAN flag (defaults to false) - if(ev.value.length > 0 && ev.value[0].type === asn1$4.Type.BOOLEAN) { - e.cA = (ev.value[0].value.charCodeAt(0) !== 0x00); - } else { - e.cA = false; - } - // get path length constraint - var value = null; - if(ev.value.length > 0 && ev.value[0].type === asn1$4.Type.INTEGER) { - value = ev.value[0].value; - } else if(ev.value.length > 1) { - value = ev.value[1].value; - } - if(value !== null) { - e.pathLenConstraint = asn1$4.derToInteger(value); - } - } else if(e.name === 'extKeyUsage') { - // handle extKeyUsage - // value is a SEQUENCE of OIDs - var ev = asn1$4.fromDer(e.value); - for(var vi = 0; vi < ev.value.length; ++vi) { - var oid = asn1$4.derToOid(ev.value[vi].value); - if(oid in oids) { - e[oids[oid]] = true; - } else { - e[oid] = true; - } - } - } else if(e.name === 'nsCertType') { - // handle nsCertType - // get value as BIT STRING - var ev = asn1$4.fromDer(e.value); - var b2 = 0x00; - if(ev.value.length > 1) { - // skip first byte, just indicates unused bits which - // will be padded with 0s anyway - // get bytes with flag bits - b2 = ev.value.charCodeAt(1); - } - // set flags - e.client = (b2 & 0x80) === 0x80; - e.server = (b2 & 0x40) === 0x40; - e.email = (b2 & 0x20) === 0x20; - e.objsign = (b2 & 0x10) === 0x10; - e.reserved = (b2 & 0x08) === 0x08; - e.sslCA = (b2 & 0x04) === 0x04; - e.emailCA = (b2 & 0x02) === 0x02; - e.objCA = (b2 & 0x01) === 0x01; - } else if( - e.name === 'subjectAltName' || - e.name === 'issuerAltName') { - // handle subjectAltName/issuerAltName - e.altNames = []; - - // ev is a SYNTAX SEQUENCE - var gn; - var ev = asn1$4.fromDer(e.value); - for(var n = 0; n < ev.value.length; ++n) { - // get GeneralName - gn = ev.value[n]; - - var altName = { - type: gn.type, - value: gn.value - }; - e.altNames.push(altName); - - // Note: Support for types 1,2,6,7,8 - switch(gn.type) { - // rfc822Name - case 1: - // dNSName - case 2: - // uniformResourceIdentifier (URI) - case 6: - break; - // IPAddress - case 7: - // convert to IPv4/IPv6 string representation - altName.ip = forge$c.util.bytesToIP(gn.value); - break; - // registeredID - case 8: - altName.oid = asn1$4.derToOid(gn.value); - break; - // unsupported - } - } - } else if(e.name === 'subjectKeyIdentifier') { - // value is an OCTETSTRING w/the hash of the key-type specific - // public key structure (eg: RSAPublicKey) - var ev = asn1$4.fromDer(e.value); - e.subjectKeyIdentifier = forge$c.util.bytesToHex(ev.value); - } - } - return e; -}; - -/** - * Converts a PKCS#10 certification request (CSR) from an ASN.1 object. - * - * Note: If the certification request is to be verified then compute hash - * should be set to true. There is currently no implementation for converting - * a certificate back to ASN.1 so the CertificationRequestInfo part of the - * ASN.1 object needs to be scanned before the csr object is created. - * - * @param obj the asn1 representation of a PKCS#10 certification request (CSR). - * @param computeHash true to compute the hash for verification. - * - * @return the certification request (CSR). - */ -pki$2.certificationRequestFromAsn1 = function(obj, computeHash) { - // validate certification request and capture data - var capture = {}; - var errors = []; - if(!asn1$4.validate(obj, certificationRequestValidator, capture, errors)) { - var error = new Error('Cannot read PKCS#10 certificate request. ' + - 'ASN.1 object is not a PKCS#10 CertificationRequest.'); - error.errors = errors; - throw error; - } - - // get oid - var oid = asn1$4.derToOid(capture.publicKeyOid); - if(oid !== pki$2.oids.rsaEncryption) { - throw new Error('Cannot read public key. OID is not RSA.'); - } - - // create certification request - var csr = pki$2.createCertificationRequest(); - csr.version = capture.csrVersion ? capture.csrVersion.charCodeAt(0) : 0; - csr.signatureOid = forge$c.asn1.derToOid(capture.csrSignatureOid); - csr.signatureParameters = _readSignatureParameters( - csr.signatureOid, capture.csrSignatureParams, true); - csr.siginfo.algorithmOid = forge$c.asn1.derToOid(capture.csrSignatureOid); - csr.siginfo.parameters = _readSignatureParameters( - csr.siginfo.algorithmOid, capture.csrSignatureParams, false); - csr.signature = capture.csrSignature; - - // keep CertificationRequestInfo to preserve signature when exporting - csr.certificationRequestInfo = capture.certificationRequestInfo; - - if(computeHash) { - // create digest for OID signature type - csr.md = _createSignatureDigest({ - signatureOid: csr.signatureOid, - type: 'certification request' - }); - - // produce DER formatted CertificationRequestInfo and digest it - var bytes = asn1$4.toDer(csr.certificationRequestInfo); - csr.md.update(bytes.getBytes()); - } - - // handle subject, build subject message digest - var smd = forge$c.md.sha1.create(); - csr.subject.getField = function(sn) { - return _getAttribute(csr.subject, sn); - }; - csr.subject.addField = function(attr) { - _fillMissingFields([attr]); - csr.subject.attributes.push(attr); - }; - csr.subject.attributes = pki$2.RDNAttributesAsArray( - capture.certificationRequestInfoSubject, smd); - csr.subject.hash = smd.digest().toHex(); - - // convert RSA public key from ASN.1 - csr.publicKey = pki$2.publicKeyFromAsn1(capture.subjectPublicKeyInfo); - - // convert attributes from ASN.1 - csr.getAttribute = function(sn) { - return _getAttribute(csr, sn); - }; - csr.addAttribute = function(attr) { - _fillMissingFields([attr]); - csr.attributes.push(attr); - }; - csr.attributes = pki$2.CRIAttributesAsArray( - capture.certificationRequestInfoAttributes || []); - - return csr; -}; - -/** - * Creates an empty certification request (a CSR or certificate signing - * request). Once created, its public key and attributes can be set and then - * it can be signed. - * - * @return the empty certification request. - */ -pki$2.createCertificationRequest = function() { - var csr = {}; - csr.version = 0x00; - csr.signatureOid = null; - csr.signature = null; - csr.siginfo = {}; - csr.siginfo.algorithmOid = null; - - csr.subject = {}; - csr.subject.getField = function(sn) { - return _getAttribute(csr.subject, sn); - }; - csr.subject.addField = function(attr) { - _fillMissingFields([attr]); - csr.subject.attributes.push(attr); - }; - csr.subject.attributes = []; - csr.subject.hash = null; - - csr.publicKey = null; - csr.attributes = []; - csr.getAttribute = function(sn) { - return _getAttribute(csr, sn); - }; - csr.addAttribute = function(attr) { - _fillMissingFields([attr]); - csr.attributes.push(attr); - }; - csr.md = null; - - /** - * Sets the subject of this certification request. - * - * @param attrs the array of subject attributes to use. - */ - csr.setSubject = function(attrs) { - // set new attributes - _fillMissingFields(attrs); - csr.subject.attributes = attrs; - csr.subject.hash = null; - }; - - /** - * Sets the attributes of this certification request. - * - * @param attrs the array of attributes to use. - */ - csr.setAttributes = function(attrs) { - // set new attributes - _fillMissingFields(attrs); - csr.attributes = attrs; - }; - - /** - * Signs this certification request using the given private key. - * - * @param key the private key to sign with. - * @param md the message digest object to use (defaults to forge.md.sha1). - */ - csr.sign = function(key, md) { - // TODO: get signature OID from private key - csr.md = md || forge$c.md.sha1.create(); - var algorithmOid = oids[csr.md.algorithm + 'WithRSAEncryption']; - if(!algorithmOid) { - var error = new Error('Could not compute certification request digest. ' + - 'Unknown message digest algorithm OID.'); - error.algorithm = csr.md.algorithm; - throw error; - } - csr.signatureOid = csr.siginfo.algorithmOid = algorithmOid; - - // get CertificationRequestInfo, convert to DER - csr.certificationRequestInfo = pki$2.getCertificationRequestInfo(csr); - var bytes = asn1$4.toDer(csr.certificationRequestInfo); - - // digest and sign - csr.md.update(bytes.getBytes()); - csr.signature = key.sign(csr.md); - }; - - /** - * Attempts verify the signature on the passed certification request using - * its public key. - * - * A CSR that has been exported to a file in PEM format can be verified using - * OpenSSL using this command: - * - * openssl req -in -verify -noout -text - * - * @return true if verified, false if not. - */ - csr.verify = function() { - var rval = false; - - var md = csr.md; - if(md === null) { - md = _createSignatureDigest({ - signatureOid: csr.signatureOid, - type: 'certification request' - }); - - // produce DER formatted CertificationRequestInfo and digest it - var cri = csr.certificationRequestInfo || - pki$2.getCertificationRequestInfo(csr); - var bytes = asn1$4.toDer(cri); - md.update(bytes.getBytes()); - } - - if(md !== null) { - rval = _verifySignature({ - certificate: csr, md: md, signature: csr.signature - }); - } - - return rval; - }; - - return csr; -}; - -/** - * Converts an X.509 subject or issuer to an ASN.1 RDNSequence. - * - * @param obj the subject or issuer (distinguished name). - * - * @return the ASN.1 RDNSequence. - */ -function _dnToAsn1(obj) { - // create an empty RDNSequence - var rval = asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - - // iterate over attributes - var attr, set; - var attrs = obj.attributes; - for(var i = 0; i < attrs.length; ++i) { - attr = attrs[i]; - var value = attr.value; - - // reuse tag class for attribute value if available - var valueTagClass = asn1$4.Type.PRINTABLESTRING; - if('valueTagClass' in attr) { - valueTagClass = attr.valueTagClass; - - if(valueTagClass === asn1$4.Type.UTF8) { - value = forge$c.util.encodeUtf8(value); - } - // FIXME: handle more encodings - } - - // create a RelativeDistinguishedName set - // each value in the set is an AttributeTypeAndValue first - // containing the type (an OID) and second the value - set = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SET, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // AttributeType - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(attr.type).getBytes()), - // AttributeValue - asn1$4.create(asn1$4.Class.UNIVERSAL, valueTagClass, false, value) - ]) - ]); - rval.value.push(set); - } - - return rval; -} - -/** - * Fills in missing fields in attributes. - * - * @param attrs the attributes to fill missing fields in. - */ -function _fillMissingFields(attrs) { - var attr; - for(var i = 0; i < attrs.length; ++i) { - attr = attrs[i]; - - // populate missing name - if(typeof attr.name === 'undefined') { - if(attr.type && attr.type in pki$2.oids) { - attr.name = pki$2.oids[attr.type]; - } else if(attr.shortName && attr.shortName in _shortNames) { - attr.name = pki$2.oids[_shortNames[attr.shortName]]; - } - } - - // populate missing type (OID) - if(typeof attr.type === 'undefined') { - if(attr.name && attr.name in pki$2.oids) { - attr.type = pki$2.oids[attr.name]; - } else { - var error = new Error('Attribute type not specified.'); - error.attribute = attr; - throw error; - } - } - - // populate missing shortname - if(typeof attr.shortName === 'undefined') { - if(attr.name && attr.name in _shortNames) { - attr.shortName = _shortNames[attr.name]; - } - } - - // convert extensions to value - if(attr.type === oids.extensionRequest) { - attr.valueConstructed = true; - attr.valueTagClass = asn1$4.Type.SEQUENCE; - if(!attr.value && attr.extensions) { - attr.value = []; - for(var ei = 0; ei < attr.extensions.length; ++ei) { - attr.value.push(pki$2.certificateExtensionToAsn1( - _fillMissingExtensionFields(attr.extensions[ei]))); - } - } - } - - if(typeof attr.value === 'undefined') { - var error = new Error('Attribute value not specified.'); - error.attribute = attr; - throw error; - } - } -} - -/** - * Fills in missing fields in certificate extensions. - * - * @param e the extension. - * @param [options] the options to use. - * [cert] the certificate the extensions are for. - * - * @return the extension. - */ -function _fillMissingExtensionFields(e, options) { - options = options || {}; - - // populate missing name - if(typeof e.name === 'undefined') { - if(e.id && e.id in pki$2.oids) { - e.name = pki$2.oids[e.id]; - } - } - - // populate missing id - if(typeof e.id === 'undefined') { - if(e.name && e.name in pki$2.oids) { - e.id = pki$2.oids[e.name]; - } else { - var error = new Error('Extension ID not specified.'); - error.extension = e; - throw error; - } - } - - if(typeof e.value !== 'undefined') { - return e; - } - - // handle missing value: - - // value is a BIT STRING - if(e.name === 'keyUsage') { - // build flags - var unused = 0; - var b2 = 0x00; - var b3 = 0x00; - if(e.digitalSignature) { - b2 |= 0x80; - unused = 7; - } - if(e.nonRepudiation) { - b2 |= 0x40; - unused = 6; - } - if(e.keyEncipherment) { - b2 |= 0x20; - unused = 5; - } - if(e.dataEncipherment) { - b2 |= 0x10; - unused = 4; - } - if(e.keyAgreement) { - b2 |= 0x08; - unused = 3; - } - if(e.keyCertSign) { - b2 |= 0x04; - unused = 2; - } - if(e.cRLSign) { - b2 |= 0x02; - unused = 1; - } - if(e.encipherOnly) { - b2 |= 0x01; - unused = 0; - } - if(e.decipherOnly) { - b3 |= 0x80; - unused = 7; - } - - // create bit string - var value = String.fromCharCode(unused); - if(b3 !== 0) { - value += String.fromCharCode(b2) + String.fromCharCode(b3); - } else if(b2 !== 0) { - value += String.fromCharCode(b2); - } - e.value = asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.BITSTRING, false, value); - } else if(e.name === 'basicConstraints') { - // basicConstraints is a SEQUENCE - e.value = asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - // cA BOOLEAN flag defaults to false - if(e.cA) { - e.value.value.push(asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.BOOLEAN, false, - String.fromCharCode(0xFF))); - } - if('pathLenConstraint' in e) { - e.value.value.push(asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.INTEGER, false, - asn1$4.integerToDer(e.pathLenConstraint).getBytes())); - } - } else if(e.name === 'extKeyUsage') { - // extKeyUsage is a SEQUENCE of OIDs - e.value = asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - var seq = e.value.value; - for(var key in e) { - if(e[key] !== true) { - continue; - } - // key is name in OID map - if(key in oids) { - seq.push(asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, - false, asn1$4.oidToDer(oids[key]).getBytes())); - } else if(key.indexOf('.') !== -1) { - // assume key is an OID - seq.push(asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, - false, asn1$4.oidToDer(key).getBytes())); - } - } - } else if(e.name === 'nsCertType') { - // nsCertType is a BIT STRING - // build flags - var unused = 0; - var b2 = 0x00; - - if(e.client) { - b2 |= 0x80; - unused = 7; - } - if(e.server) { - b2 |= 0x40; - unused = 6; - } - if(e.email) { - b2 |= 0x20; - unused = 5; - } - if(e.objsign) { - b2 |= 0x10; - unused = 4; - } - if(e.reserved) { - b2 |= 0x08; - unused = 3; - } - if(e.sslCA) { - b2 |= 0x04; - unused = 2; - } - if(e.emailCA) { - b2 |= 0x02; - unused = 1; - } - if(e.objCA) { - b2 |= 0x01; - unused = 0; - } - - // create bit string - var value = String.fromCharCode(unused); - if(b2 !== 0) { - value += String.fromCharCode(b2); - } - e.value = asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.BITSTRING, false, value); - } else if(e.name === 'subjectAltName' || e.name === 'issuerAltName') { - // SYNTAX SEQUENCE - e.value = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - - var altName; - for(var n = 0; n < e.altNames.length; ++n) { - altName = e.altNames[n]; - var value = altName.value; - // handle IP - if(altName.type === 7 && altName.ip) { - value = forge$c.util.bytesFromIP(altName.ip); - if(value === null) { - var error = new Error( - 'Extension "ip" value is not a valid IPv4 or IPv6 address.'); - error.extension = e; - throw error; - } - } else if(altName.type === 8) { - // handle OID - if(altName.oid) { - value = asn1$4.oidToDer(asn1$4.oidToDer(altName.oid)); - } else { - // deprecated ... convert value to OID - value = asn1$4.oidToDer(value); - } - } - e.value.value.push(asn1$4.create( - asn1$4.Class.CONTEXT_SPECIFIC, altName.type, false, - value)); - } - } else if(e.name === 'nsComment' && options.cert) { - // sanity check value is ASCII (req'd) and not too big - if(!(/^[\x00-\x7F]*$/.test(e.comment)) || - (e.comment.length < 1) || (e.comment.length > 128)) { - throw new Error('Invalid "nsComment" content.'); - } - // IA5STRING opaque comment - e.value = asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.IA5STRING, false, e.comment); - } else if(e.name === 'subjectKeyIdentifier' && options.cert) { - var ski = options.cert.generateSubjectKeyIdentifier(); - e.subjectKeyIdentifier = ski.toHex(); - // OCTETSTRING w/digest - e.value = asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.OCTETSTRING, false, ski.getBytes()); - } else if(e.name === 'authorityKeyIdentifier' && options.cert) { - // SYNTAX SEQUENCE - e.value = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - var seq = e.value.value; - - if(e.keyIdentifier) { - var keyIdentifier = (e.keyIdentifier === true ? - options.cert.generateSubjectKeyIdentifier().getBytes() : - e.keyIdentifier); - seq.push( - asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 0, false, keyIdentifier)); - } - - if(e.authorityCertIssuer) { - var authorityCertIssuer = [ - asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 4, true, [ - _dnToAsn1(e.authorityCertIssuer === true ? - options.cert.issuer : e.authorityCertIssuer) - ]) - ]; - seq.push( - asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 1, true, authorityCertIssuer)); - } - - if(e.serialNumber) { - var serialNumber = forge$c.util.hexToBytes(e.serialNumber === true ? - options.cert.serialNumber : e.serialNumber); - seq.push( - asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 2, false, serialNumber)); - } - } else if(e.name === 'cRLDistributionPoints') { - e.value = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - var seq = e.value.value; - - // Create sub SEQUENCE of DistributionPointName - var subSeq = asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - - // Create fullName CHOICE - var fullNameGeneralNames = asn1$4.create( - asn1$4.Class.CONTEXT_SPECIFIC, 0, true, []); - var altName; - for(var n = 0; n < e.altNames.length; ++n) { - altName = e.altNames[n]; - var value = altName.value; - // handle IP - if(altName.type === 7 && altName.ip) { - value = forge$c.util.bytesFromIP(altName.ip); - if(value === null) { - var error = new Error( - 'Extension "ip" value is not a valid IPv4 or IPv6 address.'); - error.extension = e; - throw error; - } - } else if(altName.type === 8) { - // handle OID - if(altName.oid) { - value = asn1$4.oidToDer(asn1$4.oidToDer(altName.oid)); - } else { - // deprecated ... convert value to OID - value = asn1$4.oidToDer(value); - } - } - fullNameGeneralNames.value.push(asn1$4.create( - asn1$4.Class.CONTEXT_SPECIFIC, altName.type, false, - value)); - } - - // Add to the parent SEQUENCE - subSeq.value.push(asn1$4.create( - asn1$4.Class.CONTEXT_SPECIFIC, 0, true, [fullNameGeneralNames])); - seq.push(subSeq); - } - - // ensure value has been defined by now - if(typeof e.value === 'undefined') { - var error = new Error('Extension value not specified.'); - error.extension = e; - throw error; - } - - return e; -} - -/** - * Convert signature parameters object to ASN.1 - * - * @param {String} oid Signature algorithm OID - * @param params The signature parametrs object - * @return ASN.1 object representing signature parameters - */ -function _signatureParametersToAsn1(oid, params) { - switch(oid) { - case oids['RSASSA-PSS']: - var parts = []; - - if(params.hash.algorithmOid !== undefined) { - parts.push(asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(params.hash.algorithmOid).getBytes()), - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.NULL, false, '') - ]) - ])); - } - - if(params.mgf.algorithmOid !== undefined) { - parts.push(asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 1, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(params.mgf.algorithmOid).getBytes()), - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(params.mgf.hash.algorithmOid).getBytes()), - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.NULL, false, '') - ]) - ]) - ])); - } - - if(params.saltLength !== undefined) { - parts.push(asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 2, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.INTEGER, false, - asn1$4.integerToDer(params.saltLength).getBytes()) - ])); - } - - return asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, parts); - - default: - return asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.NULL, false, ''); - } -} - -/** - * Converts a certification request's attributes to an ASN.1 set of - * CRIAttributes. - * - * @param csr certification request. - * - * @return the ASN.1 set of CRIAttributes. - */ -function _CRIAttributesToAsn1(csr) { - // create an empty context-specific container - var rval = asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 0, true, []); - - // no attributes, return empty container - if(csr.attributes.length === 0) { - return rval; - } - - // each attribute has a sequence with a type and a set of values - var attrs = csr.attributes; - for(var i = 0; i < attrs.length; ++i) { - var attr = attrs[i]; - var value = attr.value; - - // reuse tag class for attribute value if available - var valueTagClass = asn1$4.Type.UTF8; - if('valueTagClass' in attr) { - valueTagClass = attr.valueTagClass; - } - if(valueTagClass === asn1$4.Type.UTF8) { - value = forge$c.util.encodeUtf8(value); - } - var valueConstructed = false; - if('valueConstructed' in attr) { - valueConstructed = attr.valueConstructed; - } - // FIXME: handle more encodings - - // create a RelativeDistinguishedName set - // each value in the set is an AttributeTypeAndValue first - // containing the type (an OID) and second the value - var seq = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // AttributeType - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(attr.type).getBytes()), - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SET, true, [ - // AttributeValue - asn1$4.create( - asn1$4.Class.UNIVERSAL, valueTagClass, valueConstructed, value) - ]) - ]); - rval.value.push(seq); - } - - return rval; -} - -var jan_1_1950 = new Date('1950-01-01T00:00:00Z'); -var jan_1_2050 = new Date('2050-01-01T00:00:00Z'); - -/** - * Converts a Date object to ASN.1 - * Handles the different format before and after 1st January 2050 - * - * @param date date object. - * - * @return the ASN.1 object representing the date. - */ -function _dateToAsn1(date) { - if(date >= jan_1_1950 && date < jan_1_2050) { - return asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.UTCTIME, false, - asn1$4.dateToUtcTime(date)); - } else { - return asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.GENERALIZEDTIME, false, - asn1$4.dateToGeneralizedTime(date)); - } -} - -/** - * Gets the ASN.1 TBSCertificate part of an X.509v3 certificate. - * - * @param cert the certificate. - * - * @return the asn1 TBSCertificate. - */ -pki$2.getTBSCertificate = function(cert) { - // TBSCertificate - var notBefore = _dateToAsn1(cert.validity.notBefore); - var notAfter = _dateToAsn1(cert.validity.notAfter); - var tbs = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // version - asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 0, true, [ - // integer - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.INTEGER, false, - asn1$4.integerToDer(cert.version).getBytes()) - ]), - // serialNumber - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.INTEGER, false, - forge$c.util.hexToBytes(cert.serialNumber)), - // signature - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // algorithm - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(cert.siginfo.algorithmOid).getBytes()), - // parameters - _signatureParametersToAsn1( - cert.siginfo.algorithmOid, cert.siginfo.parameters) - ]), - // issuer - _dnToAsn1(cert.issuer), - // validity - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - notBefore, - notAfter - ]), - // subject - _dnToAsn1(cert.subject), - // SubjectPublicKeyInfo - pki$2.publicKeyToAsn1(cert.publicKey) - ]); - - if(cert.issuer.uniqueId) { - // issuerUniqueID (optional) - tbs.value.push( - asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 1, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.BITSTRING, false, - // TODO: support arbitrary bit length ids - String.fromCharCode(0x00) + - cert.issuer.uniqueId - ) - ]) - ); - } - if(cert.subject.uniqueId) { - // subjectUniqueID (optional) - tbs.value.push( - asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 2, true, [ - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.BITSTRING, false, - // TODO: support arbitrary bit length ids - String.fromCharCode(0x00) + - cert.subject.uniqueId - ) - ]) - ); - } - - if(cert.extensions.length > 0) { - // extensions (optional) - tbs.value.push(pki$2.certificateExtensionsToAsn1(cert.extensions)); - } - - return tbs; -}; - -/** - * Gets the ASN.1 CertificationRequestInfo part of a - * PKCS#10 CertificationRequest. - * - * @param csr the certification request. - * - * @return the asn1 CertificationRequestInfo. - */ -pki$2.getCertificationRequestInfo = function(csr) { - // CertificationRequestInfo - var cri = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // version - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.INTEGER, false, - asn1$4.integerToDer(csr.version).getBytes()), - // subject - _dnToAsn1(csr.subject), - // SubjectPublicKeyInfo - pki$2.publicKeyToAsn1(csr.publicKey), - // attributes - _CRIAttributesToAsn1(csr) - ]); - - return cri; -}; - -/** - * Converts a DistinguishedName (subject or issuer) to an ASN.1 object. - * - * @param dn the DistinguishedName. - * - * @return the asn1 representation of a DistinguishedName. - */ -pki$2.distinguishedNameToAsn1 = function(dn) { - return _dnToAsn1(dn); -}; - -/** - * Converts an X.509v3 RSA certificate to an ASN.1 object. - * - * @param cert the certificate. - * - * @return the asn1 representation of an X.509v3 RSA certificate. - */ -pki$2.certificateToAsn1 = function(cert) { - // prefer cached TBSCertificate over generating one - var tbsCertificate = cert.tbsCertificate || pki$2.getTBSCertificate(cert); - - // Certificate - return asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // TBSCertificate - tbsCertificate, - // AlgorithmIdentifier (signature algorithm) - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // algorithm - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(cert.signatureOid).getBytes()), - // parameters - _signatureParametersToAsn1(cert.signatureOid, cert.signatureParameters) - ]), - // SignatureValue - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.BITSTRING, false, - String.fromCharCode(0x00) + cert.signature) - ]); -}; - -/** - * Converts X.509v3 certificate extensions to ASN.1. - * - * @param exts the extensions to convert. - * - * @return the extensions in ASN.1 format. - */ -pki$2.certificateExtensionsToAsn1 = function(exts) { - // create top-level extension container - var rval = asn1$4.create(asn1$4.Class.CONTEXT_SPECIFIC, 3, true, []); - - // create extension sequence (stores a sequence for each extension) - var seq = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - rval.value.push(seq); - - for(var i = 0; i < exts.length; ++i) { - seq.value.push(pki$2.certificateExtensionToAsn1(exts[i])); - } - - return rval; -}; - -/** - * Converts a single certificate extension to ASN.1. - * - * @param ext the extension to convert. - * - * @return the extension in ASN.1 format. - */ -pki$2.certificateExtensionToAsn1 = function(ext) { - // create a sequence for each extension - var extseq = asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, []); - - // extnID (OID) - extseq.value.push(asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(ext.id).getBytes())); - - // critical defaults to false - if(ext.critical) { - // critical BOOLEAN DEFAULT FALSE - extseq.value.push(asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.BOOLEAN, false, - String.fromCharCode(0xFF))); - } - - var value = ext.value; - if(typeof ext.value !== 'string') { - // value is asn.1 - value = asn1$4.toDer(value).getBytes(); - } - - // extnValue (OCTET STRING) - extseq.value.push(asn1$4.create( - asn1$4.Class.UNIVERSAL, asn1$4.Type.OCTETSTRING, false, value)); - - return extseq; -}; - -/** - * Converts a PKCS#10 certification request to an ASN.1 object. - * - * @param csr the certification request. - * - * @return the asn1 representation of a certification request. - */ -pki$2.certificationRequestToAsn1 = function(csr) { - // prefer cached CertificationRequestInfo over generating one - var cri = csr.certificationRequestInfo || - pki$2.getCertificationRequestInfo(csr); - - // Certificate - return asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // CertificationRequestInfo - cri, - // AlgorithmIdentifier (signature algorithm) - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.SEQUENCE, true, [ - // algorithm - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.OID, false, - asn1$4.oidToDer(csr.signatureOid).getBytes()), - // parameters - _signatureParametersToAsn1(csr.signatureOid, csr.signatureParameters) - ]), - // signature - asn1$4.create(asn1$4.Class.UNIVERSAL, asn1$4.Type.BITSTRING, false, - String.fromCharCode(0x00) + csr.signature) - ]); -}; - -/** - * Creates a CA store. - * - * @param certs an optional array of certificate objects or PEM-formatted - * certificate strings to add to the CA store. - * - * @return the CA store. - */ -pki$2.createCaStore = function(certs) { - // create CA store - var caStore = { - // stored certificates - certs: {} - }; - - /** - * Gets the certificate that issued the passed certificate or its - * 'parent'. - * - * @param cert the certificate to get the parent for. - * - * @return the parent certificate or null if none was found. - */ - caStore.getIssuer = function(cert) { - var rval = getBySubject(cert.issuer); - - // see if there are multiple matches - /*if(forge.util.isArray(rval)) { - // TODO: resolve multiple matches by checking - // authorityKey/subjectKey/issuerUniqueID/other identifiers, etc. - // FIXME: or alternatively do authority key mapping - // if possible (X.509v1 certs can't work?) - throw new Error('Resolving multiple issuer matches not implemented yet.'); - }*/ - - return rval; - }; - - /** - * Adds a trusted certificate to the store. - * - * @param cert the certificate to add as a trusted certificate (either a - * pki.certificate object or a PEM-formatted certificate). - */ - caStore.addCertificate = function(cert) { - // convert from pem if necessary - if(typeof cert === 'string') { - cert = forge$c.pki.certificateFromPem(cert); - } - - ensureSubjectHasHash(cert.subject); - - if(!caStore.hasCertificate(cert)) { // avoid duplicate certificates in store - if(cert.subject.hash in caStore.certs) { - // subject hash already exists, append to array - var tmp = caStore.certs[cert.subject.hash]; - if(!forge$c.util.isArray(tmp)) { - tmp = [tmp]; - } - tmp.push(cert); - caStore.certs[cert.subject.hash] = tmp; - } else { - caStore.certs[cert.subject.hash] = cert; - } - } - }; - - /** - * Checks to see if the given certificate is in the store. - * - * @param cert the certificate to check (either a pki.certificate or a - * PEM-formatted certificate). - * - * @return true if the certificate is in the store, false if not. - */ - caStore.hasCertificate = function(cert) { - // convert from pem if necessary - if(typeof cert === 'string') { - cert = forge$c.pki.certificateFromPem(cert); - } - - var match = getBySubject(cert.subject); - if(!match) { - return false; - } - if(!forge$c.util.isArray(match)) { - match = [match]; - } - // compare DER-encoding of certificates - var der1 = asn1$4.toDer(pki$2.certificateToAsn1(cert)).getBytes(); - for(var i = 0; i < match.length; ++i) { - var der2 = asn1$4.toDer(pki$2.certificateToAsn1(match[i])).getBytes(); - if(der1 === der2) { - return true; - } - } - return false; - }; - - /** - * Lists all of the certificates kept in the store. - * - * @return an array of all of the pki.certificate objects in the store. - */ - caStore.listAllCertificates = function() { - var certList = []; - - for(var hash in caStore.certs) { - if(caStore.certs.hasOwnProperty(hash)) { - var value = caStore.certs[hash]; - if(!forge$c.util.isArray(value)) { - certList.push(value); - } else { - for(var i = 0; i < value.length; ++i) { - certList.push(value[i]); - } - } - } - } - - return certList; - }; - - /** - * Removes a certificate from the store. - * - * @param cert the certificate to remove (either a pki.certificate or a - * PEM-formatted certificate). - * - * @return the certificate that was removed or null if the certificate - * wasn't in store. - */ - caStore.removeCertificate = function(cert) { - var result; - - // convert from pem if necessary - if(typeof cert === 'string') { - cert = forge$c.pki.certificateFromPem(cert); - } - ensureSubjectHasHash(cert.subject); - if(!caStore.hasCertificate(cert)) { - return null; - } - - var match = getBySubject(cert.subject); - - if(!forge$c.util.isArray(match)) { - result = caStore.certs[cert.subject.hash]; - delete caStore.certs[cert.subject.hash]; - return result; - } - - // compare DER-encoding of certificates - var der1 = asn1$4.toDer(pki$2.certificateToAsn1(cert)).getBytes(); - for(var i = 0; i < match.length; ++i) { - var der2 = asn1$4.toDer(pki$2.certificateToAsn1(match[i])).getBytes(); - if(der1 === der2) { - result = match[i]; - match.splice(i, 1); - } - } - if(match.length === 0) { - delete caStore.certs[cert.subject.hash]; - } - - return result; - }; - - function getBySubject(subject) { - ensureSubjectHasHash(subject); - return caStore.certs[subject.hash] || null; - } - - function ensureSubjectHasHash(subject) { - // produce subject hash if it doesn't exist - if(!subject.hash) { - var md = forge$c.md.sha1.create(); - subject.attributes = pki$2.RDNAttributesAsArray(_dnToAsn1(subject), md); - subject.hash = md.digest().toHex(); - } - } - - // auto-add passed in certs - if(certs) { - // parse PEM-formatted certificates as necessary - for(var i = 0; i < certs.length; ++i) { - var cert = certs[i]; - caStore.addCertificate(cert); - } - } - - return caStore; -}; - -/** - * Certificate verification errors, based on TLS. - */ -pki$2.certificateError = { - bad_certificate: 'forge.pki.BadCertificate', - unsupported_certificate: 'forge.pki.UnsupportedCertificate', - certificate_revoked: 'forge.pki.CertificateRevoked', - certificate_expired: 'forge.pki.CertificateExpired', - certificate_unknown: 'forge.pki.CertificateUnknown', - unknown_ca: 'forge.pki.UnknownCertificateAuthority' -}; - -/** - * Verifies a certificate chain against the given Certificate Authority store - * with an optional custom verify callback. - * - * @param caStore a certificate store to verify against. - * @param chain the certificate chain to verify, with the root or highest - * authority at the end (an array of certificates). - * @param options a callback to be called for every certificate in the chain or - * an object with: - * verify a callback to be called for every certificate in the - * chain - * validityCheckDate the date against which the certificate - * validity period should be checked. Pass null to not check - * the validity period. By default, the current date is used. - * - * The verify callback has the following signature: - * - * verified - Set to true if certificate was verified, otherwise the - * pki.certificateError for why the certificate failed. - * depth - The current index in the chain, where 0 is the end point's cert. - * certs - The certificate chain, *NOTE* an empty chain indicates an anonymous - * end point. - * - * The function returns true on success and on failure either the appropriate - * pki.certificateError or an object with 'error' set to the appropriate - * pki.certificateError and 'message' set to a custom error message. - * - * @return true if successful, error thrown if not. - */ -pki$2.verifyCertificateChain = function(caStore, chain, options) { - /* From: RFC3280 - Internet X.509 Public Key Infrastructure Certificate - Section 6: Certification Path Validation - See inline parentheticals related to this particular implementation. - - The primary goal of path validation is to verify the binding between - a subject distinguished name or a subject alternative name and subject - public key, as represented in the end entity certificate, based on the - public key of the trust anchor. This requires obtaining a sequence of - certificates that support that binding. That sequence should be provided - in the passed 'chain'. The trust anchor should be in the given CA - store. The 'end entity' certificate is the certificate provided by the - end point (typically a server) and is the first in the chain. - - To meet this goal, the path validation process verifies, among other - things, that a prospective certification path (a sequence of n - certificates or a 'chain') satisfies the following conditions: - - (a) for all x in {1, ..., n-1}, the subject of certificate x is - the issuer of certificate x+1; - - (b) certificate 1 is issued by the trust anchor; - - (c) certificate n is the certificate to be validated; and - - (d) for all x in {1, ..., n}, the certificate was valid at the - time in question. - - Note that here 'n' is index 0 in the chain and 1 is the last certificate - in the chain and it must be signed by a certificate in the connection's - CA store. - - The path validation process also determines the set of certificate - policies that are valid for this path, based on the certificate policies - extension, policy mapping extension, policy constraints extension, and - inhibit any-policy extension. - - Note: Policy mapping extension not supported (Not Required). - - Note: If the certificate has an unsupported critical extension, then it - must be rejected. - - Note: A certificate is self-issued if the DNs that appear in the subject - and issuer fields are identical and are not empty. - - The path validation algorithm assumes the following seven inputs are - provided to the path processing logic. What this specific implementation - will use is provided parenthetically: - - (a) a prospective certification path of length n (the 'chain') - (b) the current date/time: ('now'). - (c) user-initial-policy-set: A set of certificate policy identifiers - naming the policies that are acceptable to the certificate user. - The user-initial-policy-set contains the special value any-policy - if the user is not concerned about certificate policy - (Not implemented. Any policy is accepted). - (d) trust anchor information, describing a CA that serves as a trust - anchor for the certification path. The trust anchor information - includes: - - (1) the trusted issuer name, - (2) the trusted public key algorithm, - (3) the trusted public key, and - (4) optionally, the trusted public key parameters associated - with the public key. - - (Trust anchors are provided via certificates in the CA store). - - The trust anchor information may be provided to the path processing - procedure in the form of a self-signed certificate. The trusted anchor - information is trusted because it was delivered to the path processing - procedure by some trustworthy out-of-band procedure. If the trusted - public key algorithm requires parameters, then the parameters are - provided along with the trusted public key (No parameters used in this - implementation). - - (e) initial-policy-mapping-inhibit, which indicates if policy mapping is - allowed in the certification path. - (Not implemented, no policy checking) - - (f) initial-explicit-policy, which indicates if the path must be valid - for at least one of the certificate policies in the user-initial- - policy-set. - (Not implemented, no policy checking) - - (g) initial-any-policy-inhibit, which indicates whether the - anyPolicy OID should be processed if it is included in a - certificate. - (Not implemented, so any policy is valid provided that it is - not marked as critical) */ - - /* Basic Path Processing: - - For each certificate in the 'chain', the following is checked: - - 1. The certificate validity period includes the current time. - 2. The certificate was signed by its parent (where the parent is either - the next in the chain or from the CA store). Allow processing to - continue to the next step if no parent is found but the certificate is - in the CA store. - 3. TODO: The certificate has not been revoked. - 4. The certificate issuer name matches the parent's subject name. - 5. TODO: If the certificate is self-issued and not the final certificate - in the chain, skip this step, otherwise verify that the subject name - is within one of the permitted subtrees of X.500 distinguished names - and that each of the alternative names in the subjectAltName extension - (critical or non-critical) is within one of the permitted subtrees for - that name type. - 6. TODO: If the certificate is self-issued and not the final certificate - in the chain, skip this step, otherwise verify that the subject name - is not within one of the excluded subtrees for X.500 distinguished - names and none of the subjectAltName extension names are excluded for - that name type. - 7. The other steps in the algorithm for basic path processing involve - handling the policy extension which is not presently supported in this - implementation. Instead, if a critical policy extension is found, the - certificate is rejected as not supported. - 8. If the certificate is not the first or if its the only certificate in - the chain (having no parent from the CA store or is self-signed) and it - has a critical key usage extension, verify that the keyCertSign bit is - set. If the key usage extension exists, verify that the basic - constraints extension exists. If the basic constraints extension exists, - verify that the cA flag is set. If pathLenConstraint is set, ensure that - the number of certificates that precede in the chain (come earlier - in the chain as implemented below), excluding the very first in the - chain (typically the end-entity one), isn't greater than the - pathLenConstraint. This constraint limits the number of intermediate - CAs that may appear below a CA before only end-entity certificates - may be issued. */ - - // if a verify callback is passed as the third parameter, package it within - // the options object. This is to support a legacy function signature that - // expected the verify callback as the third parameter. - if(typeof options === 'function') { - options = {verify: options}; - } - options = options || {}; - - // copy cert chain references to another array to protect against changes - // in verify callback - chain = chain.slice(0); - var certs = chain.slice(0); - - var validityCheckDate = options.validityCheckDate; - // if no validityCheckDate is specified, default to the current date. Make - // sure to maintain the value null because it indicates that the validity - // period should not be checked. - if(typeof validityCheckDate === 'undefined') { - validityCheckDate = new Date(); - } - - // verify each cert in the chain using its parent, where the parent - // is either the next in the chain or from the CA store - var first = true; - var error = null; - var depth = 0; - do { - var cert = chain.shift(); - var parent = null; - var selfSigned = false; - - if(validityCheckDate) { - // 1. check valid time - if(validityCheckDate < cert.validity.notBefore || - validityCheckDate > cert.validity.notAfter) { - error = { - message: 'Certificate is not valid yet or has expired.', - error: pki$2.certificateError.certificate_expired, - notBefore: cert.validity.notBefore, - notAfter: cert.validity.notAfter, - // TODO: we might want to reconsider renaming 'now' to - // 'validityCheckDate' should this API be changed in the future. - now: validityCheckDate - }; - } - } - - // 2. verify with parent from chain or CA store - if(error === null) { - parent = chain[0] || caStore.getIssuer(cert); - if(parent === null) { - // check for self-signed cert - if(cert.isIssuer(cert)) { - selfSigned = true; - parent = cert; - } - } - - if(parent) { - // FIXME: current CA store implementation might have multiple - // certificates where the issuer can't be determined from the - // certificate (happens rarely with, eg: old certificates) so normalize - // by always putting parents into an array - // TODO: there's may be an extreme degenerate case currently uncovered - // where an old intermediate certificate seems to have a matching parent - // but none of the parents actually verify ... but the intermediate - // is in the CA and it should pass this check; needs investigation - var parents = parent; - if(!forge$c.util.isArray(parents)) { - parents = [parents]; - } - - // try to verify with each possible parent (typically only one) - var verified = false; - while(!verified && parents.length > 0) { - parent = parents.shift(); - try { - verified = parent.verify(cert); - } catch(ex) { - // failure to verify, don't care why, try next one - } - } - - if(!verified) { - error = { - message: 'Certificate signature is invalid.', - error: pki$2.certificateError.bad_certificate - }; - } - } - - if(error === null && (!parent || selfSigned) && - !caStore.hasCertificate(cert)) { - // no parent issuer and certificate itself is not trusted - error = { - message: 'Certificate is not trusted.', - error: pki$2.certificateError.unknown_ca - }; - } - } - - // TODO: 3. check revoked - - // 4. check for matching issuer/subject - if(error === null && parent && !cert.isIssuer(parent)) { - // parent is not issuer - error = { - message: 'Certificate issuer is invalid.', - error: pki$2.certificateError.bad_certificate - }; - } - - // 5. TODO: check names with permitted names tree - - // 6. TODO: check names against excluded names tree - - // 7. check for unsupported critical extensions - if(error === null) { - // supported extensions - var se = { - keyUsage: true, - basicConstraints: true - }; - for(var i = 0; error === null && i < cert.extensions.length; ++i) { - var ext = cert.extensions[i]; - if(ext.critical && !(ext.name in se)) { - error = { - message: - 'Certificate has an unsupported critical extension.', - error: pki$2.certificateError.unsupported_certificate - }; - } - } - } - - // 8. check for CA if cert is not first or is the only certificate - // remaining in chain with no parent or is self-signed - if(error === null && - (!first || (chain.length === 0 && (!parent || selfSigned)))) { - // first check keyUsage extension and then basic constraints - var bcExt = cert.getExtension('basicConstraints'); - var keyUsageExt = cert.getExtension('keyUsage'); - if(keyUsageExt !== null) { - // keyCertSign must be true and there must be a basic - // constraints extension - if(!keyUsageExt.keyCertSign || bcExt === null) { - // bad certificate - error = { - message: - 'Certificate keyUsage or basicConstraints conflict ' + - 'or indicate that the certificate is not a CA. ' + - 'If the certificate is the only one in the chain or ' + - 'isn\'t the first then the certificate must be a ' + - 'valid CA.', - error: pki$2.certificateError.bad_certificate - }; - } - } - // basic constraints cA flag must be set - if(error === null && bcExt !== null && !bcExt.cA) { - // bad certificate - error = { - message: - 'Certificate basicConstraints indicates the certificate ' + - 'is not a CA.', - error: pki$2.certificateError.bad_certificate - }; - } - // if error is not null and keyUsage is available, then we know it - // has keyCertSign and there is a basic constraints extension too, - // which means we can check pathLenConstraint (if it exists) - if(error === null && keyUsageExt !== null && - 'pathLenConstraint' in bcExt) { - // pathLen is the maximum # of intermediate CA certs that can be - // found between the current certificate and the end-entity (depth 0) - // certificate; this number does not include the end-entity (depth 0, - // last in the chain) even if it happens to be a CA certificate itself - var pathLen = depth - 1; - if(pathLen > bcExt.pathLenConstraint) { - // pathLenConstraint violated, bad certificate - error = { - message: - 'Certificate basicConstraints pathLenConstraint violated.', - error: pki$2.certificateError.bad_certificate - }; - } - } - } - - // call application callback - var vfd = (error === null) ? true : error.error; - var ret = options.verify ? options.verify(vfd, depth, certs) : vfd; - if(ret === true) { - // clear any set error - error = null; - } else { - // if passed basic tests, set default message and alert - if(vfd === true) { - error = { - message: 'The application rejected the certificate.', - error: pki$2.certificateError.bad_certificate - }; - } - - // check for custom error info - if(ret || ret === 0) { - // set custom message and error - if(typeof ret === 'object' && !forge$c.util.isArray(ret)) { - if(ret.message) { - error.message = ret.message; - } - if(ret.error) { - error.error = ret.error; - } - } else if(typeof ret === 'string') { - // set custom error - error.error = ret; - } - } - - // throw error - throw error; - } - - // no longer first cert in chain - first = false; - ++depth; - } while(chain.length > 0); - - return true; -}; - -/** - * Javascript implementation of PKCS#12. - * - * @author Dave Longley - * @author Stefan Siegl - * - * Copyright (c) 2010-2014 Digital Bazaar, Inc. - * Copyright (c) 2012 Stefan Siegl - * - * The ASN.1 representation of PKCS#12 is as follows - * (see ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12-tc1.pdf for details) - * - * PFX ::= SEQUENCE { - * version INTEGER {v3(3)}(v3,...), - * authSafe ContentInfo, - * macData MacData OPTIONAL - * } - * - * MacData ::= SEQUENCE { - * mac DigestInfo, - * macSalt OCTET STRING, - * iterations INTEGER DEFAULT 1 - * } - * Note: The iterations default is for historical reasons and its use is - * deprecated. A higher value, like 1024, is recommended. - * - * DigestInfo is defined in PKCS#7 as follows: - * - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest - * } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * The AlgorithmIdentifier contains an Object Identifier (OID) and parameters - * for the algorithm, if any. In the case of SHA1 there is none. - * - * AlgorithmIdentifer ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL - * } - * - * Digest ::= OCTET STRING - * - * - * ContentInfo ::= SEQUENCE { - * contentType ContentType, - * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL - * } - * - * ContentType ::= OBJECT IDENTIFIER - * - * AuthenticatedSafe ::= SEQUENCE OF ContentInfo - * -- Data if unencrypted - * -- EncryptedData if password-encrypted - * -- EnvelopedData if public key-encrypted - * - * - * SafeContents ::= SEQUENCE OF SafeBag - * - * SafeBag ::= SEQUENCE { - * bagId BAG-TYPE.&id ({PKCS12BagSet}) - * bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}), - * bagAttributes SET OF PKCS12Attribute OPTIONAL - * } - * - * PKCS12Attribute ::= SEQUENCE { - * attrId ATTRIBUTE.&id ({PKCS12AttrSet}), - * attrValues SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId}) - * } -- This type is compatible with the X.500 type 'Attribute' - * - * PKCS12AttrSet ATTRIBUTE ::= { - * friendlyName | -- from PKCS #9 - * localKeyId, -- from PKCS #9 - * ... -- Other attributes are allowed - * } - * - * CertBag ::= SEQUENCE { - * certId BAG-TYPE.&id ({CertTypes}), - * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) - * } - * - * x509Certificate BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1}} - * -- DER-encoded X.509 certificate stored in OCTET STRING - * - * sdsiCertificate BAG-TYPE ::= {IA5String IDENTIFIED BY {certTypes 2}} - * -- Base64-encoded SDSI certificate stored in IA5String - * - * CertTypes BAG-TYPE ::= { - * x509Certificate | - * sdsiCertificate, - * ... -- For future extensions - * } - */ - -var forge$b = forge$D; - - - - - - - - - - - -// shortcut for asn.1 & PKI API -var asn1$3 = forge$b.asn1; -var pki$1 = forge$b.pki; - -// shortcut for PKCS#12 API -var p12 = forge$b.pkcs12 = forge$b.pkcs12 || {}; - -var contentInfoValidator = { - name: 'ContentInfo', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SEQUENCE, // a ContentInfo - constructed: true, - value: [{ - name: 'ContentInfo.contentType', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.OID, - constructed: false, - capture: 'contentType' - }, { - name: 'ContentInfo.content', - tagClass: asn1$3.Class.CONTEXT_SPECIFIC, - constructed: true, - captureAsn1: 'content' - }] -}; - -var pfxValidator = { - name: 'PFX', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'PFX.version', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.INTEGER, - constructed: false, - capture: 'version' - }, - contentInfoValidator, { - name: 'PFX.macData', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SEQUENCE, - constructed: true, - optional: true, - captureAsn1: 'mac', - value: [{ - name: 'PFX.macData.mac', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SEQUENCE, // DigestInfo - constructed: true, - value: [{ - name: 'PFX.macData.mac.digestAlgorithm', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SEQUENCE, // DigestAlgorithmIdentifier - constructed: true, - value: [{ - name: 'PFX.macData.mac.digestAlgorithm.algorithm', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.OID, - constructed: false, - capture: 'macAlgorithm' - }, { - name: 'PFX.macData.mac.digestAlgorithm.parameters', - tagClass: asn1$3.Class.UNIVERSAL, - captureAsn1: 'macAlgorithmParameters' - }] - }, { - name: 'PFX.macData.mac.digest', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.OCTETSTRING, - constructed: false, - capture: 'macDigest' - }] - }, { - name: 'PFX.macData.macSalt', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.OCTETSTRING, - constructed: false, - capture: 'macSalt' - }, { - name: 'PFX.macData.iterations', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.INTEGER, - constructed: false, - optional: true, - capture: 'macIterations' - }] - }] -}; - -var safeBagValidator = { - name: 'SafeBag', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'SafeBag.bagId', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.OID, - constructed: false, - capture: 'bagId' - }, { - name: 'SafeBag.bagValue', - tagClass: asn1$3.Class.CONTEXT_SPECIFIC, - constructed: true, - captureAsn1: 'bagValue' - }, { - name: 'SafeBag.bagAttributes', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SET, - constructed: true, - optional: true, - capture: 'bagAttributes' - }] -}; - -var attributeValidator = { - name: 'Attribute', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'Attribute.attrId', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.OID, - constructed: false, - capture: 'oid' - }, { - name: 'Attribute.attrValues', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SET, - constructed: true, - capture: 'values' - }] -}; - -var certBagValidator = { - name: 'CertBag', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'CertBag.certId', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Type.OID, - constructed: false, - capture: 'certId' - }, { - name: 'CertBag.certValue', - tagClass: asn1$3.Class.CONTEXT_SPECIFIC, - constructed: true, - /* So far we only support X.509 certificates (which are wrapped in - an OCTET STRING, hence hard code that here). */ - value: [{ - name: 'CertBag.certValue[0]', - tagClass: asn1$3.Class.UNIVERSAL, - type: asn1$3.Class.OCTETSTRING, - constructed: false, - capture: 'cert' - }] - }] -}; - -/** - * Search SafeContents structure for bags with matching attributes. - * - * The search can optionally be narrowed by a certain bag type. - * - * @param safeContents the SafeContents structure to search in. - * @param attrName the name of the attribute to compare against. - * @param attrValue the attribute value to search for. - * @param [bagType] bag type to narrow search by. - * - * @return an array of matching bags. - */ -function _getBagsByAttribute(safeContents, attrName, attrValue, bagType) { - var result = []; - - for(var i = 0; i < safeContents.length; i++) { - for(var j = 0; j < safeContents[i].safeBags.length; j++) { - var bag = safeContents[i].safeBags[j]; - if(bagType !== undefined && bag.type !== bagType) { - continue; - } - // only filter by bag type, no attribute specified - if(attrName === null) { - result.push(bag); - continue; - } - if(bag.attributes[attrName] !== undefined && - bag.attributes[attrName].indexOf(attrValue) >= 0) { - result.push(bag); - } - } - } - - return result; -} - -/** - * Converts a PKCS#12 PFX in ASN.1 notation into a PFX object. - * - * @param obj The PKCS#12 PFX in ASN.1 notation. - * @param strict true to use strict DER decoding, false not to (default: true). - * @param {String} password Password to decrypt with (optional). - * - * @return PKCS#12 PFX object. - */ -p12.pkcs12FromAsn1 = function(obj, strict, password) { - // handle args - if(typeof strict === 'string') { - password = strict; - strict = true; - } else if(strict === undefined) { - strict = true; - } - - // validate PFX and capture data - var capture = {}; - var errors = []; - if(!asn1$3.validate(obj, pfxValidator, capture, errors)) { - var error = new Error('Cannot read PKCS#12 PFX. ' + - 'ASN.1 object is not an PKCS#12 PFX.'); - error.errors = error; - throw error; - } - - var pfx = { - version: capture.version.charCodeAt(0), - safeContents: [], - - /** - * Gets bags with matching attributes. - * - * @param filter the attributes to filter by: - * [localKeyId] the localKeyId to search for. - * [localKeyIdHex] the localKeyId in hex to search for. - * [friendlyName] the friendly name to search for. - * [bagType] bag type to narrow each attribute search by. - * - * @return a map of attribute type to an array of matching bags or, if no - * attribute was given but a bag type, the map key will be the - * bag type. - */ - getBags: function(filter) { - var rval = {}; - - var localKeyId; - if('localKeyId' in filter) { - localKeyId = filter.localKeyId; - } else if('localKeyIdHex' in filter) { - localKeyId = forge$b.util.hexToBytes(filter.localKeyIdHex); - } - - // filter on bagType only - if(localKeyId === undefined && !('friendlyName' in filter) && - 'bagType' in filter) { - rval[filter.bagType] = _getBagsByAttribute( - pfx.safeContents, null, null, filter.bagType); - } - - if(localKeyId !== undefined) { - rval.localKeyId = _getBagsByAttribute( - pfx.safeContents, 'localKeyId', - localKeyId, filter.bagType); - } - if('friendlyName' in filter) { - rval.friendlyName = _getBagsByAttribute( - pfx.safeContents, 'friendlyName', - filter.friendlyName, filter.bagType); - } - - return rval; - }, - - /** - * DEPRECATED: use getBags() instead. - * - * Get bags with matching friendlyName attribute. - * - * @param friendlyName the friendly name to search for. - * @param [bagType] bag type to narrow search by. - * - * @return an array of bags with matching friendlyName attribute. - */ - getBagsByFriendlyName: function(friendlyName, bagType) { - return _getBagsByAttribute( - pfx.safeContents, 'friendlyName', friendlyName, bagType); - }, - - /** - * DEPRECATED: use getBags() instead. - * - * Get bags with matching localKeyId attribute. - * - * @param localKeyId the localKeyId to search for. - * @param [bagType] bag type to narrow search by. - * - * @return an array of bags with matching localKeyId attribute. - */ - getBagsByLocalKeyId: function(localKeyId, bagType) { - return _getBagsByAttribute( - pfx.safeContents, 'localKeyId', localKeyId, bagType); - } - }; - - if(capture.version.charCodeAt(0) !== 3) { - var error = new Error('PKCS#12 PFX of version other than 3 not supported.'); - error.version = capture.version.charCodeAt(0); - throw error; - } - - if(asn1$3.derToOid(capture.contentType) !== pki$1.oids.data) { - var error = new Error('Only PKCS#12 PFX in password integrity mode supported.'); - error.oid = asn1$3.derToOid(capture.contentType); - throw error; - } - - var data = capture.content.value[0]; - if(data.tagClass !== asn1$3.Class.UNIVERSAL || - data.type !== asn1$3.Type.OCTETSTRING) { - throw new Error('PKCS#12 authSafe content data is not an OCTET STRING.'); - } - data = _decodePkcs7Data(data); - - // check for MAC - if(capture.mac) { - var md = null; - var macKeyBytes = 0; - var macAlgorithm = asn1$3.derToOid(capture.macAlgorithm); - switch(macAlgorithm) { - case pki$1.oids.sha1: - md = forge$b.md.sha1.create(); - macKeyBytes = 20; - break; - case pki$1.oids.sha256: - md = forge$b.md.sha256.create(); - macKeyBytes = 32; - break; - case pki$1.oids.sha384: - md = forge$b.md.sha384.create(); - macKeyBytes = 48; - break; - case pki$1.oids.sha512: - md = forge$b.md.sha512.create(); - macKeyBytes = 64; - break; - case pki$1.oids.md5: - md = forge$b.md.md5.create(); - macKeyBytes = 16; - break; - } - if(md === null) { - throw new Error('PKCS#12 uses unsupported MAC algorithm: ' + macAlgorithm); - } - - // verify MAC (iterations default to 1) - var macSalt = new forge$b.util.ByteBuffer(capture.macSalt); - var macIterations = (('macIterations' in capture) ? - parseInt(forge$b.util.bytesToHex(capture.macIterations), 16) : 1); - var macKey = p12.generateKey( - password, macSalt, 3, macIterations, macKeyBytes, md); - var mac = forge$b.hmac.create(); - mac.start(md, macKey); - mac.update(data.value); - var macValue = mac.getMac(); - if(macValue.getBytes() !== capture.macDigest) { - throw new Error('PKCS#12 MAC could not be verified. Invalid password?'); - } - } - - _decodeAuthenticatedSafe(pfx, data.value, strict, password); - return pfx; -}; - -/** - * Decodes PKCS#7 Data. PKCS#7 (RFC 2315) defines "Data" as an OCTET STRING, - * but it is sometimes an OCTET STRING that is composed/constructed of chunks, - * each its own OCTET STRING. This is BER-encoding vs. DER-encoding. This - * function transforms this corner-case into the usual simple, - * non-composed/constructed OCTET STRING. - * - * This function may be moved to ASN.1 at some point to better deal with - * more BER-encoding issues, should they arise. - * - * @param data the ASN.1 Data object to transform. - */ -function _decodePkcs7Data(data) { - // handle special case of "chunked" data content: an octet string composed - // of other octet strings - if(data.composed || data.constructed) { - var value = forge$b.util.createBuffer(); - for(var i = 0; i < data.value.length; ++i) { - value.putBytes(data.value[i].value); - } - data.composed = data.constructed = false; - data.value = value.getBytes(); - } - return data; -} - -/** - * Decode PKCS#12 AuthenticatedSafe (BER encoded) into PFX object. - * - * The AuthenticatedSafe is a BER-encoded SEQUENCE OF ContentInfo. - * - * @param pfx The PKCS#12 PFX object to fill. - * @param {String} authSafe BER-encoded AuthenticatedSafe. - * @param strict true to use strict DER decoding, false not to. - * @param {String} password Password to decrypt with (optional). - */ -function _decodeAuthenticatedSafe(pfx, authSafe, strict, password) { - authSafe = asn1$3.fromDer(authSafe, strict); /* actually it's BER encoded */ - - if(authSafe.tagClass !== asn1$3.Class.UNIVERSAL || - authSafe.type !== asn1$3.Type.SEQUENCE || - authSafe.constructed !== true) { - throw new Error('PKCS#12 AuthenticatedSafe expected to be a ' + - 'SEQUENCE OF ContentInfo'); - } - - for(var i = 0; i < authSafe.value.length; i++) { - var contentInfo = authSafe.value[i]; - - // validate contentInfo and capture data - var capture = {}; - var errors = []; - if(!asn1$3.validate(contentInfo, contentInfoValidator, capture, errors)) { - var error = new Error('Cannot read ContentInfo.'); - error.errors = errors; - throw error; - } - - var obj = { - encrypted: false - }; - var safeContents = null; - var data = capture.content.value[0]; - switch(asn1$3.derToOid(capture.contentType)) { - case pki$1.oids.data: - if(data.tagClass !== asn1$3.Class.UNIVERSAL || - data.type !== asn1$3.Type.OCTETSTRING) { - throw new Error('PKCS#12 SafeContents Data is not an OCTET STRING.'); - } - safeContents = _decodePkcs7Data(data).value; - break; - case pki$1.oids.encryptedData: - safeContents = _decryptSafeContents(data, password); - obj.encrypted = true; - break; - default: - var error = new Error('Unsupported PKCS#12 contentType.'); - error.contentType = asn1$3.derToOid(capture.contentType); - throw error; - } - - obj.safeBags = _decodeSafeContents(safeContents, strict, password); - pfx.safeContents.push(obj); - } -} - -/** - * Decrypt PKCS#7 EncryptedData structure. - * - * @param data ASN.1 encoded EncryptedContentInfo object. - * @param password The user-provided password. - * - * @return The decrypted SafeContents (ASN.1 object). - */ -function _decryptSafeContents(data, password) { - var capture = {}; - var errors = []; - if(!asn1$3.validate( - data, forge$b.pkcs7.asn1.encryptedDataValidator, capture, errors)) { - var error = new Error('Cannot read EncryptedContentInfo.'); - error.errors = errors; - throw error; - } - - var oid = asn1$3.derToOid(capture.contentType); - if(oid !== pki$1.oids.data) { - var error = new Error( - 'PKCS#12 EncryptedContentInfo ContentType is not Data.'); - error.oid = oid; - throw error; - } - - // get cipher - oid = asn1$3.derToOid(capture.encAlgorithm); - var cipher = pki$1.pbe.getCipher(oid, capture.encParameter, password); - - // get encrypted data - var encryptedContentAsn1 = _decodePkcs7Data(capture.encryptedContentAsn1); - var encrypted = forge$b.util.createBuffer(encryptedContentAsn1.value); - - cipher.update(encrypted); - if(!cipher.finish()) { - throw new Error('Failed to decrypt PKCS#12 SafeContents.'); - } - - return cipher.output.getBytes(); -} - -/** - * Decode PKCS#12 SafeContents (BER-encoded) into array of Bag objects. - * - * The safeContents is a BER-encoded SEQUENCE OF SafeBag. - * - * @param {String} safeContents BER-encoded safeContents. - * @param strict true to use strict DER decoding, false not to. - * @param {String} password Password to decrypt with (optional). - * - * @return {Array} Array of Bag objects. - */ -function _decodeSafeContents(safeContents, strict, password) { - // if strict and no safe contents, return empty safes - if(!strict && safeContents.length === 0) { - return []; - } - - // actually it's BER-encoded - safeContents = asn1$3.fromDer(safeContents, strict); - - if(safeContents.tagClass !== asn1$3.Class.UNIVERSAL || - safeContents.type !== asn1$3.Type.SEQUENCE || - safeContents.constructed !== true) { - throw new Error( - 'PKCS#12 SafeContents expected to be a SEQUENCE OF SafeBag.'); - } - - var res = []; - for(var i = 0; i < safeContents.value.length; i++) { - var safeBag = safeContents.value[i]; - - // validate SafeBag and capture data - var capture = {}; - var errors = []; - if(!asn1$3.validate(safeBag, safeBagValidator, capture, errors)) { - var error = new Error('Cannot read SafeBag.'); - error.errors = errors; - throw error; - } - - /* Create bag object and push to result array. */ - var bag = { - type: asn1$3.derToOid(capture.bagId), - attributes: _decodeBagAttributes(capture.bagAttributes) - }; - res.push(bag); - - var validator, decoder; - var bagAsn1 = capture.bagValue.value[0]; - switch(bag.type) { - case pki$1.oids.pkcs8ShroudedKeyBag: - /* bagAsn1 has a EncryptedPrivateKeyInfo, which we need to decrypt. - Afterwards we can handle it like a keyBag, - which is a PrivateKeyInfo. */ - bagAsn1 = pki$1.decryptPrivateKeyInfo(bagAsn1, password); - if(bagAsn1 === null) { - throw new Error( - 'Unable to decrypt PKCS#8 ShroudedKeyBag, wrong password?'); - } - - /* fall through */ - case pki$1.oids.keyBag: - /* A PKCS#12 keyBag is a simple PrivateKeyInfo as understood by our - PKI module, hence we don't have to do validation/capturing here, - just pass what we already got. */ - try { - bag.key = pki$1.privateKeyFromAsn1(bagAsn1); - } catch(e) { - // ignore unknown key type, pass asn1 value - bag.key = null; - bag.asn1 = bagAsn1; - } - continue; /* Nothing more to do. */ - - case pki$1.oids.certBag: - /* A PKCS#12 certBag can wrap both X.509 and sdsi certificates. - Therefore put the SafeBag content through another validator to - capture the fields. Afterwards check & store the results. */ - validator = certBagValidator; - decoder = function() { - if(asn1$3.derToOid(capture.certId) !== pki$1.oids.x509Certificate) { - var error = new Error( - 'Unsupported certificate type, only X.509 supported.'); - error.oid = asn1$3.derToOid(capture.certId); - throw error; - } - - // true=produce cert hash - var certAsn1 = asn1$3.fromDer(capture.cert, strict); - try { - bag.cert = pki$1.certificateFromAsn1(certAsn1, true); - } catch(e) { - // ignore unknown cert type, pass asn1 value - bag.cert = null; - bag.asn1 = certAsn1; - } - }; - break; - - default: - var error = new Error('Unsupported PKCS#12 SafeBag type.'); - error.oid = bag.type; - throw error; - } - - /* Validate SafeBag value (i.e. CertBag, etc.) and capture data if needed. */ - if(validator !== undefined && - !asn1$3.validate(bagAsn1, validator, capture, errors)) { - var error = new Error('Cannot read PKCS#12 ' + validator.name); - error.errors = errors; - throw error; - } - - /* Call decoder function from above to store the results. */ - decoder(); - } - - return res; -} - -/** - * Decode PKCS#12 SET OF PKCS12Attribute into JavaScript object. - * - * @param attributes SET OF PKCS12Attribute (ASN.1 object). - * - * @return the decoded attributes. - */ -function _decodeBagAttributes(attributes) { - var decodedAttrs = {}; - - if(attributes !== undefined) { - for(var i = 0; i < attributes.length; ++i) { - var capture = {}; - var errors = []; - if(!asn1$3.validate(attributes[i], attributeValidator, capture, errors)) { - var error = new Error('Cannot read PKCS#12 BagAttribute.'); - error.errors = errors; - throw error; - } - - var oid = asn1$3.derToOid(capture.oid); - if(pki$1.oids[oid] === undefined) { - // unsupported attribute type, ignore. - continue; - } - - decodedAttrs[pki$1.oids[oid]] = []; - for(var j = 0; j < capture.values.length; ++j) { - decodedAttrs[pki$1.oids[oid]].push(capture.values[j].value); - } - } - } - - return decodedAttrs; -} - -/** - * Wraps a private key and certificate in a PKCS#12 PFX wrapper. If a - * password is provided then the private key will be encrypted. - * - * An entire certificate chain may also be included. To do this, pass - * an array for the "cert" parameter where the first certificate is - * the one that is paired with the private key and each subsequent one - * verifies the previous one. The certificates may be in PEM format or - * have been already parsed by Forge. - * - * @todo implement password-based-encryption for the whole package - * - * @param key the private key. - * @param cert the certificate (may be an array of certificates in order - * to specify a certificate chain). - * @param password the password to use, null for none. - * @param options: - * algorithm the encryption algorithm to use - * ('aes128', 'aes192', 'aes256', '3des'), defaults to 'aes128'. - * count the iteration count to use. - * saltSize the salt size to use. - * useMac true to include a MAC, false not to, defaults to true. - * localKeyId the local key ID to use, in hex. - * friendlyName the friendly name to use. - * generateLocalKeyId true to generate a random local key ID, - * false not to, defaults to true. - * - * @return the PKCS#12 PFX ASN.1 object. - */ -p12.toPkcs12Asn1 = function(key, cert, password, options) { - // set default options - options = options || {}; - options.saltSize = options.saltSize || 8; - options.count = options.count || 2048; - options.algorithm = options.algorithm || options.encAlgorithm || 'aes128'; - if(!('useMac' in options)) { - options.useMac = true; - } - if(!('localKeyId' in options)) { - options.localKeyId = null; - } - if(!('generateLocalKeyId' in options)) { - options.generateLocalKeyId = true; - } - - var localKeyId = options.localKeyId; - var bagAttrs; - if(localKeyId !== null) { - localKeyId = forge$b.util.hexToBytes(localKeyId); - } else if(options.generateLocalKeyId) { - // use SHA-1 of paired cert, if available - if(cert) { - var pairedCert = forge$b.util.isArray(cert) ? cert[0] : cert; - if(typeof pairedCert === 'string') { - pairedCert = pki$1.certificateFromPem(pairedCert); - } - var sha1 = forge$b.md.sha1.create(); - sha1.update(asn1$3.toDer(pki$1.certificateToAsn1(pairedCert)).getBytes()); - localKeyId = sha1.digest().getBytes(); - } else { - // FIXME: consider using SHA-1 of public key (which can be generated - // from private key components), see: cert.generateSubjectKeyIdentifier - // generate random bytes - localKeyId = forge$b.random.getBytes(20); - } - } - - var attrs = []; - if(localKeyId !== null) { - attrs.push( - // localKeyID - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // attrId - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - asn1$3.oidToDer(pki$1.oids.localKeyId).getBytes()), - // attrValues - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SET, true, [ - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OCTETSTRING, false, - localKeyId) - ]) - ])); - } - if('friendlyName' in options) { - attrs.push( - // friendlyName - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // attrId - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - asn1$3.oidToDer(pki$1.oids.friendlyName).getBytes()), - // attrValues - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SET, true, [ - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.BMPSTRING, false, - options.friendlyName) - ]) - ])); - } - - if(attrs.length > 0) { - bagAttrs = asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SET, true, attrs); - } - - // collect contents for AuthenticatedSafe - var contents = []; - - // create safe bag(s) for certificate chain - var chain = []; - if(cert !== null) { - if(forge$b.util.isArray(cert)) { - chain = cert; - } else { - chain = [cert]; - } - } - - var certSafeBags = []; - for(var i = 0; i < chain.length; ++i) { - // convert cert from PEM as necessary - cert = chain[i]; - if(typeof cert === 'string') { - cert = pki$1.certificateFromPem(cert); - } - - // SafeBag - var certBagAttrs = (i === 0) ? bagAttrs : undefined; - var certAsn1 = pki$1.certificateToAsn1(cert); - var certSafeBag = - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // bagId - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - asn1$3.oidToDer(pki$1.oids.certBag).getBytes()), - // bagValue - asn1$3.create(asn1$3.Class.CONTEXT_SPECIFIC, 0, true, [ - // CertBag - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // certId - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - asn1$3.oidToDer(pki$1.oids.x509Certificate).getBytes()), - // certValue (x509Certificate) - asn1$3.create(asn1$3.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1$3.create( - asn1$3.Class.UNIVERSAL, asn1$3.Type.OCTETSTRING, false, - asn1$3.toDer(certAsn1).getBytes()) - ])])]), - // bagAttributes (OPTIONAL) - certBagAttrs - ]); - certSafeBags.push(certSafeBag); - } - - if(certSafeBags.length > 0) { - // SafeContents - var certSafeContents = asn1$3.create( - asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, certSafeBags); - - // ContentInfo - var certCI = - // PKCS#7 ContentInfo - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // contentType - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - // OID for the content type is 'data' - asn1$3.oidToDer(pki$1.oids.data).getBytes()), - // content - asn1$3.create(asn1$3.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1$3.create( - asn1$3.Class.UNIVERSAL, asn1$3.Type.OCTETSTRING, false, - asn1$3.toDer(certSafeContents).getBytes()) - ]) - ]); - contents.push(certCI); - } - - // create safe contents for private key - var keyBag = null; - if(key !== null) { - // SafeBag - var pkAsn1 = pki$1.wrapRsaPrivateKey(pki$1.privateKeyToAsn1(key)); - if(password === null) { - // no encryption - keyBag = asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // bagId - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - asn1$3.oidToDer(pki$1.oids.keyBag).getBytes()), - // bagValue - asn1$3.create(asn1$3.Class.CONTEXT_SPECIFIC, 0, true, [ - // PrivateKeyInfo - pkAsn1 - ]), - // bagAttributes (OPTIONAL) - bagAttrs - ]); - } else { - // encrypted PrivateKeyInfo - keyBag = asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // bagId - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - asn1$3.oidToDer(pki$1.oids.pkcs8ShroudedKeyBag).getBytes()), - // bagValue - asn1$3.create(asn1$3.Class.CONTEXT_SPECIFIC, 0, true, [ - // EncryptedPrivateKeyInfo - pki$1.encryptPrivateKeyInfo(pkAsn1, password, options) - ]), - // bagAttributes (OPTIONAL) - bagAttrs - ]); - } - - // SafeContents - var keySafeContents = - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [keyBag]); - - // ContentInfo - var keyCI = - // PKCS#7 ContentInfo - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // contentType - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - // OID for the content type is 'data' - asn1$3.oidToDer(pki$1.oids.data).getBytes()), - // content - asn1$3.create(asn1$3.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1$3.create( - asn1$3.Class.UNIVERSAL, asn1$3.Type.OCTETSTRING, false, - asn1$3.toDer(keySafeContents).getBytes()) - ]) - ]); - contents.push(keyCI); - } - - // create AuthenticatedSafe by stringing together the contents - var safe = asn1$3.create( - asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, contents); - - var macData; - if(options.useMac) { - // MacData - var sha1 = forge$b.md.sha1.create(); - var macSalt = new forge$b.util.ByteBuffer( - forge$b.random.getBytes(options.saltSize)); - var count = options.count; - // 160-bit key - var key = p12.generateKey(password, macSalt, 3, count, 20); - var mac = forge$b.hmac.create(); - mac.start(sha1, key); - mac.update(asn1$3.toDer(safe).getBytes()); - var macValue = mac.getMac(); - macData = asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // mac DigestInfo - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // digestAlgorithm - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // algorithm = SHA-1 - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - asn1$3.oidToDer(pki$1.oids.sha1).getBytes()), - // parameters = Null - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.NULL, false, '') - ]), - // digest - asn1$3.create( - asn1$3.Class.UNIVERSAL, asn1$3.Type.OCTETSTRING, - false, macValue.getBytes()) - ]), - // macSalt OCTET STRING - asn1$3.create( - asn1$3.Class.UNIVERSAL, asn1$3.Type.OCTETSTRING, false, macSalt.getBytes()), - // iterations INTEGER (XXX: Only support count < 65536) - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.INTEGER, false, - asn1$3.integerToDer(count).getBytes() - ) - ]); - } - - // PFX - return asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // version (3) - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.INTEGER, false, - asn1$3.integerToDer(3).getBytes()), - // PKCS#7 ContentInfo - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.SEQUENCE, true, [ - // contentType - asn1$3.create(asn1$3.Class.UNIVERSAL, asn1$3.Type.OID, false, - // OID for the content type is 'data' - asn1$3.oidToDer(pki$1.oids.data).getBytes()), - // content - asn1$3.create(asn1$3.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1$3.create( - asn1$3.Class.UNIVERSAL, asn1$3.Type.OCTETSTRING, false, - asn1$3.toDer(safe).getBytes()) - ]) - ]), - macData - ]); -}; - -/** - * Derives a PKCS#12 key. - * - * @param password the password to derive the key material from, null or - * undefined for none. - * @param salt the salt, as a ByteBuffer, to use. - * @param id the PKCS#12 ID byte (1 = key material, 2 = IV, 3 = MAC). - * @param iter the iteration count. - * @param n the number of bytes to derive from the password. - * @param md the message digest to use, defaults to SHA-1. - * - * @return a ByteBuffer with the bytes derived from the password. - */ -p12.generateKey = forge$b.pbe.generatePkcs12Key; - -/** - * Javascript implementation of a basic Public Key Infrastructure, including - * support for RSA public and private keys. - * - * @author Dave Longley - * - * Copyright (c) 2010-2013 Digital Bazaar, Inc. - */ - -var forge$a = forge$D; - - - - - - - - - - - -// shortcut for asn.1 API -var asn1$2 = forge$a.asn1; - -/* Public Key Infrastructure (PKI) implementation. */ -var pki = forge$a.pki = forge$a.pki || {}; - -/** - * NOTE: THIS METHOD IS DEPRECATED. Use pem.decode() instead. - * - * Converts PEM-formatted data to DER. - * - * @param pem the PEM-formatted data. - * - * @return the DER-formatted data. - */ -pki.pemToDer = function(pem) { - var msg = forge$a.pem.decode(pem)[0]; - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - throw new Error('Could not convert PEM to DER; PEM is encrypted.'); - } - return forge$a.util.createBuffer(msg.body); -}; - -/** - * Converts an RSA private key from PEM format. - * - * @param pem the PEM-formatted private key. - * - * @return the private key. - */ -pki.privateKeyFromPem = function(pem) { - var msg = forge$a.pem.decode(pem)[0]; - - if(msg.type !== 'PRIVATE KEY' && msg.type !== 'RSA PRIVATE KEY') { - var error = new Error('Could not convert private key from PEM; PEM ' + - 'header type is not "PRIVATE KEY" or "RSA PRIVATE KEY".'); - error.headerType = msg.type; - throw error; - } - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - throw new Error('Could not convert private key from PEM; PEM is encrypted.'); - } - - // convert DER to ASN.1 object - var obj = asn1$2.fromDer(msg.body); - - return pki.privateKeyFromAsn1(obj); -}; - -/** - * Converts an RSA private key to PEM format. - * - * @param key the private key. - * @param maxline the maximum characters per line, defaults to 64. - * - * @return the PEM-formatted private key. - */ -pki.privateKeyToPem = function(key, maxline) { - // convert to ASN.1, then DER, then PEM-encode - var msg = { - type: 'RSA PRIVATE KEY', - body: asn1$2.toDer(pki.privateKeyToAsn1(key)).getBytes() - }; - return forge$a.pem.encode(msg, {maxline: maxline}); -}; - -/** - * Converts a PrivateKeyInfo to PEM format. - * - * @param pki the PrivateKeyInfo. - * @param maxline the maximum characters per line, defaults to 64. - * - * @return the PEM-formatted private key. - */ -pki.privateKeyInfoToPem = function(pki, maxline) { - // convert to DER, then PEM-encode - var msg = { - type: 'PRIVATE KEY', - body: asn1$2.toDer(pki).getBytes() - }; - return forge$a.pem.encode(msg, {maxline: maxline}); -}; - -/** - * A Javascript implementation of Transport Layer Security (TLS). - * - * @author Dave Longley - * - * Copyright (c) 2009-2014 Digital Bazaar, Inc. - * - * The TLS Handshake Protocol involves the following steps: - * - * - Exchange hello messages to agree on algorithms, exchange random values, - * and check for session resumption. - * - * - Exchange the necessary cryptographic parameters to allow the client and - * server to agree on a premaster secret. - * - * - Exchange certificates and cryptographic information to allow the client - * and server to authenticate themselves. - * - * - Generate a master secret from the premaster secret and exchanged random - * values. - * - * - Provide security parameters to the record layer. - * - * - Allow the client and server to verify that their peer has calculated the - * same security parameters and that the handshake occurred without tampering - * by an attacker. - * - * Up to 4 different messages may be sent during a key exchange. The server - * certificate, the server key exchange, the client certificate, and the - * client key exchange. - * - * A typical handshake (from the client's perspective). - * - * 1. Client sends ClientHello. - * 2. Client receives ServerHello. - * 3. Client receives optional Certificate. - * 4. Client receives optional ServerKeyExchange. - * 5. Client receives ServerHelloDone. - * 6. Client sends optional Certificate. - * 7. Client sends ClientKeyExchange. - * 8. Client sends optional CertificateVerify. - * 9. Client sends ChangeCipherSpec. - * 10. Client sends Finished. - * 11. Client receives ChangeCipherSpec. - * 12. Client receives Finished. - * 13. Client sends/receives application data. - * - * To reuse an existing session: - * - * 1. Client sends ClientHello with session ID for reuse. - * 2. Client receives ServerHello with same session ID if reusing. - * 3. Client receives ChangeCipherSpec message if reusing. - * 4. Client receives Finished. - * 5. Client sends ChangeCipherSpec. - * 6. Client sends Finished. - * - * Note: Client ignores HelloRequest if in the middle of a handshake. - * - * Record Layer: - * - * The record layer fragments information blocks into TLSPlaintext records - * carrying data in chunks of 2^14 bytes or less. Client message boundaries are - * not preserved in the record layer (i.e., multiple client messages of the - * same ContentType MAY be coalesced into a single TLSPlaintext record, or a - * single message MAY be fragmented across several records). - * - * struct { - * uint8 major; - * uint8 minor; - * } ProtocolVersion; - * - * struct { - * ContentType type; - * ProtocolVersion version; - * uint16 length; - * opaque fragment[TLSPlaintext.length]; - * } TLSPlaintext; - * - * type: - * The higher-level protocol used to process the enclosed fragment. - * - * version: - * The version of the protocol being employed. TLS Version 1.2 uses version - * {3, 3}. TLS Version 1.0 uses version {3, 1}. Note that a client that - * supports multiple versions of TLS may not know what version will be - * employed before it receives the ServerHello. - * - * length: - * The length (in bytes) of the following TLSPlaintext.fragment. The length - * MUST NOT exceed 2^14 = 16384 bytes. - * - * fragment: - * The application data. This data is transparent and treated as an - * independent block to be dealt with by the higher-level protocol specified - * by the type field. - * - * Implementations MUST NOT send zero-length fragments of Handshake, Alert, or - * ChangeCipherSpec content types. Zero-length fragments of Application data - * MAY be sent as they are potentially useful as a traffic analysis - * countermeasure. - * - * Note: Data of different TLS record layer content types MAY be interleaved. - * Application data is generally of lower precedence for transmission than - * other content types. However, records MUST be delivered to the network in - * the same order as they are protected by the record layer. Recipients MUST - * receive and process interleaved application layer traffic during handshakes - * subsequent to the first one on a connection. - * - * struct { - * ContentType type; // same as TLSPlaintext.type - * ProtocolVersion version;// same as TLSPlaintext.version - * uint16 length; - * opaque fragment[TLSCompressed.length]; - * } TLSCompressed; - * - * length: - * The length (in bytes) of the following TLSCompressed.fragment. - * The length MUST NOT exceed 2^14 + 1024. - * - * fragment: - * The compressed form of TLSPlaintext.fragment. - * - * Note: A CompressionMethod.null operation is an identity operation; no fields - * are altered. In this implementation, since no compression is supported, - * uncompressed records are always the same as compressed records. - * - * Encryption Information: - * - * The encryption and MAC functions translate a TLSCompressed structure into a - * TLSCiphertext. The decryption functions reverse the process. The MAC of the - * record also includes a sequence number so that missing, extra, or repeated - * messages are detectable. - * - * struct { - * ContentType type; - * ProtocolVersion version; - * uint16 length; - * select (SecurityParameters.cipher_type) { - * case stream: GenericStreamCipher; - * case block: GenericBlockCipher; - * case aead: GenericAEADCipher; - * } fragment; - * } TLSCiphertext; - * - * type: - * The type field is identical to TLSCompressed.type. - * - * version: - * The version field is identical to TLSCompressed.version. - * - * length: - * The length (in bytes) of the following TLSCiphertext.fragment. - * The length MUST NOT exceed 2^14 + 2048. - * - * fragment: - * The encrypted form of TLSCompressed.fragment, with the MAC. - * - * Note: Only CBC Block Ciphers are supported by this implementation. - * - * The TLSCompressed.fragment structures are converted to/from block - * TLSCiphertext.fragment structures. - * - * struct { - * opaque IV[SecurityParameters.record_iv_length]; - * block-ciphered struct { - * opaque content[TLSCompressed.length]; - * opaque MAC[SecurityParameters.mac_length]; - * uint8 padding[GenericBlockCipher.padding_length]; - * uint8 padding_length; - * }; - * } GenericBlockCipher; - * - * The MAC is generated as described in Section 6.2.3.1. - * - * IV: - * The Initialization Vector (IV) SHOULD be chosen at random, and MUST be - * unpredictable. Note that in versions of TLS prior to 1.1, there was no - * IV field, and the last ciphertext block of the previous record (the "CBC - * residue") was used as the IV. This was changed to prevent the attacks - * described in [CBCATT]. For block ciphers, the IV length is of length - * SecurityParameters.record_iv_length, which is equal to the - * SecurityParameters.block_size. - * - * padding: - * Padding that is added to force the length of the plaintext to be an - * integral multiple of the block cipher's block length. The padding MAY be - * any length up to 255 bytes, as long as it results in the - * TLSCiphertext.length being an integral multiple of the block length. - * Lengths longer than necessary might be desirable to frustrate attacks on - * a protocol that are based on analysis of the lengths of exchanged - * messages. Each uint8 in the padding data vector MUST be filled with the - * padding length value. The receiver MUST check this padding and MUST use - * the bad_record_mac alert to indicate padding errors. - * - * padding_length: - * The padding length MUST be such that the total size of the - * GenericBlockCipher structure is a multiple of the cipher's block length. - * Legal values range from zero to 255, inclusive. This length specifies the - * length of the padding field exclusive of the padding_length field itself. - * - * The encrypted data length (TLSCiphertext.length) is one more than the sum of - * SecurityParameters.block_length, TLSCompressed.length, - * SecurityParameters.mac_length, and padding_length. - * - * Example: If the block length is 8 bytes, the content length - * (TLSCompressed.length) is 61 bytes, and the MAC length is 20 bytes, then the - * length before padding is 82 bytes (this does not include the IV. Thus, the - * padding length modulo 8 must be equal to 6 in order to make the total length - * an even multiple of 8 bytes (the block length). The padding length can be - * 6, 14, 22, and so on, through 254. If the padding length were the minimum - * necessary, 6, the padding would be 6 bytes, each containing the value 6. - * Thus, the last 8 octets of the GenericBlockCipher before block encryption - * would be xx 06 06 06 06 06 06 06, where xx is the last octet of the MAC. - * - * Note: With block ciphers in CBC mode (Cipher Block Chaining), it is critical - * that the entire plaintext of the record be known before any ciphertext is - * transmitted. Otherwise, it is possible for the attacker to mount the attack - * described in [CBCATT]. - * - * Implementation note: Canvel et al. [CBCTIME] have demonstrated a timing - * attack on CBC padding based on the time required to compute the MAC. In - * order to defend against this attack, implementations MUST ensure that - * record processing time is essentially the same whether or not the padding - * is correct. In general, the best way to do this is to compute the MAC even - * if the padding is incorrect, and only then reject the packet. For instance, - * if the pad appears to be incorrect, the implementation might assume a - * zero-length pad and then compute the MAC. This leaves a small timing - * channel, since MAC performance depends, to some extent, on the size of the - * data fragment, but it is not believed to be large enough to be exploitable, - * due to the large block size of existing MACs and the small size of the - * timing signal. - */ - -var forge$9 = forge$D; - - - - - - - - - -/** - * Generates pseudo random bytes by mixing the result of two hash functions, - * MD5 and SHA-1. - * - * prf_TLS1(secret, label, seed) = - * P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed); - * - * Each P_hash function functions as follows: - * - * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + - * HMAC_hash(secret, A(2) + seed) + - * HMAC_hash(secret, A(3) + seed) + ... - * A() is defined as: - * A(0) = seed - * A(i) = HMAC_hash(secret, A(i-1)) - * - * The '+' operator denotes concatenation. - * - * As many iterations A(N) as are needed are performed to generate enough - * pseudo random byte output. If an iteration creates more data than is - * necessary, then it is truncated. - * - * Therefore: - * A(1) = HMAC_hash(secret, A(0)) - * = HMAC_hash(secret, seed) - * A(2) = HMAC_hash(secret, A(1)) - * = HMAC_hash(secret, HMAC_hash(secret, seed)) - * - * Therefore: - * P_hash(secret, seed) = - * HMAC_hash(secret, HMAC_hash(secret, A(0)) + seed) + - * HMAC_hash(secret, HMAC_hash(secret, A(1)) + seed) + - * ... - * - * Therefore: - * P_hash(secret, seed) = - * HMAC_hash(secret, HMAC_hash(secret, seed) + seed) + - * HMAC_hash(secret, HMAC_hash(secret, HMAC_hash(secret, seed)) + seed) + - * ... - * - * @param secret the secret to use. - * @param label the label to use. - * @param seed the seed value to use. - * @param length the number of bytes to generate. - * - * @return the pseudo random bytes in a byte buffer. - */ -var prf_TLS1 = function(secret, label, seed, length) { - var rval = forge$9.util.createBuffer(); - - /* For TLS 1.0, the secret is split in half, into two secrets of equal - length. If the secret has an odd length then the last byte of the first - half will be the same as the first byte of the second. The length of the - two secrets is half of the secret rounded up. */ - var idx = (secret.length >> 1); - var slen = idx + (secret.length & 1); - var s1 = secret.substr(0, slen); - var s2 = secret.substr(idx, slen); - var ai = forge$9.util.createBuffer(); - var hmac = forge$9.hmac.create(); - seed = label + seed; - - // determine the number of iterations that must be performed to generate - // enough output bytes, md5 creates 16 byte hashes, sha1 creates 20 - var md5itr = Math.ceil(length / 16); - var sha1itr = Math.ceil(length / 20); - - // do md5 iterations - hmac.start('MD5', s1); - var md5bytes = forge$9.util.createBuffer(); - ai.putBytes(seed); - for(var i = 0; i < md5itr; ++i) { - // HMAC_hash(secret, A(i-1)) - hmac.start(null, null); - hmac.update(ai.getBytes()); - ai.putBuffer(hmac.digest()); - - // HMAC_hash(secret, A(i) + seed) - hmac.start(null, null); - hmac.update(ai.bytes() + seed); - md5bytes.putBuffer(hmac.digest()); - } - - // do sha1 iterations - hmac.start('SHA1', s2); - var sha1bytes = forge$9.util.createBuffer(); - ai.clear(); - ai.putBytes(seed); - for(var i = 0; i < sha1itr; ++i) { - // HMAC_hash(secret, A(i-1)) - hmac.start(null, null); - hmac.update(ai.getBytes()); - ai.putBuffer(hmac.digest()); - - // HMAC_hash(secret, A(i) + seed) - hmac.start(null, null); - hmac.update(ai.bytes() + seed); - sha1bytes.putBuffer(hmac.digest()); - } - - // XOR the md5 bytes with the sha1 bytes - rval.putBytes(forge$9.util.xorBytes( - md5bytes.getBytes(), sha1bytes.getBytes(), length)); - - return rval; -}; - -/** - * Gets a MAC for a record using the SHA-1 hash algorithm. - * - * @param key the mac key. - * @param state the sequence number (array of two 32-bit integers). - * @param record the record. - * - * @return the sha-1 hash (20 bytes) for the given record. - */ -var hmac_sha1 = function(key, seqNum, record) { - /* MAC is computed like so: - HMAC_hash( - key, seqNum + - TLSCompressed.type + - TLSCompressed.version + - TLSCompressed.length + - TLSCompressed.fragment) - */ - var hmac = forge$9.hmac.create(); - hmac.start('SHA1', key); - var b = forge$9.util.createBuffer(); - b.putInt32(seqNum[0]); - b.putInt32(seqNum[1]); - b.putByte(record.type); - b.putByte(record.version.major); - b.putByte(record.version.minor); - b.putInt16(record.length); - b.putBytes(record.fragment.bytes()); - hmac.update(b.getBytes()); - return hmac.digest().getBytes(); -}; - -/** - * Compresses the TLSPlaintext record into a TLSCompressed record using the - * deflate algorithm. - * - * @param c the TLS connection. - * @param record the TLSPlaintext record to compress. - * @param s the ConnectionState to use. - * - * @return true on success, false on failure. - */ -var deflate = function(c, record, s) { - var rval = false; - - try { - var bytes = c.deflate(record.fragment.getBytes()); - record.fragment = forge$9.util.createBuffer(bytes); - record.length = bytes.length; - rval = true; - } catch(ex) { - // deflate error, fail out - } - - return rval; -}; - -/** - * Decompresses the TLSCompressed record into a TLSPlaintext record using the - * deflate algorithm. - * - * @param c the TLS connection. - * @param record the TLSCompressed record to decompress. - * @param s the ConnectionState to use. - * - * @return true on success, false on failure. - */ -var inflate = function(c, record, s) { - var rval = false; - - try { - var bytes = c.inflate(record.fragment.getBytes()); - record.fragment = forge$9.util.createBuffer(bytes); - record.length = bytes.length; - rval = true; - } catch(ex) { - // inflate error, fail out - } - - return rval; -}; - -/** - * Reads a TLS variable-length vector from a byte buffer. - * - * Variable-length vectors are defined by specifying a subrange of legal - * lengths, inclusively, using the notation . When these are - * encoded, the actual length precedes the vector's contents in the byte - * stream. The length will be in the form of a number consuming as many bytes - * as required to hold the vector's specified maximum (ceiling) length. A - * variable-length vector with an actual length field of zero is referred to - * as an empty vector. - * - * @param b the byte buffer. - * @param lenBytes the number of bytes required to store the length. - * - * @return the resulting byte buffer. - */ -var readVector = function(b, lenBytes) { - var len = 0; - switch(lenBytes) { - case 1: - len = b.getByte(); - break; - case 2: - len = b.getInt16(); - break; - case 3: - len = b.getInt24(); - break; - case 4: - len = b.getInt32(); - break; - } - - // read vector bytes into a new buffer - return forge$9.util.createBuffer(b.getBytes(len)); -}; - -/** - * Writes a TLS variable-length vector to a byte buffer. - * - * @param b the byte buffer. - * @param lenBytes the number of bytes required to store the length. - * @param v the byte buffer vector. - */ -var writeVector = function(b, lenBytes, v) { - // encode length at the start of the vector, where the number of bytes for - // the length is the maximum number of bytes it would take to encode the - // vector's ceiling - b.putInt(v.length(), lenBytes << 3); - b.putBuffer(v); -}; - -/** - * The tls implementation. - */ -var tls$1 = {}; - -/** - * Version: TLS 1.2 = 3.3, TLS 1.1 = 3.2, TLS 1.0 = 3.1. Both TLS 1.1 and - * TLS 1.2 were still too new (ie: openSSL didn't implement them) at the time - * of this implementation so TLS 1.0 was implemented instead. - */ -tls$1.Versions = { - TLS_1_0: {major: 3, minor: 1}, - TLS_1_1: {major: 3, minor: 2}, - TLS_1_2: {major: 3, minor: 3} -}; -tls$1.SupportedVersions = [ - tls$1.Versions.TLS_1_1, - tls$1.Versions.TLS_1_0 -]; -tls$1.Version = tls$1.SupportedVersions[0]; - -/** - * Maximum fragment size. True maximum is 16384, but we fragment before that - * to allow for unusual small increases during compression. - */ -tls$1.MaxFragment = 16384 - 1024; - -/** - * Whether this entity is considered the "client" or "server". - * enum { server, client } ConnectionEnd; - */ -tls$1.ConnectionEnd = { - server: 0, - client: 1 -}; - -/** - * Pseudo-random function algorithm used to generate keys from the master - * secret. - * enum { tls_prf_sha256 } PRFAlgorithm; - */ -tls$1.PRFAlgorithm = { - tls_prf_sha256: 0 -}; - -/** - * Bulk encryption algorithms. - * enum { null, rc4, des3, aes } BulkCipherAlgorithm; - */ -tls$1.BulkCipherAlgorithm = { - none: null, - rc4: 0, - des3: 1, - aes: 2 -}; - -/** - * Cipher types. - * enum { stream, block, aead } CipherType; - */ -tls$1.CipherType = { - stream: 0, - block: 1, - aead: 2 -}; - -/** - * MAC (Message Authentication Code) algorithms. - * enum { null, hmac_md5, hmac_sha1, hmac_sha256, - * hmac_sha384, hmac_sha512} MACAlgorithm; - */ -tls$1.MACAlgorithm = { - none: null, - hmac_md5: 0, - hmac_sha1: 1, - hmac_sha256: 2, - hmac_sha384: 3, - hmac_sha512: 4 -}; - -/** - * Compression algorithms. - * enum { null(0), deflate(1), (255) } CompressionMethod; - */ -tls$1.CompressionMethod = { - none: 0, - deflate: 1 -}; - -/** - * TLS record content types. - * enum { - * change_cipher_spec(20), alert(21), handshake(22), - * application_data(23), (255) - * } ContentType; - */ -tls$1.ContentType = { - change_cipher_spec: 20, - alert: 21, - handshake: 22, - application_data: 23, - heartbeat: 24 -}; - -/** - * TLS handshake types. - * enum { - * hello_request(0), client_hello(1), server_hello(2), - * certificate(11), server_key_exchange (12), - * certificate_request(13), server_hello_done(14), - * certificate_verify(15), client_key_exchange(16), - * finished(20), (255) - * } HandshakeType; - */ -tls$1.HandshakeType = { - hello_request: 0, - client_hello: 1, - server_hello: 2, - certificate: 11, - server_key_exchange: 12, - certificate_request: 13, - server_hello_done: 14, - certificate_verify: 15, - client_key_exchange: 16, - finished: 20 -}; - -/** - * TLS Alert Protocol. - * - * enum { warning(1), fatal(2), (255) } AlertLevel; - * - * enum { - * close_notify(0), - * unexpected_message(10), - * bad_record_mac(20), - * decryption_failed(21), - * record_overflow(22), - * decompression_failure(30), - * handshake_failure(40), - * bad_certificate(42), - * unsupported_certificate(43), - * certificate_revoked(44), - * certificate_expired(45), - * certificate_unknown(46), - * illegal_parameter(47), - * unknown_ca(48), - * access_denied(49), - * decode_error(50), - * decrypt_error(51), - * export_restriction(60), - * protocol_version(70), - * insufficient_security(71), - * internal_error(80), - * user_canceled(90), - * no_renegotiation(100), - * (255) - * } AlertDescription; - * - * struct { - * AlertLevel level; - * AlertDescription description; - * } Alert; - */ -tls$1.Alert = {}; -tls$1.Alert.Level = { - warning: 1, - fatal: 2 -}; -tls$1.Alert.Description = { - close_notify: 0, - unexpected_message: 10, - bad_record_mac: 20, - decryption_failed: 21, - record_overflow: 22, - decompression_failure: 30, - handshake_failure: 40, - bad_certificate: 42, - unsupported_certificate: 43, - certificate_revoked: 44, - certificate_expired: 45, - certificate_unknown: 46, - illegal_parameter: 47, - unknown_ca: 48, - access_denied: 49, - decode_error: 50, - decrypt_error: 51, - export_restriction: 60, - protocol_version: 70, - insufficient_security: 71, - internal_error: 80, - user_canceled: 90, - no_renegotiation: 100 -}; - -/** - * TLS Heartbeat Message types. - * enum { - * heartbeat_request(1), - * heartbeat_response(2), - * (255) - * } HeartbeatMessageType; - */ -tls$1.HeartbeatMessageType = { - heartbeat_request: 1, - heartbeat_response: 2 -}; - -/** - * Supported cipher suites. - */ -tls$1.CipherSuites = {}; - -/** - * Gets a supported cipher suite from its 2 byte ID. - * - * @param twoBytes two bytes in a string. - * - * @return the matching supported cipher suite or null. - */ -tls$1.getCipherSuite = function(twoBytes) { - var rval = null; - for(var key in tls$1.CipherSuites) { - var cs = tls$1.CipherSuites[key]; - if(cs.id[0] === twoBytes.charCodeAt(0) && - cs.id[1] === twoBytes.charCodeAt(1)) { - rval = cs; - break; - } - } - return rval; -}; - -/** - * Called when an unexpected record is encountered. - * - * @param c the connection. - * @param record the record. - */ -tls$1.handleUnexpected = function(c, record) { - // if connection is client and closed, ignore unexpected messages - var ignore = (!c.open && c.entity === tls$1.ConnectionEnd.client); - if(!ignore) { - c.error(c, { - message: 'Unexpected message. Received TLS record out of order.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.unexpected_message - } - }); - } -}; - -/** - * Called when a client receives a HelloRequest record. - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleHelloRequest = function(c, record, length) { - // ignore renegotiation requests from the server during a handshake, but - // if handshaking, send a warning alert that renegotation is denied - if(!c.handshaking && c.handshakes > 0) { - // send alert warning - tls$1.queue(c, tls$1.createAlert(c, { - level: tls$1.Alert.Level.warning, - description: tls$1.Alert.Description.no_renegotiation - })); - tls$1.flush(c); - } - - // continue - c.process(); -}; - -/** - * Parses a hello message from a ClientHello or ServerHello record. - * - * @param record the record to parse. - * - * @return the parsed message. - */ -tls$1.parseHelloMessage = function(c, record, length) { - var msg = null; - - var client = (c.entity === tls$1.ConnectionEnd.client); - - // minimum of 38 bytes in message - if(length < 38) { - c.error(c, { - message: client ? - 'Invalid ServerHello message. Message too short.' : - 'Invalid ClientHello message. Message too short.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.illegal_parameter - } - }); - } else { - // use 'remaining' to calculate # of remaining bytes in the message - var b = record.fragment; - var remaining = b.length(); - msg = { - version: { - major: b.getByte(), - minor: b.getByte() - }, - random: forge$9.util.createBuffer(b.getBytes(32)), - session_id: readVector(b, 1), - extensions: [] - }; - if(client) { - msg.cipher_suite = b.getBytes(2); - msg.compression_method = b.getByte(); - } else { - msg.cipher_suites = readVector(b, 2); - msg.compression_methods = readVector(b, 1); - } - - // read extensions if there are any bytes left in the message - remaining = length - (remaining - b.length()); - if(remaining > 0) { - // parse extensions - var exts = readVector(b, 2); - while(exts.length() > 0) { - msg.extensions.push({ - type: [exts.getByte(), exts.getByte()], - data: readVector(exts, 2) - }); - } - - // TODO: make extension support modular - if(!client) { - for(var i = 0; i < msg.extensions.length; ++i) { - var ext = msg.extensions[i]; - - // support SNI extension - if(ext.type[0] === 0x00 && ext.type[1] === 0x00) { - // get server name list - var snl = readVector(ext.data, 2); - while(snl.length() > 0) { - // read server name type - var snType = snl.getByte(); - - // only HostName type (0x00) is known, break out if - // another type is detected - if(snType !== 0x00) { - break; - } - - // add host name to server name list - c.session.extensions.server_name.serverNameList.push( - readVector(snl, 2).getBytes()); - } - } - } - } - } - - // version already set, do not allow version change - if(c.session.version) { - if(msg.version.major !== c.session.version.major || - msg.version.minor !== c.session.version.minor) { - return c.error(c, { - message: 'TLS version change is disallowed during renegotiation.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.protocol_version - } - }); - } - } - - // get the chosen (ServerHello) cipher suite - if(client) { - // FIXME: should be checking configured acceptable cipher suites - c.session.cipherSuite = tls$1.getCipherSuite(msg.cipher_suite); - } else { - // get a supported preferred (ClientHello) cipher suite - // choose the first supported cipher suite - var tmp = forge$9.util.createBuffer(msg.cipher_suites.bytes()); - while(tmp.length() > 0) { - // FIXME: should be checking configured acceptable suites - // cipher suites take up 2 bytes - c.session.cipherSuite = tls$1.getCipherSuite(tmp.getBytes(2)); - if(c.session.cipherSuite !== null) { - break; - } - } - } - - // cipher suite not supported - if(c.session.cipherSuite === null) { - return c.error(c, { - message: 'No cipher suites in common.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.handshake_failure - }, - cipherSuite: forge$9.util.bytesToHex(msg.cipher_suite) - }); - } - - // TODO: handle compression methods - if(client) { - c.session.compressionMethod = msg.compression_method; - } else { - // no compression - c.session.compressionMethod = tls$1.CompressionMethod.none; - } - } - - return msg; -}; - -/** - * Creates security parameters for the given connection based on the given - * hello message. - * - * @param c the TLS connection. - * @param msg the hello message. - */ -tls$1.createSecurityParameters = function(c, msg) { - /* Note: security params are from TLS 1.2, some values like prf_algorithm - are ignored for TLS 1.0/1.1 and the builtin as specified in the spec is - used. */ - - // TODO: handle other options from server when more supported - - // get client and server randoms - var client = (c.entity === tls$1.ConnectionEnd.client); - var msgRandom = msg.random.bytes(); - var cRandom = client ? c.session.sp.client_random : msgRandom; - var sRandom = client ? msgRandom : tls$1.createRandom().getBytes(); - - // create new security parameters - c.session.sp = { - entity: c.entity, - prf_algorithm: tls$1.PRFAlgorithm.tls_prf_sha256, - bulk_cipher_algorithm: null, - cipher_type: null, - enc_key_length: null, - block_length: null, - fixed_iv_length: null, - record_iv_length: null, - mac_algorithm: null, - mac_length: null, - mac_key_length: null, - compression_algorithm: c.session.compressionMethod, - pre_master_secret: null, - master_secret: null, - client_random: cRandom, - server_random: sRandom - }; -}; - -/** - * Called when a client receives a ServerHello record. - * - * When a ServerHello message will be sent: - * The server will send this message in response to a client hello message - * when it was able to find an acceptable set of algorithms. If it cannot - * find such a match, it will respond with a handshake failure alert. - * - * uint24 length; - * struct { - * ProtocolVersion server_version; - * Random random; - * SessionID session_id; - * CipherSuite cipher_suite; - * CompressionMethod compression_method; - * select(extensions_present) { - * case false: - * struct {}; - * case true: - * Extension extensions<0..2^16-1>; - * }; - * } ServerHello; - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleServerHello = function(c, record, length) { - var msg = tls$1.parseHelloMessage(c, record, length); - if(c.fail) { - return; - } - - // ensure server version is compatible - if(msg.version.minor <= c.version.minor) { - c.version.minor = msg.version.minor; - } else { - return c.error(c, { - message: 'Incompatible TLS version.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.protocol_version - } - }); - } - - // indicate session version has been set - c.session.version = c.version; - - // get the session ID from the message - var sessionId = msg.session_id.bytes(); - - // if the session ID is not blank and matches the cached one, resume - // the session - if(sessionId.length > 0 && sessionId === c.session.id) { - // resuming session, expect a ChangeCipherSpec next - c.expect = SCC; - c.session.resuming = true; - - // get new server random - c.session.sp.server_random = msg.random.bytes(); - } else { - // not resuming, expect a server Certificate message next - c.expect = SCE; - c.session.resuming = false; - - // create new security parameters - tls$1.createSecurityParameters(c, msg); - } - - // set new session ID - c.session.id = sessionId; - - // continue - c.process(); -}; - -/** - * Called when a server receives a ClientHello record. - * - * When a ClientHello message will be sent: - * When a client first connects to a server it is required to send the - * client hello as its first message. The client can also send a client - * hello in response to a hello request or on its own initiative in order - * to renegotiate the security parameters in an existing connection. - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleClientHello = function(c, record, length) { - var msg = tls$1.parseHelloMessage(c, record, length); - if(c.fail) { - return; - } - - // get the session ID from the message - var sessionId = msg.session_id.bytes(); - - // see if the given session ID is in the cache - var session = null; - if(c.sessionCache) { - session = c.sessionCache.getSession(sessionId); - if(session === null) { - // session ID not found - sessionId = ''; - } else if(session.version.major !== msg.version.major || - session.version.minor > msg.version.minor) { - // if session version is incompatible with client version, do not resume - session = null; - sessionId = ''; - } - } - - // no session found to resume, generate a new session ID - if(sessionId.length === 0) { - sessionId = forge$9.random.getBytes(32); - } - - // update session - c.session.id = sessionId; - c.session.clientHelloVersion = msg.version; - c.session.sp = {}; - if(session) { - // use version and security parameters from resumed session - c.version = c.session.version = session.version; - c.session.sp = session.sp; - } else { - // use highest compatible minor version - var version; - for(var i = 1; i < tls$1.SupportedVersions.length; ++i) { - version = tls$1.SupportedVersions[i]; - if(version.minor <= msg.version.minor) { - break; - } - } - c.version = {major: version.major, minor: version.minor}; - c.session.version = c.version; - } - - // if a session is set, resume it - if(session !== null) { - // resuming session, expect a ChangeCipherSpec next - c.expect = CCC; - c.session.resuming = true; - - // get new client random - c.session.sp.client_random = msg.random.bytes(); - } else { - // not resuming, expect a Certificate or ClientKeyExchange - c.expect = (c.verifyClient !== false) ? CCE : CKE; - c.session.resuming = false; - - // create new security parameters - tls$1.createSecurityParameters(c, msg); - } - - // connection now open - c.open = true; - - // queue server hello - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createServerHello(c) - })); - - if(c.session.resuming) { - // queue change cipher spec message - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.change_cipher_spec, - data: tls$1.createChangeCipherSpec() - })); - - // create pending state - c.state.pending = tls$1.createConnectionState(c); - - // change current write state to pending write state - c.state.current.write = c.state.pending.write; - - // queue finished - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createFinished(c) - })); - } else { - // queue server certificate - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createCertificate(c) - })); - - if(!c.fail) { - // queue server key exchange - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createServerKeyExchange(c) - })); - - // request client certificate if set - if(c.verifyClient !== false) { - // queue certificate request - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createCertificateRequest(c) - })); - } - - // queue server hello done - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createServerHelloDone(c) - })); - } - } - - // send records - tls$1.flush(c); - - // continue - c.process(); -}; - -/** - * Called when a client receives a Certificate record. - * - * When this message will be sent: - * The server must send a certificate whenever the agreed-upon key exchange - * method is not an anonymous one. This message will always immediately - * follow the server hello message. - * - * Meaning of this message: - * The certificate type must be appropriate for the selected cipher suite's - * key exchange algorithm, and is generally an X.509v3 certificate. It must - * contain a key which matches the key exchange method, as follows. Unless - * otherwise specified, the signing algorithm for the certificate must be - * the same as the algorithm for the certificate key. Unless otherwise - * specified, the public key may be of any length. - * - * opaque ASN.1Cert<1..2^24-1>; - * struct { - * ASN.1Cert certificate_list<1..2^24-1>; - * } Certificate; - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleCertificate = function(c, record, length) { - // minimum of 3 bytes in message - if(length < 3) { - return c.error(c, { - message: 'Invalid Certificate message. Message too short.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.illegal_parameter - } - }); - } - - var b = record.fragment; - var msg = { - certificate_list: readVector(b, 3) - }; - - /* The sender's certificate will be first in the list (chain), each - subsequent one that follows will certify the previous one, but root - certificates (self-signed) that specify the certificate authority may - be omitted under the assumption that clients must already possess it. */ - var cert, asn1; - var certs = []; - try { - while(msg.certificate_list.length() > 0) { - // each entry in msg.certificate_list is a vector with 3 len bytes - cert = readVector(msg.certificate_list, 3); - asn1 = forge$9.asn1.fromDer(cert); - cert = forge$9.pki.certificateFromAsn1(asn1, true); - certs.push(cert); - } - } catch(ex) { - return c.error(c, { - message: 'Could not parse certificate list.', - cause: ex, - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.bad_certificate - } - }); - } - - // ensure at least 1 certificate was provided if in client-mode - // or if verifyClient was set to true to require a certificate - // (as opposed to 'optional') - var client = (c.entity === tls$1.ConnectionEnd.client); - if((client || c.verifyClient === true) && certs.length === 0) { - // error, no certificate - c.error(c, { - message: client ? - 'No server certificate provided.' : - 'No client certificate provided.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.illegal_parameter - } - }); - } else if(certs.length === 0) { - // no certs to verify - // expect a ServerKeyExchange or ClientKeyExchange message next - c.expect = client ? SKE : CKE; - } else { - // save certificate in session - if(client) { - c.session.serverCertificate = certs[0]; - } else { - c.session.clientCertificate = certs[0]; - } - - if(tls$1.verifyCertificateChain(c, certs)) { - // expect a ServerKeyExchange or ClientKeyExchange message next - c.expect = client ? SKE : CKE; - } - } - - // continue - c.process(); -}; - -/** - * Called when a client receives a ServerKeyExchange record. - * - * When this message will be sent: - * This message will be sent immediately after the server certificate - * message (or the server hello message, if this is an anonymous - * negotiation). - * - * The server key exchange message is sent by the server only when the - * server certificate message (if sent) does not contain enough data to - * allow the client to exchange a premaster secret. - * - * Meaning of this message: - * This message conveys cryptographic information to allow the client to - * communicate the premaster secret: either an RSA public key to encrypt - * the premaster secret with, or a Diffie-Hellman public key with which the - * client can complete a key exchange (with the result being the premaster - * secret.) - * - * enum { - * dhe_dss, dhe_rsa, dh_anon, rsa, dh_dss, dh_rsa - * } KeyExchangeAlgorithm; - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - * - * struct { - * select(KeyExchangeAlgorithm) { - * case dh_anon: - * ServerDHParams params; - * case dhe_dss: - * case dhe_rsa: - * ServerDHParams params; - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * } signed_params; - * case rsa: - * case dh_dss: - * case dh_rsa: - * struct {}; - * }; - * } ServerKeyExchange; - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleServerKeyExchange = function(c, record, length) { - // this implementation only supports RSA, no Diffie-Hellman support - // so any length > 0 is invalid - if(length > 0) { - return c.error(c, { - message: 'Invalid key parameters. Only RSA is supported.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.unsupported_certificate - } - }); - } - - // expect an optional CertificateRequest message next - c.expect = SCR; - - // continue - c.process(); -}; - -/** - * Called when a client receives a ClientKeyExchange record. - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleClientKeyExchange = function(c, record, length) { - // this implementation only supports RSA, no Diffie-Hellman support - // so any length < 48 is invalid - if(length < 48) { - return c.error(c, { - message: 'Invalid key parameters. Only RSA is supported.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.unsupported_certificate - } - }); - } - - var b = record.fragment; - var msg = { - enc_pre_master_secret: readVector(b, 2).getBytes() - }; - - // do rsa decryption - var privateKey = null; - if(c.getPrivateKey) { - try { - privateKey = c.getPrivateKey(c, c.session.serverCertificate); - privateKey = forge$9.pki.privateKeyFromPem(privateKey); - } catch(ex) { - c.error(c, { - message: 'Could not get private key.', - cause: ex, - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.internal_error - } - }); - } - } - - if(privateKey === null) { - return c.error(c, { - message: 'No private key set.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.internal_error - } - }); - } - - try { - // decrypt 48-byte pre-master secret - var sp = c.session.sp; - sp.pre_master_secret = privateKey.decrypt(msg.enc_pre_master_secret); - - // ensure client hello version matches first 2 bytes - var version = c.session.clientHelloVersion; - if(version.major !== sp.pre_master_secret.charCodeAt(0) || - version.minor !== sp.pre_master_secret.charCodeAt(1)) { - // error, do not send alert (see BLEI attack below) - throw new Error('TLS version rollback attack detected.'); - } - } catch(ex) { - /* Note: Daniel Bleichenbacher [BLEI] can be used to attack a - TLS server which is using PKCS#1 encoded RSA, so instead of - failing here, we generate 48 random bytes and use that as - the pre-master secret. */ - sp.pre_master_secret = forge$9.random.getBytes(48); - } - - // expect a CertificateVerify message if a Certificate was received that - // does not have fixed Diffie-Hellman params, otherwise expect - // ChangeCipherSpec - c.expect = CCC; - if(c.session.clientCertificate !== null) { - // only RSA support, so expect CertificateVerify - // TODO: support Diffie-Hellman - c.expect = CCV; - } - - // continue - c.process(); -}; - -/** - * Called when a client receives a CertificateRequest record. - * - * When this message will be sent: - * A non-anonymous server can optionally request a certificate from the - * client, if appropriate for the selected cipher suite. This message, if - * sent, will immediately follow the Server Key Exchange message (if it is - * sent; otherwise, the Server Certificate message). - * - * enum { - * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), - * rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6), - * fortezza_dms_RESERVED(20), (255) - * } ClientCertificateType; - * - * opaque DistinguishedName<1..2^16-1>; - * - * struct { - * ClientCertificateType certificate_types<1..2^8-1>; - * SignatureAndHashAlgorithm supported_signature_algorithms<2^16-1>; - * DistinguishedName certificate_authorities<0..2^16-1>; - * } CertificateRequest; - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleCertificateRequest = function(c, record, length) { - // minimum of 3 bytes in message - if(length < 3) { - return c.error(c, { - message: 'Invalid CertificateRequest. Message too short.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.illegal_parameter - } - }); - } - - // TODO: TLS 1.2+ has different format including - // SignatureAndHashAlgorithm after cert types - var b = record.fragment; - var msg = { - certificate_types: readVector(b, 1), - certificate_authorities: readVector(b, 2) - }; - - // save certificate request in session - c.session.certificateRequest = msg; - - // expect a ServerHelloDone message next - c.expect = SHD; - - // continue - c.process(); -}; - -/** - * Called when a server receives a CertificateVerify record. - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleCertificateVerify = function(c, record, length) { - if(length < 2) { - return c.error(c, { - message: 'Invalid CertificateVerify. Message too short.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.illegal_parameter - } - }); - } - - // rewind to get full bytes for message so it can be manually - // digested below (special case for CertificateVerify messages because - // they must be digested *after* handling as opposed to all others) - var b = record.fragment; - b.read -= 4; - var msgBytes = b.bytes(); - b.read += 4; - - var msg = { - signature: readVector(b, 2).getBytes() - }; - - // TODO: add support for DSA - - // generate data to verify - var verify = forge$9.util.createBuffer(); - verify.putBuffer(c.session.md5.digest()); - verify.putBuffer(c.session.sha1.digest()); - verify = verify.getBytes(); - - try { - var cert = c.session.clientCertificate; - /*b = forge.pki.rsa.decrypt( - msg.signature, cert.publicKey, true, verify.length); - if(b !== verify) {*/ - if(!cert.publicKey.verify(verify, msg.signature, 'NONE')) { - throw new Error('CertificateVerify signature does not match.'); - } - - // digest message now that it has been handled - c.session.md5.update(msgBytes); - c.session.sha1.update(msgBytes); - } catch(ex) { - return c.error(c, { - message: 'Bad signature in CertificateVerify.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.handshake_failure - } - }); - } - - // expect ChangeCipherSpec - c.expect = CCC; - - // continue - c.process(); -}; - -/** - * Called when a client receives a ServerHelloDone record. - * - * When this message will be sent: - * The server hello done message is sent by the server to indicate the end - * of the server hello and associated messages. After sending this message - * the server will wait for a client response. - * - * Meaning of this message: - * This message means that the server is done sending messages to support - * the key exchange, and the client can proceed with its phase of the key - * exchange. - * - * Upon receipt of the server hello done message the client should verify - * that the server provided a valid certificate if required and check that - * the server hello parameters are acceptable. - * - * struct {} ServerHelloDone; - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleServerHelloDone = function(c, record, length) { - // len must be 0 bytes - if(length > 0) { - return c.error(c, { - message: 'Invalid ServerHelloDone message. Invalid length.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.record_overflow - } - }); - } - - if(c.serverCertificate === null) { - // no server certificate was provided - var error = { - message: 'No server certificate provided. Not enough security.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.insufficient_security - } - }; - - // call application callback - var depth = 0; - var ret = c.verify(c, error.alert.description, depth, []); - if(ret !== true) { - // check for custom alert info - if(ret || ret === 0) { - // set custom message and alert description - if(typeof ret === 'object' && !forge$9.util.isArray(ret)) { - if(ret.message) { - error.message = ret.message; - } - if(ret.alert) { - error.alert.description = ret.alert; - } - } else if(typeof ret === 'number') { - // set custom alert description - error.alert.description = ret; - } - } - - // send error - return c.error(c, error); - } - } - - // create client certificate message if requested - if(c.session.certificateRequest !== null) { - record = tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createCertificate(c) - }); - tls$1.queue(c, record); - } - - // create client key exchange message - record = tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createClientKeyExchange(c) - }); - tls$1.queue(c, record); - - // expect no messages until the following callback has been called - c.expect = SER; - - // create callback to handle client signature (for client-certs) - var callback = function(c, signature) { - if(c.session.certificateRequest !== null && - c.session.clientCertificate !== null) { - // create certificate verify message - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createCertificateVerify(c, signature) - })); - } - - // create change cipher spec message - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.change_cipher_spec, - data: tls$1.createChangeCipherSpec() - })); - - // create pending state - c.state.pending = tls$1.createConnectionState(c); - - // change current write state to pending write state - c.state.current.write = c.state.pending.write; - - // create finished message - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createFinished(c) - })); - - // expect a server ChangeCipherSpec message next - c.expect = SCC; - - // send records - tls$1.flush(c); - - // continue - c.process(); - }; - - // if there is no certificate request or no client certificate, do - // callback immediately - if(c.session.certificateRequest === null || - c.session.clientCertificate === null) { - return callback(c, null); - } - - // otherwise get the client signature - tls$1.getClientSignature(c, callback); -}; - -/** - * Called when a ChangeCipherSpec record is received. - * - * @param c the connection. - * @param record the record. - */ -tls$1.handleChangeCipherSpec = function(c, record) { - if(record.fragment.getByte() !== 0x01) { - return c.error(c, { - message: 'Invalid ChangeCipherSpec message received.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.illegal_parameter - } - }); - } - - // create pending state if: - // 1. Resuming session in client mode OR - // 2. NOT resuming session in server mode - var client = (c.entity === tls$1.ConnectionEnd.client); - if((c.session.resuming && client) || (!c.session.resuming && !client)) { - c.state.pending = tls$1.createConnectionState(c); - } - - // change current read state to pending read state - c.state.current.read = c.state.pending.read; - - // clear pending state if: - // 1. NOT resuming session in client mode OR - // 2. resuming a session in server mode - if((!c.session.resuming && client) || (c.session.resuming && !client)) { - c.state.pending = null; - } - - // expect a Finished record next - c.expect = client ? SFI : CFI; - - // continue - c.process(); -}; - -/** - * Called when a Finished record is received. - * - * When this message will be sent: - * A finished message is always sent immediately after a change - * cipher spec message to verify that the key exchange and - * authentication processes were successful. It is essential that a - * change cipher spec message be received between the other - * handshake messages and the Finished message. - * - * Meaning of this message: - * The finished message is the first protected with the just- - * negotiated algorithms, keys, and secrets. Recipients of finished - * messages must verify that the contents are correct. Once a side - * has sent its Finished message and received and validated the - * Finished message from its peer, it may begin to send and receive - * application data over the connection. - * - * struct { - * opaque verify_data[verify_data_length]; - * } Finished; - * - * verify_data - * PRF(master_secret, finished_label, Hash(handshake_messages)) - * [0..verify_data_length-1]; - * - * finished_label - * For Finished messages sent by the client, the string - * "client finished". For Finished messages sent by the server, the - * string "server finished". - * - * verify_data_length depends on the cipher suite. If it is not specified - * by the cipher suite, then it is 12. Versions of TLS < 1.2 always used - * 12 bytes. - * - * @param c the connection. - * @param record the record. - * @param length the length of the handshake message. - */ -tls$1.handleFinished = function(c, record, length) { - // rewind to get full bytes for message so it can be manually - // digested below (special case for Finished messages because they - // must be digested *after* handling as opposed to all others) - var b = record.fragment; - b.read -= 4; - var msgBytes = b.bytes(); - b.read += 4; - - // message contains only verify_data - var vd = record.fragment.getBytes(); - - // ensure verify data is correct - b = forge$9.util.createBuffer(); - b.putBuffer(c.session.md5.digest()); - b.putBuffer(c.session.sha1.digest()); - - // set label based on entity type - var client = (c.entity === tls$1.ConnectionEnd.client); - var label = client ? 'server finished' : 'client finished'; - - // TODO: determine prf function and verify length for TLS 1.2 - var sp = c.session.sp; - var vdl = 12; - var prf = prf_TLS1; - b = prf(sp.master_secret, label, b.getBytes(), vdl); - if(b.getBytes() !== vd) { - return c.error(c, { - message: 'Invalid verify_data in Finished message.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.decrypt_error - } - }); - } - - // digest finished message now that it has been handled - c.session.md5.update(msgBytes); - c.session.sha1.update(msgBytes); - - // resuming session as client or NOT resuming session as server - if((c.session.resuming && client) || (!c.session.resuming && !client)) { - // create change cipher spec message - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.change_cipher_spec, - data: tls$1.createChangeCipherSpec() - })); - - // change current write state to pending write state, clear pending - c.state.current.write = c.state.pending.write; - c.state.pending = null; - - // create finished message - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createFinished(c) - })); - } - - // expect application data next - c.expect = client ? SAD : CAD; - - // handshake complete - c.handshaking = false; - ++c.handshakes; - - // save access to peer certificate - c.peerCertificate = client ? - c.session.serverCertificate : c.session.clientCertificate; - - // send records - tls$1.flush(c); - - // now connected - c.isConnected = true; - c.connected(c); - - // continue - c.process(); -}; - -/** - * Called when an Alert record is received. - * - * @param c the connection. - * @param record the record. - */ -tls$1.handleAlert = function(c, record) { - // read alert - var b = record.fragment; - var alert = { - level: b.getByte(), - description: b.getByte() - }; - - // TODO: consider using a table? - // get appropriate message - var msg; - switch(alert.description) { - case tls$1.Alert.Description.close_notify: - msg = 'Connection closed.'; - break; - case tls$1.Alert.Description.unexpected_message: - msg = 'Unexpected message.'; - break; - case tls$1.Alert.Description.bad_record_mac: - msg = 'Bad record MAC.'; - break; - case tls$1.Alert.Description.decryption_failed: - msg = 'Decryption failed.'; - break; - case tls$1.Alert.Description.record_overflow: - msg = 'Record overflow.'; - break; - case tls$1.Alert.Description.decompression_failure: - msg = 'Decompression failed.'; - break; - case tls$1.Alert.Description.handshake_failure: - msg = 'Handshake failure.'; - break; - case tls$1.Alert.Description.bad_certificate: - msg = 'Bad certificate.'; - break; - case tls$1.Alert.Description.unsupported_certificate: - msg = 'Unsupported certificate.'; - break; - case tls$1.Alert.Description.certificate_revoked: - msg = 'Certificate revoked.'; - break; - case tls$1.Alert.Description.certificate_expired: - msg = 'Certificate expired.'; - break; - case tls$1.Alert.Description.certificate_unknown: - msg = 'Certificate unknown.'; - break; - case tls$1.Alert.Description.illegal_parameter: - msg = 'Illegal parameter.'; - break; - case tls$1.Alert.Description.unknown_ca: - msg = 'Unknown certificate authority.'; - break; - case tls$1.Alert.Description.access_denied: - msg = 'Access denied.'; - break; - case tls$1.Alert.Description.decode_error: - msg = 'Decode error.'; - break; - case tls$1.Alert.Description.decrypt_error: - msg = 'Decrypt error.'; - break; - case tls$1.Alert.Description.export_restriction: - msg = 'Export restriction.'; - break; - case tls$1.Alert.Description.protocol_version: - msg = 'Unsupported protocol version.'; - break; - case tls$1.Alert.Description.insufficient_security: - msg = 'Insufficient security.'; - break; - case tls$1.Alert.Description.internal_error: - msg = 'Internal error.'; - break; - case tls$1.Alert.Description.user_canceled: - msg = 'User canceled.'; - break; - case tls$1.Alert.Description.no_renegotiation: - msg = 'Renegotiation not supported.'; - break; - default: - msg = 'Unknown error.'; - break; - } - - // close connection on close_notify, not an error - if(alert.description === tls$1.Alert.Description.close_notify) { - return c.close(); - } - - // call error handler - c.error(c, { - message: msg, - send: false, - // origin is the opposite end - origin: (c.entity === tls$1.ConnectionEnd.client) ? 'server' : 'client', - alert: alert - }); - - // continue - c.process(); -}; - -/** - * Called when a Handshake record is received. - * - * @param c the connection. - * @param record the record. - */ -tls$1.handleHandshake = function(c, record) { - // get the handshake type and message length - var b = record.fragment; - var type = b.getByte(); - var length = b.getInt24(); - - // see if the record fragment doesn't yet contain the full message - if(length > b.length()) { - // cache the record, clear its fragment, and reset the buffer read - // pointer before the type and length were read - c.fragmented = record; - record.fragment = forge$9.util.createBuffer(); - b.read -= 4; - - // continue - return c.process(); - } - - // full message now available, clear cache, reset read pointer to - // before type and length - c.fragmented = null; - b.read -= 4; - - // save the handshake bytes for digestion after handler is found - // (include type and length of handshake msg) - var bytes = b.bytes(length + 4); - - // restore read pointer - b.read += 4; - - // handle expected message - if(type in hsTable[c.entity][c.expect]) { - // initialize server session - if(c.entity === tls$1.ConnectionEnd.server && !c.open && !c.fail) { - c.handshaking = true; - c.session = { - version: null, - extensions: { - server_name: { - serverNameList: [] - } - }, - cipherSuite: null, - compressionMethod: null, - serverCertificate: null, - clientCertificate: null, - md5: forge$9.md.md5.create(), - sha1: forge$9.md.sha1.create() - }; - } - - /* Update handshake messages digest. Finished and CertificateVerify - messages are not digested here. They can't be digested as part of - the verify_data that they contain. These messages are manually - digested in their handlers. HelloRequest messages are simply never - included in the handshake message digest according to spec. */ - if(type !== tls$1.HandshakeType.hello_request && - type !== tls$1.HandshakeType.certificate_verify && - type !== tls$1.HandshakeType.finished) { - c.session.md5.update(bytes); - c.session.sha1.update(bytes); - } - - // handle specific handshake type record - hsTable[c.entity][c.expect][type](c, record, length); - } else { - // unexpected record - tls$1.handleUnexpected(c, record); - } -}; - -/** - * Called when an ApplicationData record is received. - * - * @param c the connection. - * @param record the record. - */ -tls$1.handleApplicationData = function(c, record) { - // buffer data, notify that its ready - c.data.putBuffer(record.fragment); - c.dataReady(c); - - // continue - c.process(); -}; - -/** - * Called when a Heartbeat record is received. - * - * @param c the connection. - * @param record the record. - */ -tls$1.handleHeartbeat = function(c, record) { - // get the heartbeat type and payload - var b = record.fragment; - var type = b.getByte(); - var length = b.getInt16(); - var payload = b.getBytes(length); - - if(type === tls$1.HeartbeatMessageType.heartbeat_request) { - // discard request during handshake or if length is too large - if(c.handshaking || length > payload.length) { - // continue - return c.process(); - } - // retransmit payload - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.heartbeat, - data: tls$1.createHeartbeat( - tls$1.HeartbeatMessageType.heartbeat_response, payload) - })); - tls$1.flush(c); - } else if(type === tls$1.HeartbeatMessageType.heartbeat_response) { - // check payload against expected payload, discard heartbeat if no match - if(payload !== c.expectedHeartbeatPayload) { - // continue - return c.process(); - } - - // notify that a valid heartbeat was received - if(c.heartbeatReceived) { - c.heartbeatReceived(c, forge$9.util.createBuffer(payload)); - } - } - - // continue - c.process(); -}; - -/** - * The transistional state tables for receiving TLS records. It maps the - * current TLS engine state and a received record to a function to handle the - * record and update the state. - * - * For instance, if the current state is SHE, then the TLS engine is expecting - * a ServerHello record. Once a record is received, the handler function is - * looked up using the state SHE and the record's content type. - * - * The resulting function will either be an error handler or a record handler. - * The function will take whatever action is appropriate and update the state - * for the next record. - * - * The states are all based on possible server record types. Note that the - * client will never specifically expect to receive a HelloRequest or an alert - * from the server so there is no state that reflects this. These messages may - * occur at any time. - * - * There are two tables for mapping states because there is a second tier of - * types for handshake messages. Once a record with a content type of handshake - * is received, the handshake record handler will look up the handshake type in - * the secondary map to get its appropriate handler. - * - * Valid message orders are as follows: - * - * =======================FULL HANDSHAKE====================== - * Client Server - * - * ClientHello --------> - * ServerHello - * Certificate* - * ServerKeyExchange* - * CertificateRequest* - * <-------- ServerHelloDone - * Certificate* - * ClientKeyExchange - * CertificateVerify* - * [ChangeCipherSpec] - * Finished --------> - * [ChangeCipherSpec] - * <-------- Finished - * Application Data <-------> Application Data - * - * =====================SESSION RESUMPTION===================== - * Client Server - * - * ClientHello --------> - * ServerHello - * [ChangeCipherSpec] - * <-------- Finished - * [ChangeCipherSpec] - * Finished --------> - * Application Data <-------> Application Data - */ -// client expect states (indicate which records are expected to be received) -var SHE = 0; // rcv server hello -var SCE = 1; // rcv server certificate -var SKE = 2; // rcv server key exchange -var SCR = 3; // rcv certificate request -var SHD = 4; // rcv server hello done -var SCC = 5; // rcv change cipher spec -var SFI = 6; // rcv finished -var SAD = 7; // rcv application data -var SER = 8; // not expecting any messages at this point - -// server expect states -var CHE = 0; // rcv client hello -var CCE = 1; // rcv client certificate -var CKE = 2; // rcv client key exchange -var CCV = 3; // rcv certificate verify -var CCC = 4; // rcv change cipher spec -var CFI = 5; // rcv finished -var CAD = 6; // rcv application data - -// map client current expect state and content type to function -var __ = tls$1.handleUnexpected; -var R0 = tls$1.handleChangeCipherSpec; -var R1 = tls$1.handleAlert; -var R2 = tls$1.handleHandshake; -var R3 = tls$1.handleApplicationData; -var R4 = tls$1.handleHeartbeat; -var ctTable = []; -ctTable[tls$1.ConnectionEnd.client] = [ -// CC,AL,HS,AD,HB -/*SHE*/[__,R1,R2,__,R4], -/*SCE*/[__,R1,R2,__,R4], -/*SKE*/[__,R1,R2,__,R4], -/*SCR*/[__,R1,R2,__,R4], -/*SHD*/[__,R1,R2,__,R4], -/*SCC*/[R0,R1,__,__,R4], -/*SFI*/[__,R1,R2,__,R4], -/*SAD*/[__,R1,R2,R3,R4], -/*SER*/[__,R1,R2,__,R4] -]; - -// map server current expect state and content type to function -ctTable[tls$1.ConnectionEnd.server] = [ -// CC,AL,HS,AD -/*CHE*/[__,R1,R2,__,R4], -/*CCE*/[__,R1,R2,__,R4], -/*CKE*/[__,R1,R2,__,R4], -/*CCV*/[__,R1,R2,__,R4], -/*CCC*/[R0,R1,__,__,R4], -/*CFI*/[__,R1,R2,__,R4], -/*CAD*/[__,R1,R2,R3,R4], -/*CER*/[__,R1,R2,__,R4] -]; - -// map client current expect state and handshake type to function -var H0 = tls$1.handleHelloRequest; -var H1 = tls$1.handleServerHello; -var H2 = tls$1.handleCertificate; -var H3 = tls$1.handleServerKeyExchange; -var H4 = tls$1.handleCertificateRequest; -var H5 = tls$1.handleServerHelloDone; -var H6 = tls$1.handleFinished; -var hsTable = []; -hsTable[tls$1.ConnectionEnd.client] = [ -// HR,01,SH,03,04,05,06,07,08,09,10,SC,SK,CR,HD,15,CK,17,18,19,FI -/*SHE*/[__,__,H1,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], -/*SCE*/[H0,__,__,__,__,__,__,__,__,__,__,H2,H3,H4,H5,__,__,__,__,__,__], -/*SKE*/[H0,__,__,__,__,__,__,__,__,__,__,__,H3,H4,H5,__,__,__,__,__,__], -/*SCR*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,H4,H5,__,__,__,__,__,__], -/*SHD*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,H5,__,__,__,__,__,__], -/*SCC*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], -/*SFI*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H6], -/*SAD*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], -/*SER*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__] -]; - -// map server current expect state and handshake type to function -// Note: CAD[CH] does not map to FB because renegotation is prohibited -var H7 = tls$1.handleClientHello; -var H8 = tls$1.handleClientKeyExchange; -var H9 = tls$1.handleCertificateVerify; -hsTable[tls$1.ConnectionEnd.server] = [ -// 01,CH,02,03,04,05,06,07,08,09,10,CC,12,13,14,CV,CK,17,18,19,FI -/*CHE*/[__,H7,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], -/*CCE*/[__,__,__,__,__,__,__,__,__,__,__,H2,__,__,__,__,__,__,__,__,__], -/*CKE*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H8,__,__,__,__], -/*CCV*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H9,__,__,__,__,__], -/*CCC*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], -/*CFI*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H6], -/*CAD*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], -/*CER*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__] -]; - -/** - * Generates the master_secret and keys using the given security parameters. - * - * The security parameters for a TLS connection state are defined as such: - * - * struct { - * ConnectionEnd entity; - * PRFAlgorithm prf_algorithm; - * BulkCipherAlgorithm bulk_cipher_algorithm; - * CipherType cipher_type; - * uint8 enc_key_length; - * uint8 block_length; - * uint8 fixed_iv_length; - * uint8 record_iv_length; - * MACAlgorithm mac_algorithm; - * uint8 mac_length; - * uint8 mac_key_length; - * CompressionMethod compression_algorithm; - * opaque master_secret[48]; - * opaque client_random[32]; - * opaque server_random[32]; - * } SecurityParameters; - * - * Note that this definition is from TLS 1.2. In TLS 1.0 some of these - * parameters are ignored because, for instance, the PRFAlgorithm is a - * builtin-fixed algorithm combining iterations of MD5 and SHA-1 in TLS 1.0. - * - * The Record Protocol requires an algorithm to generate keys required by the - * current connection state. - * - * The master secret is expanded into a sequence of secure bytes, which is then - * split to a client write MAC key, a server write MAC key, a client write - * encryption key, and a server write encryption key. In TLS 1.0 a client write - * IV and server write IV are also generated. Each of these is generated from - * the byte sequence in that order. Unused values are empty. In TLS 1.2, some - * AEAD ciphers may additionally require a client write IV and a server write - * IV (see Section 6.2.3.3). - * - * When keys, MAC keys, and IVs are generated, the master secret is used as an - * entropy source. - * - * To generate the key material, compute: - * - * master_secret = PRF(pre_master_secret, "master secret", - * ClientHello.random + ServerHello.random) - * - * key_block = PRF(SecurityParameters.master_secret, - * "key expansion", - * SecurityParameters.server_random + - * SecurityParameters.client_random); - * - * until enough output has been generated. Then, the key_block is - * partitioned as follows: - * - * client_write_MAC_key[SecurityParameters.mac_key_length] - * server_write_MAC_key[SecurityParameters.mac_key_length] - * client_write_key[SecurityParameters.enc_key_length] - * server_write_key[SecurityParameters.enc_key_length] - * client_write_IV[SecurityParameters.fixed_iv_length] - * server_write_IV[SecurityParameters.fixed_iv_length] - * - * In TLS 1.2, the client_write_IV and server_write_IV are only generated for - * implicit nonce techniques as described in Section 3.2.1 of [AEAD]. This - * implementation uses TLS 1.0 so IVs are generated. - * - * Implementation note: The currently defined cipher suite which requires the - * most material is AES_256_CBC_SHA256. It requires 2 x 32 byte keys and 2 x 32 - * byte MAC keys, for a total 128 bytes of key material. In TLS 1.0 it also - * requires 2 x 16 byte IVs, so it actually takes 160 bytes of key material. - * - * @param c the connection. - * @param sp the security parameters to use. - * - * @return the security keys. - */ -tls$1.generateKeys = function(c, sp) { - // TLS_RSA_WITH_AES_128_CBC_SHA (required to be compliant with TLS 1.2) & - // TLS_RSA_WITH_AES_256_CBC_SHA are the only cipher suites implemented - // at present - - // TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA is required to be compliant with - // TLS 1.0 but we don't care right now because AES is better and we have - // an implementation for it - - // TODO: TLS 1.2 implementation - /* - // determine the PRF - var prf; - switch(sp.prf_algorithm) { - case tls.PRFAlgorithm.tls_prf_sha256: - prf = prf_sha256; - break; - default: - // should never happen - throw new Error('Invalid PRF'); - } - */ - - // TLS 1.0/1.1 implementation - var prf = prf_TLS1; - - // concatenate server and client random - var random = sp.client_random + sp.server_random; - - // only create master secret if session is new - if(!c.session.resuming) { - // create master secret, clean up pre-master secret - sp.master_secret = prf( - sp.pre_master_secret, 'master secret', random, 48).bytes(); - sp.pre_master_secret = null; - } - - // generate the amount of key material needed - random = sp.server_random + sp.client_random; - var length = 2 * sp.mac_key_length + 2 * sp.enc_key_length; - - // include IV for TLS/1.0 - var tls10 = (c.version.major === tls$1.Versions.TLS_1_0.major && - c.version.minor === tls$1.Versions.TLS_1_0.minor); - if(tls10) { - length += 2 * sp.fixed_iv_length; - } - var km = prf(sp.master_secret, 'key expansion', random, length); - - // split the key material into the MAC and encryption keys - var rval = { - client_write_MAC_key: km.getBytes(sp.mac_key_length), - server_write_MAC_key: km.getBytes(sp.mac_key_length), - client_write_key: km.getBytes(sp.enc_key_length), - server_write_key: km.getBytes(sp.enc_key_length) - }; - - // include TLS 1.0 IVs - if(tls10) { - rval.client_write_IV = km.getBytes(sp.fixed_iv_length); - rval.server_write_IV = km.getBytes(sp.fixed_iv_length); - } - - return rval; -}; - -/** - * Creates a new initialized TLS connection state. A connection state has - * a read mode and a write mode. - * - * compression state: - * The current state of the compression algorithm. - * - * cipher state: - * The current state of the encryption algorithm. This will consist of the - * scheduled key for that connection. For stream ciphers, this will also - * contain whatever state information is necessary to allow the stream to - * continue to encrypt or decrypt data. - * - * MAC key: - * The MAC key for the connection. - * - * sequence number: - * Each connection state contains a sequence number, which is maintained - * separately for read and write states. The sequence number MUST be set to - * zero whenever a connection state is made the active state. Sequence - * numbers are of type uint64 and may not exceed 2^64-1. Sequence numbers do - * not wrap. If a TLS implementation would need to wrap a sequence number, - * it must renegotiate instead. A sequence number is incremented after each - * record: specifically, the first record transmitted under a particular - * connection state MUST use sequence number 0. - * - * @param c the connection. - * - * @return the new initialized TLS connection state. - */ -tls$1.createConnectionState = function(c) { - var client = (c.entity === tls$1.ConnectionEnd.client); - - var createMode = function() { - var mode = { - // two 32-bit numbers, first is most significant - sequenceNumber: [0, 0], - macKey: null, - macLength: 0, - macFunction: null, - cipherState: null, - cipherFunction: function(record) {return true;}, - compressionState: null, - compressFunction: function(record) {return true;}, - updateSequenceNumber: function() { - if(mode.sequenceNumber[1] === 0xFFFFFFFF) { - mode.sequenceNumber[1] = 0; - ++mode.sequenceNumber[0]; - } else { - ++mode.sequenceNumber[1]; - } - } - }; - return mode; - }; - var state = { - read: createMode(), - write: createMode() - }; - - // update function in read mode will decrypt then decompress a record - state.read.update = function(c, record) { - if(!state.read.cipherFunction(record, state.read)) { - c.error(c, { - message: 'Could not decrypt record or bad MAC.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - // doesn't matter if decryption failed or MAC was - // invalid, return the same error so as not to reveal - // which one occurred - description: tls$1.Alert.Description.bad_record_mac - } - }); - } else if(!state.read.compressFunction(c, record, state.read)) { - c.error(c, { - message: 'Could not decompress record.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.decompression_failure - } - }); - } - return !c.fail; - }; - - // update function in write mode will compress then encrypt a record - state.write.update = function(c, record) { - if(!state.write.compressFunction(c, record, state.write)) { - // error, but do not send alert since it would require - // compression as well - c.error(c, { - message: 'Could not compress record.', - send: false, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.internal_error - } - }); - } else if(!state.write.cipherFunction(record, state.write)) { - // error, but do not send alert since it would require - // encryption as well - c.error(c, { - message: 'Could not encrypt record.', - send: false, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.internal_error - } - }); - } - return !c.fail; - }; - - // handle security parameters - if(c.session) { - var sp = c.session.sp; - c.session.cipherSuite.initSecurityParameters(sp); - - // generate keys - sp.keys = tls$1.generateKeys(c, sp); - state.read.macKey = client ? - sp.keys.server_write_MAC_key : sp.keys.client_write_MAC_key; - state.write.macKey = client ? - sp.keys.client_write_MAC_key : sp.keys.server_write_MAC_key; - - // cipher suite setup - c.session.cipherSuite.initConnectionState(state, c, sp); - - // compression setup - switch(sp.compression_algorithm) { - case tls$1.CompressionMethod.none: - break; - case tls$1.CompressionMethod.deflate: - state.read.compressFunction = inflate; - state.write.compressFunction = deflate; - break; - default: - throw new Error('Unsupported compression algorithm.'); - } - } - - return state; -}; - -/** - * Creates a Random structure. - * - * struct { - * uint32 gmt_unix_time; - * opaque random_bytes[28]; - * } Random; - * - * gmt_unix_time: - * The current time and date in standard UNIX 32-bit format (seconds since - * the midnight starting Jan 1, 1970, UTC, ignoring leap seconds) according - * to the sender's internal clock. Clocks are not required to be set - * correctly by the basic TLS protocol; higher-level or application - * protocols may define additional requirements. Note that, for historical - * reasons, the data element is named using GMT, the predecessor of the - * current worldwide time base, UTC. - * random_bytes: - * 28 bytes generated by a secure random number generator. - * - * @return the Random structure as a byte array. - */ -tls$1.createRandom = function() { - // get UTC milliseconds - var d = new Date(); - var utc = +d + d.getTimezoneOffset() * 60000; - var rval = forge$9.util.createBuffer(); - rval.putInt32(utc); - rval.putBytes(forge$9.random.getBytes(28)); - return rval; -}; - -/** - * Creates a TLS record with the given type and data. - * - * @param c the connection. - * @param options: - * type: the record type. - * data: the plain text data in a byte buffer. - * - * @return the created record. - */ -tls$1.createRecord = function(c, options) { - if(!options.data) { - return null; - } - var record = { - type: options.type, - version: { - major: c.version.major, - minor: c.version.minor - }, - length: options.data.length(), - fragment: options.data - }; - return record; -}; - -/** - * Creates a TLS alert record. - * - * @param c the connection. - * @param alert: - * level: the TLS alert level. - * description: the TLS alert description. - * - * @return the created alert record. - */ -tls$1.createAlert = function(c, alert) { - var b = forge$9.util.createBuffer(); - b.putByte(alert.level); - b.putByte(alert.description); - return tls$1.createRecord(c, { - type: tls$1.ContentType.alert, - data: b - }); -}; - -/* The structure of a TLS handshake message. - * - * struct { - * HandshakeType msg_type; // handshake type - * uint24 length; // bytes in message - * select(HandshakeType) { - * case hello_request: HelloRequest; - * case client_hello: ClientHello; - * case server_hello: ServerHello; - * case certificate: Certificate; - * case server_key_exchange: ServerKeyExchange; - * case certificate_request: CertificateRequest; - * case server_hello_done: ServerHelloDone; - * case certificate_verify: CertificateVerify; - * case client_key_exchange: ClientKeyExchange; - * case finished: Finished; - * } body; - * } Handshake; - */ - -/** - * Creates a ClientHello message. - * - * opaque SessionID<0..32>; - * enum { null(0), deflate(1), (255) } CompressionMethod; - * uint8 CipherSuite[2]; - * - * struct { - * ProtocolVersion client_version; - * Random random; - * SessionID session_id; - * CipherSuite cipher_suites<2..2^16-2>; - * CompressionMethod compression_methods<1..2^8-1>; - * select(extensions_present) { - * case false: - * struct {}; - * case true: - * Extension extensions<0..2^16-1>; - * }; - * } ClientHello; - * - * The extension format for extended client hellos and server hellos is: - * - * struct { - * ExtensionType extension_type; - * opaque extension_data<0..2^16-1>; - * } Extension; - * - * Here: - * - * - "extension_type" identifies the particular extension type. - * - "extension_data" contains information specific to the particular - * extension type. - * - * The extension types defined in this document are: - * - * enum { - * server_name(0), max_fragment_length(1), - * client_certificate_url(2), trusted_ca_keys(3), - * truncated_hmac(4), status_request(5), (65535) - * } ExtensionType; - * - * @param c the connection. - * - * @return the ClientHello byte buffer. - */ -tls$1.createClientHello = function(c) { - // save hello version - c.session.clientHelloVersion = { - major: c.version.major, - minor: c.version.minor - }; - - // create supported cipher suites - var cipherSuites = forge$9.util.createBuffer(); - for(var i = 0; i < c.cipherSuites.length; ++i) { - var cs = c.cipherSuites[i]; - cipherSuites.putByte(cs.id[0]); - cipherSuites.putByte(cs.id[1]); - } - var cSuites = cipherSuites.length(); - - // create supported compression methods, null always supported, but - // also support deflate if connection has inflate and deflate methods - var compressionMethods = forge$9.util.createBuffer(); - compressionMethods.putByte(tls$1.CompressionMethod.none); - // FIXME: deflate support disabled until issues with raw deflate data - // without zlib headers are resolved - /* - if(c.inflate !== null && c.deflate !== null) { - compressionMethods.putByte(tls.CompressionMethod.deflate); - } - */ - var cMethods = compressionMethods.length(); - - // create TLS SNI (server name indication) extension if virtual host - // has been specified, see RFC 3546 - var extensions = forge$9.util.createBuffer(); - if(c.virtualHost) { - // create extension struct - var ext = forge$9.util.createBuffer(); - ext.putByte(0x00); // type server_name (ExtensionType is 2 bytes) - ext.putByte(0x00); - - /* In order to provide the server name, clients MAY include an - * extension of type "server_name" in the (extended) client hello. - * The "extension_data" field of this extension SHALL contain - * "ServerNameList" where: - * - * struct { - * NameType name_type; - * select(name_type) { - * case host_name: HostName; - * } name; - * } ServerName; - * - * enum { - * host_name(0), (255) - * } NameType; - * - * opaque HostName<1..2^16-1>; - * - * struct { - * ServerName server_name_list<1..2^16-1> - * } ServerNameList; - */ - var serverName = forge$9.util.createBuffer(); - serverName.putByte(0x00); // type host_name - writeVector(serverName, 2, forge$9.util.createBuffer(c.virtualHost)); - - // ServerNameList is in extension_data - var snList = forge$9.util.createBuffer(); - writeVector(snList, 2, serverName); - writeVector(ext, 2, snList); - extensions.putBuffer(ext); - } - var extLength = extensions.length(); - if(extLength > 0) { - // add extension vector length - extLength += 2; - } - - // determine length of the handshake message - // cipher suites and compression methods size will need to be - // updated if more get added to the list - var sessionId = c.session.id; - var length = - sessionId.length + 1 + // session ID vector - 2 + // version (major + minor) - 4 + 28 + // random time and random bytes - 2 + cSuites + // cipher suites vector - 1 + cMethods + // compression methods vector - extLength; // extensions vector - - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(tls$1.HandshakeType.client_hello); - rval.putInt24(length); // handshake length - rval.putByte(c.version.major); // major version - rval.putByte(c.version.minor); // minor version - rval.putBytes(c.session.sp.client_random); // random time + bytes - writeVector(rval, 1, forge$9.util.createBuffer(sessionId)); - writeVector(rval, 2, cipherSuites); - writeVector(rval, 1, compressionMethods); - if(extLength > 0) { - writeVector(rval, 2, extensions); - } - return rval; -}; - -/** - * Creates a ServerHello message. - * - * @param c the connection. - * - * @return the ServerHello byte buffer. - */ -tls$1.createServerHello = function(c) { - // determine length of the handshake message - var sessionId = c.session.id; - var length = - sessionId.length + 1 + // session ID vector - 2 + // version (major + minor) - 4 + 28 + // random time and random bytes - 2 + // chosen cipher suite - 1; // chosen compression method - - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(tls$1.HandshakeType.server_hello); - rval.putInt24(length); // handshake length - rval.putByte(c.version.major); // major version - rval.putByte(c.version.minor); // minor version - rval.putBytes(c.session.sp.server_random); // random time + bytes - writeVector(rval, 1, forge$9.util.createBuffer(sessionId)); - rval.putByte(c.session.cipherSuite.id[0]); - rval.putByte(c.session.cipherSuite.id[1]); - rval.putByte(c.session.compressionMethod); - return rval; -}; - -/** - * Creates a Certificate message. - * - * When this message will be sent: - * This is the first message the client can send after receiving a server - * hello done message and the first message the server can send after - * sending a ServerHello. This client message is only sent if the server - * requests a certificate. If no suitable certificate is available, the - * client should send a certificate message containing no certificates. If - * client authentication is required by the server for the handshake to - * continue, it may respond with a fatal handshake failure alert. - * - * opaque ASN.1Cert<1..2^24-1>; - * - * struct { - * ASN.1Cert certificate_list<0..2^24-1>; - * } Certificate; - * - * @param c the connection. - * - * @return the Certificate byte buffer. - */ -tls$1.createCertificate = function(c) { - // TODO: check certificate request to ensure types are supported - - // get a certificate (a certificate as a PEM string) - var client = (c.entity === tls$1.ConnectionEnd.client); - var cert = null; - if(c.getCertificate) { - var hint; - if(client) { - hint = c.session.certificateRequest; - } else { - hint = c.session.extensions.server_name.serverNameList; - } - cert = c.getCertificate(c, hint); - } - - // buffer to hold certificate list - var certList = forge$9.util.createBuffer(); - if(cert !== null) { - try { - // normalize cert to a chain of certificates - if(!forge$9.util.isArray(cert)) { - cert = [cert]; - } - var asn1 = null; - for(var i = 0; i < cert.length; ++i) { - var msg = forge$9.pem.decode(cert[i])[0]; - if(msg.type !== 'CERTIFICATE' && - msg.type !== 'X509 CERTIFICATE' && - msg.type !== 'TRUSTED CERTIFICATE') { - var error = new Error('Could not convert certificate from PEM; PEM ' + - 'header type is not "CERTIFICATE", "X509 CERTIFICATE", or ' + - '"TRUSTED CERTIFICATE".'); - error.headerType = msg.type; - throw error; - } - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - throw new Error('Could not convert certificate from PEM; PEM is encrypted.'); - } - - var der = forge$9.util.createBuffer(msg.body); - if(asn1 === null) { - asn1 = forge$9.asn1.fromDer(der.bytes(), false); - } - - // certificate entry is itself a vector with 3 length bytes - var certBuffer = forge$9.util.createBuffer(); - writeVector(certBuffer, 3, der); - - // add cert vector to cert list vector - certList.putBuffer(certBuffer); - } - - // save certificate - cert = forge$9.pki.certificateFromAsn1(asn1); - if(client) { - c.session.clientCertificate = cert; - } else { - c.session.serverCertificate = cert; - } - } catch(ex) { - return c.error(c, { - message: 'Could not send certificate list.', - cause: ex, - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.bad_certificate - } - }); - } - } - - // determine length of the handshake message - var length = 3 + certList.length(); // cert list vector - - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(tls$1.HandshakeType.certificate); - rval.putInt24(length); - writeVector(rval, 3, certList); - return rval; -}; - -/** - * Creates a ClientKeyExchange message. - * - * When this message will be sent: - * This message is always sent by the client. It will immediately follow the - * client certificate message, if it is sent. Otherwise it will be the first - * message sent by the client after it receives the server hello done - * message. - * - * Meaning of this message: - * With this message, the premaster secret is set, either though direct - * transmission of the RSA-encrypted secret, or by the transmission of - * Diffie-Hellman parameters which will allow each side to agree upon the - * same premaster secret. When the key exchange method is DH_RSA or DH_DSS, - * client certification has been requested, and the client was able to - * respond with a certificate which contained a Diffie-Hellman public key - * whose parameters (group and generator) matched those specified by the - * server in its certificate, this message will not contain any data. - * - * Meaning of this message: - * If RSA is being used for key agreement and authentication, the client - * generates a 48-byte premaster secret, encrypts it using the public key - * from the server's certificate or the temporary RSA key provided in a - * server key exchange message, and sends the result in an encrypted - * premaster secret message. This structure is a variant of the client - * key exchange message, not a message in itself. - * - * struct { - * select(KeyExchangeAlgorithm) { - * case rsa: EncryptedPreMasterSecret; - * case diffie_hellman: ClientDiffieHellmanPublic; - * } exchange_keys; - * } ClientKeyExchange; - * - * struct { - * ProtocolVersion client_version; - * opaque random[46]; - * } PreMasterSecret; - * - * struct { - * public-key-encrypted PreMasterSecret pre_master_secret; - * } EncryptedPreMasterSecret; - * - * A public-key-encrypted element is encoded as a vector <0..2^16-1>. - * - * @param c the connection. - * - * @return the ClientKeyExchange byte buffer. - */ -tls$1.createClientKeyExchange = function(c) { - // create buffer to encrypt - var b = forge$9.util.createBuffer(); - - // add highest client-supported protocol to help server avoid version - // rollback attacks - b.putByte(c.session.clientHelloVersion.major); - b.putByte(c.session.clientHelloVersion.minor); - - // generate and add 46 random bytes - b.putBytes(forge$9.random.getBytes(46)); - - // save pre-master secret - var sp = c.session.sp; - sp.pre_master_secret = b.getBytes(); - - // RSA-encrypt the pre-master secret - var key = c.session.serverCertificate.publicKey; - b = key.encrypt(sp.pre_master_secret); - - /* Note: The encrypted pre-master secret will be stored in a - public-key-encrypted opaque vector that has the length prefixed using - 2 bytes, so include those 2 bytes in the handshake message length. This - is done as a minor optimization instead of calling writeVector(). */ - - // determine length of the handshake message - var length = b.length + 2; - - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(tls$1.HandshakeType.client_key_exchange); - rval.putInt24(length); - // add vector length bytes - rval.putInt16(b.length); - rval.putBytes(b); - return rval; -}; - -/** - * Creates a ServerKeyExchange message. - * - * @param c the connection. - * - * @return the ServerKeyExchange byte buffer. - */ -tls$1.createServerKeyExchange = function(c) { - - // build record fragment - var rval = forge$9.util.createBuffer(); - return rval; -}; - -/** - * Gets the signed data used to verify a client-side certificate. See - * tls.createCertificateVerify() for details. - * - * @param c the connection. - * @param callback the callback to call once the signed data is ready. - */ -tls$1.getClientSignature = function(c, callback) { - // generate data to RSA encrypt - var b = forge$9.util.createBuffer(); - b.putBuffer(c.session.md5.digest()); - b.putBuffer(c.session.sha1.digest()); - b = b.getBytes(); - - // create default signing function as necessary - c.getSignature = c.getSignature || function(c, b, callback) { - // do rsa encryption, call callback - var privateKey = null; - if(c.getPrivateKey) { - try { - privateKey = c.getPrivateKey(c, c.session.clientCertificate); - privateKey = forge$9.pki.privateKeyFromPem(privateKey); - } catch(ex) { - c.error(c, { - message: 'Could not get private key.', - cause: ex, - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.internal_error - } - }); - } - } - if(privateKey === null) { - c.error(c, { - message: 'No private key set.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.internal_error - } - }); - } else { - b = privateKey.sign(b, null); - } - callback(c, b); - }; - - // get client signature - c.getSignature(c, b, callback); -}; - -/** - * Creates a CertificateVerify message. - * - * Meaning of this message: - * This structure conveys the client's Diffie-Hellman public value - * (Yc) if it was not already included in the client's certificate. - * The encoding used for Yc is determined by the enumerated - * PublicValueEncoding. This structure is a variant of the client - * key exchange message, not a message in itself. - * - * When this message will be sent: - * This message is used to provide explicit verification of a client - * certificate. This message is only sent following a client - * certificate that has signing capability (i.e. all certificates - * except those containing fixed Diffie-Hellman parameters). When - * sent, it will immediately follow the client key exchange message. - * - * struct { - * Signature signature; - * } CertificateVerify; - * - * CertificateVerify.signature.md5_hash - * MD5(handshake_messages); - * - * Certificate.signature.sha_hash - * SHA(handshake_messages); - * - * Here handshake_messages refers to all handshake messages sent or - * received starting at client hello up to but not including this - * message, including the type and length fields of the handshake - * messages. - * - * select(SignatureAlgorithm) { - * case anonymous: struct { }; - * case rsa: - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * case dsa: - * digitally-signed struct { - * opaque sha_hash[20]; - * }; - * } Signature; - * - * In digital signing, one-way hash functions are used as input for a - * signing algorithm. A digitally-signed element is encoded as an opaque - * vector <0..2^16-1>, where the length is specified by the signing - * algorithm and key. - * - * In RSA signing, a 36-byte structure of two hashes (one SHA and one - * MD5) is signed (encrypted with the private key). It is encoded with - * PKCS #1 block type 0 or type 1 as described in [PKCS1]. - * - * In DSS, the 20 bytes of the SHA hash are run directly through the - * Digital Signing Algorithm with no additional hashing. - * - * @param c the connection. - * @param signature the signature to include in the message. - * - * @return the CertificateVerify byte buffer. - */ -tls$1.createCertificateVerify = function(c, signature) { - /* Note: The signature will be stored in a "digitally-signed" opaque - vector that has the length prefixed using 2 bytes, so include those - 2 bytes in the handshake message length. This is done as a minor - optimization instead of calling writeVector(). */ - - // determine length of the handshake message - var length = signature.length + 2; - - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(tls$1.HandshakeType.certificate_verify); - rval.putInt24(length); - // add vector length bytes - rval.putInt16(signature.length); - rval.putBytes(signature); - return rval; -}; - -/** - * Creates a CertificateRequest message. - * - * @param c the connection. - * - * @return the CertificateRequest byte buffer. - */ -tls$1.createCertificateRequest = function(c) { - // TODO: support other certificate types - var certTypes = forge$9.util.createBuffer(); - - // common RSA certificate type - certTypes.putByte(0x01); - - // add distinguished names from CA store - var cAs = forge$9.util.createBuffer(); - for(var key in c.caStore.certs) { - var cert = c.caStore.certs[key]; - var dn = forge$9.pki.distinguishedNameToAsn1(cert.subject); - var byteBuffer = forge$9.asn1.toDer(dn); - cAs.putInt16(byteBuffer.length()); - cAs.putBuffer(byteBuffer); - } - - // TODO: TLS 1.2+ has a different format - - // determine length of the handshake message - var length = - 1 + certTypes.length() + - 2 + cAs.length(); - - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(tls$1.HandshakeType.certificate_request); - rval.putInt24(length); - writeVector(rval, 1, certTypes); - writeVector(rval, 2, cAs); - return rval; -}; - -/** - * Creates a ServerHelloDone message. - * - * @param c the connection. - * - * @return the ServerHelloDone byte buffer. - */ -tls$1.createServerHelloDone = function(c) { - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(tls$1.HandshakeType.server_hello_done); - rval.putInt24(0); - return rval; -}; - -/** - * Creates a ChangeCipherSpec message. - * - * The change cipher spec protocol exists to signal transitions in - * ciphering strategies. The protocol consists of a single message, - * which is encrypted and compressed under the current (not the pending) - * connection state. The message consists of a single byte of value 1. - * - * struct { - * enum { change_cipher_spec(1), (255) } type; - * } ChangeCipherSpec; - * - * @return the ChangeCipherSpec byte buffer. - */ -tls$1.createChangeCipherSpec = function() { - var rval = forge$9.util.createBuffer(); - rval.putByte(0x01); - return rval; -}; - -/** - * Creates a Finished message. - * - * struct { - * opaque verify_data[12]; - * } Finished; - * - * verify_data - * PRF(master_secret, finished_label, MD5(handshake_messages) + - * SHA-1(handshake_messages)) [0..11]; - * - * finished_label - * For Finished messages sent by the client, the string "client - * finished". For Finished messages sent by the server, the - * string "server finished". - * - * handshake_messages - * All of the data from all handshake messages up to but not - * including this message. This is only data visible at the - * handshake layer and does not include record layer headers. - * This is the concatenation of all the Handshake structures as - * defined in 7.4 exchanged thus far. - * - * @param c the connection. - * - * @return the Finished byte buffer. - */ -tls$1.createFinished = function(c) { - // generate verify_data - var b = forge$9.util.createBuffer(); - b.putBuffer(c.session.md5.digest()); - b.putBuffer(c.session.sha1.digest()); - - // TODO: determine prf function and verify length for TLS 1.2 - var client = (c.entity === tls$1.ConnectionEnd.client); - var sp = c.session.sp; - var vdl = 12; - var prf = prf_TLS1; - var label = client ? 'client finished' : 'server finished'; - b = prf(sp.master_secret, label, b.getBytes(), vdl); - - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(tls$1.HandshakeType.finished); - rval.putInt24(b.length()); - rval.putBuffer(b); - return rval; -}; - -/** - * Creates a HeartbeatMessage (See RFC 6520). - * - * struct { - * HeartbeatMessageType type; - * uint16 payload_length; - * opaque payload[HeartbeatMessage.payload_length]; - * opaque padding[padding_length]; - * } HeartbeatMessage; - * - * The total length of a HeartbeatMessage MUST NOT exceed 2^14 or - * max_fragment_length when negotiated as defined in [RFC6066]. - * - * type: The message type, either heartbeat_request or heartbeat_response. - * - * payload_length: The length of the payload. - * - * payload: The payload consists of arbitrary content. - * - * padding: The padding is random content that MUST be ignored by the - * receiver. The length of a HeartbeatMessage is TLSPlaintext.length - * for TLS and DTLSPlaintext.length for DTLS. Furthermore, the - * length of the type field is 1 byte, and the length of the - * payload_length is 2. Therefore, the padding_length is - * TLSPlaintext.length - payload_length - 3 for TLS and - * DTLSPlaintext.length - payload_length - 3 for DTLS. The - * padding_length MUST be at least 16. - * - * The sender of a HeartbeatMessage MUST use a random padding of at - * least 16 bytes. The padding of a received HeartbeatMessage message - * MUST be ignored. - * - * If the payload_length of a received HeartbeatMessage is too large, - * the received HeartbeatMessage MUST be discarded silently. - * - * @param c the connection. - * @param type the tls.HeartbeatMessageType. - * @param payload the heartbeat data to send as the payload. - * @param [payloadLength] the payload length to use, defaults to the - * actual payload length. - * - * @return the HeartbeatRequest byte buffer. - */ -tls$1.createHeartbeat = function(type, payload, payloadLength) { - if(typeof payloadLength === 'undefined') { - payloadLength = payload.length; - } - // build record fragment - var rval = forge$9.util.createBuffer(); - rval.putByte(type); // heartbeat message type - rval.putInt16(payloadLength); // payload length - rval.putBytes(payload); // payload - // padding - var plaintextLength = rval.length(); - var paddingLength = Math.max(16, plaintextLength - payloadLength - 3); - rval.putBytes(forge$9.random.getBytes(paddingLength)); - return rval; -}; - -/** - * Fragments, compresses, encrypts, and queues a record for delivery. - * - * @param c the connection. - * @param record the record to queue. - */ -tls$1.queue = function(c, record) { - // error during record creation - if(!record) { - return; - } - - if(record.fragment.length() === 0) { - if(record.type === tls$1.ContentType.handshake || - record.type === tls$1.ContentType.alert || - record.type === tls$1.ContentType.change_cipher_spec) { - // Empty handshake, alert of change cipher spec messages are not allowed per the TLS specification and should not be sent. - return; - } - } - - // if the record is a handshake record, update handshake hashes - if(record.type === tls$1.ContentType.handshake) { - var bytes = record.fragment.bytes(); - c.session.md5.update(bytes); - c.session.sha1.update(bytes); - bytes = null; - } - - // handle record fragmentation - var records; - if(record.fragment.length() <= tls$1.MaxFragment) { - records = [record]; - } else { - // fragment data as long as it is too long - records = []; - var data = record.fragment.bytes(); - while(data.length > tls$1.MaxFragment) { - records.push(tls$1.createRecord(c, { - type: record.type, - data: forge$9.util.createBuffer(data.slice(0, tls$1.MaxFragment)) - })); - data = data.slice(tls$1.MaxFragment); - } - // add last record - if(data.length > 0) { - records.push(tls$1.createRecord(c, { - type: record.type, - data: forge$9.util.createBuffer(data) - })); - } - } - - // compress and encrypt all fragmented records - for(var i = 0; i < records.length && !c.fail; ++i) { - // update the record using current write state - var rec = records[i]; - var s = c.state.current.write; - if(s.update(c, rec)) { - // store record - c.records.push(rec); - } - } -}; - -/** - * Flushes all queued records to the output buffer and calls the - * tlsDataReady() handler on the given connection. - * - * @param c the connection. - * - * @return true on success, false on failure. - */ -tls$1.flush = function(c) { - for(var i = 0; i < c.records.length; ++i) { - var record = c.records[i]; - - // add record header and fragment - c.tlsData.putByte(record.type); - c.tlsData.putByte(record.version.major); - c.tlsData.putByte(record.version.minor); - c.tlsData.putInt16(record.fragment.length()); - c.tlsData.putBuffer(c.records[i].fragment); - } - c.records = []; - return c.tlsDataReady(c); -}; - -/** - * Maps a pki.certificateError to a tls.Alert.Description. - * - * @param error the error to map. - * - * @return the alert description. - */ -var _certErrorToAlertDesc = function(error) { - switch(error) { - case true: - return true; - case forge$9.pki.certificateError.bad_certificate: - return tls$1.Alert.Description.bad_certificate; - case forge$9.pki.certificateError.unsupported_certificate: - return tls$1.Alert.Description.unsupported_certificate; - case forge$9.pki.certificateError.certificate_revoked: - return tls$1.Alert.Description.certificate_revoked; - case forge$9.pki.certificateError.certificate_expired: - return tls$1.Alert.Description.certificate_expired; - case forge$9.pki.certificateError.certificate_unknown: - return tls$1.Alert.Description.certificate_unknown; - case forge$9.pki.certificateError.unknown_ca: - return tls$1.Alert.Description.unknown_ca; - default: - return tls$1.Alert.Description.bad_certificate; - } -}; - -/** - * Maps a tls.Alert.Description to a pki.certificateError. - * - * @param desc the alert description. - * - * @return the certificate error. - */ -var _alertDescToCertError = function(desc) { - switch(desc) { - case true: - return true; - case tls$1.Alert.Description.bad_certificate: - return forge$9.pki.certificateError.bad_certificate; - case tls$1.Alert.Description.unsupported_certificate: - return forge$9.pki.certificateError.unsupported_certificate; - case tls$1.Alert.Description.certificate_revoked: - return forge$9.pki.certificateError.certificate_revoked; - case tls$1.Alert.Description.certificate_expired: - return forge$9.pki.certificateError.certificate_expired; - case tls$1.Alert.Description.certificate_unknown: - return forge$9.pki.certificateError.certificate_unknown; - case tls$1.Alert.Description.unknown_ca: - return forge$9.pki.certificateError.unknown_ca; - default: - return forge$9.pki.certificateError.bad_certificate; - } -}; - -/** - * Verifies a certificate chain against the given connection's - * Certificate Authority store. - * - * @param c the TLS connection. - * @param chain the certificate chain to verify, with the root or highest - * authority at the end. - * - * @return true if successful, false if not. - */ -tls$1.verifyCertificateChain = function(c, chain) { - try { - // Make a copy of c.verifyOptions so that we can modify options.verify - // without modifying c.verifyOptions. - var options = {}; - for (var key in c.verifyOptions) { - options[key] = c.verifyOptions[key]; - } - - options.verify = function(vfd, depth, chain) { - // convert pki.certificateError to tls alert description - var desc = _certErrorToAlertDesc(vfd); - - // call application callback - var ret = c.verify(c, vfd, depth, chain); - if(ret !== true) { - if(typeof ret === 'object' && !forge$9.util.isArray(ret)) { - // throw custom error - var error = new Error('The application rejected the certificate.'); - error.send = true; - error.alert = { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.bad_certificate - }; - if(ret.message) { - error.message = ret.message; - } - if(ret.alert) { - error.alert.description = ret.alert; - } - throw error; - } - - // convert tls alert description to pki.certificateError - if(ret !== vfd) { - ret = _alertDescToCertError(ret); - } - } - - return ret; - }; - - // verify chain - forge$9.pki.verifyCertificateChain(c.caStore, chain, options); - } catch(ex) { - // build tls error if not already customized - var err = ex; - if(typeof err !== 'object' || forge$9.util.isArray(err)) { - err = { - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: _certErrorToAlertDesc(ex) - } - }; - } - if(!('send' in err)) { - err.send = true; - } - if(!('alert' in err)) { - err.alert = { - level: tls$1.Alert.Level.fatal, - description: _certErrorToAlertDesc(err.error) - }; - } - - // send error - c.error(c, err); - } - - return !c.fail; -}; - -/** - * Creates a new TLS session cache. - * - * @param cache optional map of session ID to cached session. - * @param capacity the maximum size for the cache (default: 100). - * - * @return the new TLS session cache. - */ -tls$1.createSessionCache = function(cache, capacity) { - var rval = null; - - // assume input is already a session cache object - if(cache && cache.getSession && cache.setSession && cache.order) { - rval = cache; - } else { - // create cache - rval = {}; - rval.cache = cache || {}; - rval.capacity = Math.max(capacity || 100, 1); - rval.order = []; - - // store order for sessions, delete session overflow - for(var key in cache) { - if(rval.order.length <= capacity) { - rval.order.push(key); - } else { - delete cache[key]; - } - } - - // get a session from a session ID (or get any session) - rval.getSession = function(sessionId) { - var session = null; - var key = null; - - // if session ID provided, use it - if(sessionId) { - key = forge$9.util.bytesToHex(sessionId); - } else if(rval.order.length > 0) { - // get first session from cache - key = rval.order[0]; - } - - if(key !== null && key in rval.cache) { - // get cached session and remove from cache - session = rval.cache[key]; - delete rval.cache[key]; - for(var i in rval.order) { - if(rval.order[i] === key) { - rval.order.splice(i, 1); - break; - } - } - } - - return session; - }; - - // set a session in the cache - rval.setSession = function(sessionId, session) { - // remove session from cache if at capacity - if(rval.order.length === rval.capacity) { - var key = rval.order.shift(); - delete rval.cache[key]; - } - // add session to cache - var key = forge$9.util.bytesToHex(sessionId); - rval.order.push(key); - rval.cache[key] = session; - }; - } - - return rval; -}; - -/** - * Creates a new TLS connection. - * - * See public createConnection() docs for more details. - * - * @param options the options for this connection. - * - * @return the new TLS connection. - */ -tls$1.createConnection = function(options) { - var caStore = null; - if(options.caStore) { - // if CA store is an array, convert it to a CA store object - if(forge$9.util.isArray(options.caStore)) { - caStore = forge$9.pki.createCaStore(options.caStore); - } else { - caStore = options.caStore; - } - } else { - // create empty CA store - caStore = forge$9.pki.createCaStore(); - } - - // setup default cipher suites - var cipherSuites = options.cipherSuites || null; - if(cipherSuites === null) { - cipherSuites = []; - for(var key in tls$1.CipherSuites) { - cipherSuites.push(tls$1.CipherSuites[key]); - } - } - - // set default entity - var entity = (options.server || false) ? - tls$1.ConnectionEnd.server : tls$1.ConnectionEnd.client; - - // create session cache if requested - var sessionCache = options.sessionCache ? - tls$1.createSessionCache(options.sessionCache) : null; - - // create TLS connection - var c = { - version: {major: tls$1.Version.major, minor: tls$1.Version.minor}, - entity: entity, - sessionId: options.sessionId, - caStore: caStore, - sessionCache: sessionCache, - cipherSuites: cipherSuites, - connected: options.connected, - virtualHost: options.virtualHost || null, - verifyClient: options.verifyClient || false, - verify: options.verify || function(cn, vfd, dpth, cts) {return vfd;}, - verifyOptions: options.verifyOptions || {}, - getCertificate: options.getCertificate || null, - getPrivateKey: options.getPrivateKey || null, - getSignature: options.getSignature || null, - input: forge$9.util.createBuffer(), - tlsData: forge$9.util.createBuffer(), - data: forge$9.util.createBuffer(), - tlsDataReady: options.tlsDataReady, - dataReady: options.dataReady, - heartbeatReceived: options.heartbeatReceived, - closed: options.closed, - error: function(c, ex) { - // set origin if not set - ex.origin = ex.origin || - ((c.entity === tls$1.ConnectionEnd.client) ? 'client' : 'server'); - - // send TLS alert - if(ex.send) { - tls$1.queue(c, tls$1.createAlert(c, ex.alert)); - tls$1.flush(c); - } - - // error is fatal by default - var fatal = (ex.fatal !== false); - if(fatal) { - // set fail flag - c.fail = true; - } - - // call error handler first - options.error(c, ex); - - if(fatal) { - // fatal error, close connection, do not clear fail - c.close(false); - } - }, - deflate: options.deflate || null, - inflate: options.inflate || null - }; - - /** - * Resets a closed TLS connection for reuse. Called in c.close(). - * - * @param clearFail true to clear the fail flag (default: true). - */ - c.reset = function(clearFail) { - c.version = {major: tls$1.Version.major, minor: tls$1.Version.minor}; - c.record = null; - c.session = null; - c.peerCertificate = null; - c.state = { - pending: null, - current: null - }; - c.expect = (c.entity === tls$1.ConnectionEnd.client) ? SHE : CHE; - c.fragmented = null; - c.records = []; - c.open = false; - c.handshakes = 0; - c.handshaking = false; - c.isConnected = false; - c.fail = !(clearFail || typeof(clearFail) === 'undefined'); - c.input.clear(); - c.tlsData.clear(); - c.data.clear(); - c.state.current = tls$1.createConnectionState(c); - }; - - // do initial reset of connection - c.reset(); - - /** - * Updates the current TLS engine state based on the given record. - * - * @param c the TLS connection. - * @param record the TLS record to act on. - */ - var _update = function(c, record) { - // get record handler (align type in table by subtracting lowest) - var aligned = record.type - tls$1.ContentType.change_cipher_spec; - var handlers = ctTable[c.entity][c.expect]; - if(aligned in handlers) { - handlers[aligned](c, record); - } else { - // unexpected record - tls$1.handleUnexpected(c, record); - } - }; - - /** - * Reads the record header and initializes the next record on the given - * connection. - * - * @param c the TLS connection with the next record. - * - * @return 0 if the input data could be processed, otherwise the - * number of bytes required for data to be processed. - */ - var _readRecordHeader = function(c) { - var rval = 0; - - // get input buffer and its length - var b = c.input; - var len = b.length(); - - // need at least 5 bytes to initialize a record - if(len < 5) { - rval = 5 - len; - } else { - // enough bytes for header - // initialize record - c.record = { - type: b.getByte(), - version: { - major: b.getByte(), - minor: b.getByte() - }, - length: b.getInt16(), - fragment: forge$9.util.createBuffer(), - ready: false - }; - - // check record version - var compatibleVersion = (c.record.version.major === c.version.major); - if(compatibleVersion && c.session && c.session.version) { - // session version already set, require same minor version - compatibleVersion = (c.record.version.minor === c.version.minor); - } - if(!compatibleVersion) { - c.error(c, { - message: 'Incompatible TLS version.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: tls$1.Alert.Description.protocol_version - } - }); - } - } - - return rval; - }; - - /** - * Reads the next record's contents and appends its message to any - * previously fragmented message. - * - * @param c the TLS connection with the next record. - * - * @return 0 if the input data could be processed, otherwise the - * number of bytes required for data to be processed. - */ - var _readRecord = function(c) { - var rval = 0; - - // ensure there is enough input data to get the entire record - var b = c.input; - var len = b.length(); - if(len < c.record.length) { - // not enough data yet, return how much is required - rval = c.record.length - len; - } else { - // there is enough data to parse the pending record - // fill record fragment and compact input buffer - c.record.fragment.putBytes(b.getBytes(c.record.length)); - b.compact(); - - // update record using current read state - var s = c.state.current.read; - if(s.update(c, c.record)) { - // see if there is a previously fragmented message that the - // new record's message fragment should be appended to - if(c.fragmented !== null) { - // if the record type matches a previously fragmented - // record, append the record fragment to it - if(c.fragmented.type === c.record.type) { - // concatenate record fragments - c.fragmented.fragment.putBuffer(c.record.fragment); - c.record = c.fragmented; - } else { - // error, invalid fragmented record - c.error(c, { - message: 'Invalid fragmented record.', - send: true, - alert: { - level: tls$1.Alert.Level.fatal, - description: - tls$1.Alert.Description.unexpected_message - } - }); - } - } - - // record is now ready - c.record.ready = true; - } - } - - return rval; - }; - - /** - * Performs a handshake using the TLS Handshake Protocol, as a client. - * - * This method should only be called if the connection is in client mode. - * - * @param sessionId the session ID to use, null to start a new one. - */ - c.handshake = function(sessionId) { - // error to call this in non-client mode - if(c.entity !== tls$1.ConnectionEnd.client) { - // not fatal error - c.error(c, { - message: 'Cannot initiate handshake as a server.', - fatal: false - }); - } else if(c.handshaking) { - // handshake is already in progress, fail but not fatal error - c.error(c, { - message: 'Handshake already in progress.', - fatal: false - }); - } else { - // clear fail flag on reuse - if(c.fail && !c.open && c.handshakes === 0) { - c.fail = false; - } - - // now handshaking - c.handshaking = true; - - // default to blank (new session) - sessionId = sessionId || ''; - - // if a session ID was specified, try to find it in the cache - var session = null; - if(sessionId.length > 0) { - if(c.sessionCache) { - session = c.sessionCache.getSession(sessionId); - } - - // matching session not found in cache, clear session ID - if(session === null) { - sessionId = ''; - } - } - - // no session given, grab a session from the cache, if available - if(sessionId.length === 0 && c.sessionCache) { - session = c.sessionCache.getSession(); - if(session !== null) { - sessionId = session.id; - } - } - - // set up session - c.session = { - id: sessionId, - version: null, - cipherSuite: null, - compressionMethod: null, - serverCertificate: null, - certificateRequest: null, - clientCertificate: null, - sp: {}, - md5: forge$9.md.md5.create(), - sha1: forge$9.md.sha1.create() - }; - - // use existing session information - if(session) { - // only update version on connection, session version not yet set - c.version = session.version; - c.session.sp = session.sp; - } - - // generate new client random - c.session.sp.client_random = tls$1.createRandom().getBytes(); - - // connection now open - c.open = true; - - // send hello - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.handshake, - data: tls$1.createClientHello(c) - })); - tls$1.flush(c); - } - }; - - /** - * Called when TLS protocol data has been received from somewhere and should - * be processed by the TLS engine. - * - * @param data the TLS protocol data, as a string, to process. - * - * @return 0 if the data could be processed, otherwise the number of bytes - * required for data to be processed. - */ - c.process = function(data) { - var rval = 0; - - // buffer input data - if(data) { - c.input.putBytes(data); - } - - // process next record if no failure, process will be called after - // each record is handled (since handling can be asynchronous) - if(!c.fail) { - // reset record if ready and now empty - if(c.record !== null && - c.record.ready && c.record.fragment.isEmpty()) { - c.record = null; - } - - // if there is no pending record, try to read record header - if(c.record === null) { - rval = _readRecordHeader(c); - } - - // read the next record (if record not yet ready) - if(!c.fail && c.record !== null && !c.record.ready) { - rval = _readRecord(c); - } - - // record ready to be handled, update engine state - if(!c.fail && c.record !== null && c.record.ready) { - _update(c, c.record); - } - } - - return rval; - }; - - /** - * Requests that application data be packaged into a TLS record. The - * tlsDataReady handler will be called when the TLS record(s) have been - * prepared. - * - * @param data the application data, as a raw 'binary' encoded string, to - * be sent; to send utf-16/utf-8 string data, use the return value - * of util.encodeUtf8(str). - * - * @return true on success, false on failure. - */ - c.prepare = function(data) { - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.application_data, - data: forge$9.util.createBuffer(data) - })); - return tls$1.flush(c); - }; - - /** - * Requests that a heartbeat request be packaged into a TLS record for - * transmission. The tlsDataReady handler will be called when TLS record(s) - * have been prepared. - * - * When a heartbeat response has been received, the heartbeatReceived - * handler will be called with the matching payload. This handler can - * be used to clear a retransmission timer, etc. - * - * @param payload the heartbeat data to send as the payload in the message. - * @param [payloadLength] the payload length to use, defaults to the - * actual payload length. - * - * @return true on success, false on failure. - */ - c.prepareHeartbeatRequest = function(payload, payloadLength) { - if(payload instanceof forge$9.util.ByteBuffer) { - payload = payload.bytes(); - } - if(typeof payloadLength === 'undefined') { - payloadLength = payload.length; - } - c.expectedHeartbeatPayload = payload; - tls$1.queue(c, tls$1.createRecord(c, { - type: tls$1.ContentType.heartbeat, - data: tls$1.createHeartbeat( - tls$1.HeartbeatMessageType.heartbeat_request, payload, payloadLength) - })); - return tls$1.flush(c); - }; - - /** - * Closes the connection (sends a close_notify alert). - * - * @param clearFail true to clear the fail flag (default: true). - */ - c.close = function(clearFail) { - // save session if connection didn't fail - if(!c.fail && c.sessionCache && c.session) { - // only need to preserve session ID, version, and security params - var session = { - id: c.session.id, - version: c.session.version, - sp: c.session.sp - }; - session.sp.keys = null; - c.sessionCache.setSession(session.id, session); - } - - if(c.open) { - // connection no longer open, clear input - c.open = false; - c.input.clear(); - - // if connected or handshaking, send an alert - if(c.isConnected || c.handshaking) { - c.isConnected = c.handshaking = false; - - // send close_notify alert - tls$1.queue(c, tls$1.createAlert(c, { - level: tls$1.Alert.Level.warning, - description: tls$1.Alert.Description.close_notify - })); - tls$1.flush(c); - } - - // call handler - c.closed(c); - } - - // reset TLS connection, do not clear fail flag - c.reset(clearFail); - }; - - return c; -}; - -/* TLS API */ -forge$9.tls = forge$9.tls || {}; - -// expose non-functions -for(var key in tls$1) { - if(typeof tls$1[key] !== 'function') { - forge$9.tls[key] = tls$1[key]; - } -} - -// expose prf_tls1 for testing -forge$9.tls.prf_tls1 = prf_TLS1; - -// expose sha1 hmac method -forge$9.tls.hmac_sha1 = hmac_sha1; - -// expose session cache creation -forge$9.tls.createSessionCache = tls$1.createSessionCache; - -/** - * Creates a new TLS connection. This does not make any assumptions about the - * transport layer that TLS is working on top of, ie: it does not assume there - * is a TCP/IP connection or establish one. A TLS connection is totally - * abstracted away from the layer is runs on top of, it merely establishes a - * secure channel between a client" and a "server". - * - * A TLS connection contains 4 connection states: pending read and write, and - * current read and write. - * - * At initialization, the current read and write states will be null. Only once - * the security parameters have been set and the keys have been generated can - * the pending states be converted into current states. Current states will be - * updated for each record processed. - * - * A custom certificate verify callback may be provided to check information - * like the common name on the server's certificate. It will be called for - * every certificate in the chain. It has the following signature: - * - * variable func(c, certs, index, preVerify) - * Where: - * c The TLS connection - * verified Set to true if certificate was verified, otherwise the alert - * tls.Alert.Description for why the certificate failed. - * depth The current index in the chain, where 0 is the server's cert. - * certs The certificate chain, *NOTE* if the server was anonymous then - * the chain will be empty. - * - * The function returns true on success and on failure either the appropriate - * tls.Alert.Description or an object with 'alert' set to the appropriate - * tls.Alert.Description and 'message' set to a custom error message. If true - * is not returned then the connection will abort using, in order of - * availability, first the returned alert description, second the preVerify - * alert description, and lastly the default 'bad_certificate'. - * - * There are three callbacks that can be used to make use of client-side - * certificates where each takes the TLS connection as the first parameter: - * - * getCertificate(conn, hint) - * The second parameter is a hint as to which certificate should be - * returned. If the connection entity is a client, then the hint will be - * the CertificateRequest message from the server that is part of the - * TLS protocol. If the connection entity is a server, then it will be - * the servername list provided via an SNI extension the ClientHello, if - * one was provided (empty array if not). The hint can be examined to - * determine which certificate to use (advanced). Most implementations - * will just return a certificate. The return value must be a - * PEM-formatted certificate or an array of PEM-formatted certificates - * that constitute a certificate chain, with the first in the array/chain - * being the client's certificate. - * getPrivateKey(conn, certificate) - * The second parameter is an forge.pki X.509 certificate object that - * is associated with the requested private key. The return value must - * be a PEM-formatted private key. - * getSignature(conn, bytes, callback) - * This callback can be used instead of getPrivateKey if the private key - * is not directly accessible in javascript or should not be. For - * instance, a secure external web service could provide the signature - * in exchange for appropriate credentials. The second parameter is a - * string of bytes to be signed that are part of the TLS protocol. These - * bytes are used to verify that the private key for the previously - * provided client-side certificate is accessible to the client. The - * callback is a function that takes 2 parameters, the TLS connection - * and the RSA encrypted (signed) bytes as a string. This callback must - * be called once the signature is ready. - * - * @param options the options for this connection: - * server: true if the connection is server-side, false for client. - * sessionId: a session ID to reuse, null for a new connection. - * caStore: an array of certificates to trust. - * sessionCache: a session cache to use. - * cipherSuites: an optional array of cipher suites to use, - * see tls.CipherSuites. - * connected: function(conn) called when the first handshake completes. - * virtualHost: the virtual server name to use in a TLS SNI extension. - * verifyClient: true to require a client certificate in server mode, - * 'optional' to request one, false not to (default: false). - * verify: a handler used to custom verify certificates in the chain. - * verifyOptions: an object with options for the certificate chain validation. - * See documentation of pki.verifyCertificateChain for possible options. - * verifyOptions.verify is ignored. If you wish to specify a verify handler - * use the verify key. - * getCertificate: an optional callback used to get a certificate or - * a chain of certificates (as an array). - * getPrivateKey: an optional callback used to get a private key. - * getSignature: an optional callback used to get a signature. - * tlsDataReady: function(conn) called when TLS protocol data has been - * prepared and is ready to be used (typically sent over a socket - * connection to its destination), read from conn.tlsData buffer. - * dataReady: function(conn) called when application data has - * been parsed from a TLS record and should be consumed by the - * application, read from conn.data buffer. - * closed: function(conn) called when the connection has been closed. - * error: function(conn, error) called when there was an error. - * deflate: function(inBytes) if provided, will deflate TLS records using - * the deflate algorithm if the server supports it. - * inflate: function(inBytes) if provided, will inflate TLS records using - * the deflate algorithm if the server supports it. - * - * @return the new TLS connection. - */ -forge$9.tls.createConnection = tls$1.createConnection; - -/** - * A Javascript implementation of AES Cipher Suites for TLS. - * - * @author Dave Longley - * - * Copyright (c) 2009-2015 Digital Bazaar, Inc. - * - */ - -var forge$8 = forge$D; - - - -var tls = forge$8.tls; - -/** - * Supported cipher suites. - */ -tls.CipherSuites['TLS_RSA_WITH_AES_128_CBC_SHA'] = { - id: [0x00, 0x2f], - name: 'TLS_RSA_WITH_AES_128_CBC_SHA', - initSecurityParameters: function(sp) { - sp.bulk_cipher_algorithm = tls.BulkCipherAlgorithm.aes; - sp.cipher_type = tls.CipherType.block; - sp.enc_key_length = 16; - sp.block_length = 16; - sp.fixed_iv_length = 16; - sp.record_iv_length = 16; - sp.mac_algorithm = tls.MACAlgorithm.hmac_sha1; - sp.mac_length = 20; - sp.mac_key_length = 20; - }, - initConnectionState: initConnectionState -}; -tls.CipherSuites['TLS_RSA_WITH_AES_256_CBC_SHA'] = { - id: [0x00, 0x35], - name: 'TLS_RSA_WITH_AES_256_CBC_SHA', - initSecurityParameters: function(sp) { - sp.bulk_cipher_algorithm = tls.BulkCipherAlgorithm.aes; - sp.cipher_type = tls.CipherType.block; - sp.enc_key_length = 32; - sp.block_length = 16; - sp.fixed_iv_length = 16; - sp.record_iv_length = 16; - sp.mac_algorithm = tls.MACAlgorithm.hmac_sha1; - sp.mac_length = 20; - sp.mac_key_length = 20; - }, - initConnectionState: initConnectionState -}; - -function initConnectionState(state, c, sp) { - var client = (c.entity === forge$8.tls.ConnectionEnd.client); - - // cipher setup - state.read.cipherState = { - init: false, - cipher: forge$8.cipher.createDecipher('AES-CBC', client ? - sp.keys.server_write_key : sp.keys.client_write_key), - iv: client ? sp.keys.server_write_IV : sp.keys.client_write_IV - }; - state.write.cipherState = { - init: false, - cipher: forge$8.cipher.createCipher('AES-CBC', client ? - sp.keys.client_write_key : sp.keys.server_write_key), - iv: client ? sp.keys.client_write_IV : sp.keys.server_write_IV - }; - state.read.cipherFunction = decrypt_aes_cbc_sha1; - state.write.cipherFunction = encrypt_aes_cbc_sha1; - - // MAC setup - state.read.macLength = state.write.macLength = sp.mac_length; - state.read.macFunction = state.write.macFunction = tls.hmac_sha1; -} - -/** - * Encrypts the TLSCompressed record into a TLSCipherText record using AES - * in CBC mode. - * - * @param record the TLSCompressed record to encrypt. - * @param s the ConnectionState to use. - * - * @return true on success, false on failure. - */ -function encrypt_aes_cbc_sha1(record, s) { - var rval = false; - - // append MAC to fragment, update sequence number - var mac = s.macFunction(s.macKey, s.sequenceNumber, record); - record.fragment.putBytes(mac); - s.updateSequenceNumber(); - - // TLS 1.1+ use an explicit IV every time to protect against CBC attacks - var iv; - if(record.version.minor === tls.Versions.TLS_1_0.minor) { - // use the pre-generated IV when initializing for TLS 1.0, otherwise use - // the residue from the previous encryption - iv = s.cipherState.init ? null : s.cipherState.iv; - } else { - iv = forge$8.random.getBytesSync(16); - } - - s.cipherState.init = true; - - // start cipher - var cipher = s.cipherState.cipher; - cipher.start({iv: iv}); - - // TLS 1.1+ write IV into output - if(record.version.minor >= tls.Versions.TLS_1_1.minor) { - cipher.output.putBytes(iv); - } - - // do encryption (default padding is appropriate) - cipher.update(record.fragment); - if(cipher.finish(encrypt_aes_cbc_sha1_padding)) { - // set record fragment to encrypted output - record.fragment = cipher.output; - record.length = record.fragment.length(); - rval = true; - } - - return rval; -} - -/** - * Handles padding for aes_cbc_sha1 in encrypt mode. - * - * @param blockSize the block size. - * @param input the input buffer. - * @param decrypt true in decrypt mode, false in encrypt mode. - * - * @return true on success, false on failure. - */ -function encrypt_aes_cbc_sha1_padding(blockSize, input, decrypt) { - /* The encrypted data length (TLSCiphertext.length) is one more than the sum - of SecurityParameters.block_length, TLSCompressed.length, - SecurityParameters.mac_length, and padding_length. - - The padding may be any length up to 255 bytes long, as long as it results in - the TLSCiphertext.length being an integral multiple of the block length. - Lengths longer than necessary might be desirable to frustrate attacks on a - protocol based on analysis of the lengths of exchanged messages. Each uint8 - in the padding data vector must be filled with the padding length value. - - The padding length should be such that the total size of the - GenericBlockCipher structure is a multiple of the cipher's block length. - Legal values range from zero to 255, inclusive. This length specifies the - length of the padding field exclusive of the padding_length field itself. - - This is slightly different from PKCS#7 because the padding value is 1 - less than the actual number of padding bytes if you include the - padding_length uint8 itself as a padding byte. */ - if(!decrypt) { - // get the number of padding bytes required to reach the blockSize and - // subtract 1 for the padding value (to make room for the padding_length - // uint8) - var padding = blockSize - (input.length() % blockSize); - input.fillWithByte(padding - 1, padding); - } - return true; -} - -/** - * Handles padding for aes_cbc_sha1 in decrypt mode. - * - * @param blockSize the block size. - * @param output the output buffer. - * @param decrypt true in decrypt mode, false in encrypt mode. - * - * @return true on success, false on failure. - */ -function decrypt_aes_cbc_sha1_padding(blockSize, output, decrypt) { - var rval = true; - if(decrypt) { - /* The last byte in the output specifies the number of padding bytes not - including itself. Each of the padding bytes has the same value as that - last byte (known as the padding_length). Here we check all padding - bytes to ensure they have the value of padding_length even if one of - them is bad in order to ward-off timing attacks. */ - var len = output.length(); - var paddingLength = output.last(); - for(var i = len - 1 - paddingLength; i < len - 1; ++i) { - rval = rval && (output.at(i) == paddingLength); - } - if(rval) { - // trim off padding bytes and last padding length byte - output.truncate(paddingLength + 1); - } - } - return rval; -} - -/** - * Decrypts a TLSCipherText record into a TLSCompressed record using - * AES in CBC mode. - * - * @param record the TLSCipherText record to decrypt. - * @param s the ConnectionState to use. - * - * @return true on success, false on failure. - */ -function decrypt_aes_cbc_sha1(record, s) { - var rval = false; - - var iv; - if(record.version.minor === tls.Versions.TLS_1_0.minor) { - // use pre-generated IV when initializing for TLS 1.0, otherwise use the - // residue from the previous decryption - iv = s.cipherState.init ? null : s.cipherState.iv; - } else { - // TLS 1.1+ use an explicit IV every time to protect against CBC attacks - // that is appended to the record fragment - iv = record.fragment.getBytes(16); - } - - s.cipherState.init = true; - - // start cipher - var cipher = s.cipherState.cipher; - cipher.start({iv: iv}); - - // do decryption - cipher.update(record.fragment); - rval = cipher.finish(decrypt_aes_cbc_sha1_padding); - - // even if decryption fails, keep going to minimize timing attacks - - // decrypted data: - // first (len - 20) bytes = application data - // last 20 bytes = MAC - var macLen = s.macLength; - - // create a random MAC to check against should the mac length check fail - // Note: do this regardless of the failure to keep timing consistent - var mac = forge$8.random.getBytesSync(macLen); - - // get fragment and mac - var len = cipher.output.length(); - if(len >= macLen) { - record.fragment = cipher.output.getBytes(len - macLen); - mac = cipher.output.getBytes(macLen); - } else { - // bad data, but get bytes anyway to try to keep timing consistent - record.fragment = cipher.output.getBytes(); - } - record.fragment = forge$8.util.createBuffer(record.fragment); - record.length = record.fragment.length(); - - // see if data integrity checks out, update sequence number - var mac2 = s.macFunction(s.macKey, s.sequenceNumber, record); - s.updateSequenceNumber(); - rval = compareMacs(s.macKey, mac, mac2) && rval; - return rval; -} - -/** - * Safely compare two MACs. This function will compare two MACs in a way - * that protects against timing attacks. - * - * TODO: Expose elsewhere as a utility API. - * - * See: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ - * - * @param key the MAC key to use. - * @param mac1 as a binary-encoded string of bytes. - * @param mac2 as a binary-encoded string of bytes. - * - * @return true if the MACs are the same, false if not. - */ -function compareMacs(key, mac1, mac2) { - var hmac = forge$8.hmac.create(); - - hmac.start('SHA1', key); - hmac.update(mac1); - mac1 = hmac.digest().getBytes(); - - hmac.start(null, null); - hmac.update(mac2); - mac2 = hmac.digest().getBytes(); - - return mac1 === mac2; -} - -/** - * Secure Hash Algorithm with a 1024-bit block size implementation. - * - * This includes: SHA-512, SHA-384, SHA-512/224, and SHA-512/256. For - * SHA-256 (block size 512 bits), see sha256.js. - * - * See FIPS 180-4 for details. - * - * @author Dave Longley - * - * Copyright (c) 2014-2015 Digital Bazaar, Inc. - */ - -var forge$7 = forge$D; - - - -var sha512$1 = forge$7.sha512 = forge$7.sha512 || {}; - -// SHA-512 -forge$7.md.sha512 = forge$7.md.algorithms.sha512 = sha512$1; - -// SHA-384 -var sha384 = forge$7.sha384 = forge$7.sha512.sha384 = forge$7.sha512.sha384 || {}; -sha384.create = function() { - return sha512$1.create('SHA-384'); -}; -forge$7.md.sha384 = forge$7.md.algorithms.sha384 = sha384; - -// SHA-512/256 -forge$7.sha512.sha256 = forge$7.sha512.sha256 || { - create: function() { - return sha512$1.create('SHA-512/256'); - } -}; -forge$7.md['sha512/256'] = forge$7.md.algorithms['sha512/256'] = - forge$7.sha512.sha256; - -// SHA-512/224 -forge$7.sha512.sha224 = forge$7.sha512.sha224 || { - create: function() { - return sha512$1.create('SHA-512/224'); - } -}; -forge$7.md['sha512/224'] = forge$7.md.algorithms['sha512/224'] = - forge$7.sha512.sha224; - -/** - * Creates a SHA-2 message digest object. - * - * @param algorithm the algorithm to use (SHA-512, SHA-384, SHA-512/224, - * SHA-512/256). - * - * @return a message digest object. - */ -sha512$1.create = function(algorithm) { - // do initialization as necessary - if(!_initialized) { - _init(); - } - - if(typeof algorithm === 'undefined') { - algorithm = 'SHA-512'; - } - - if(!(algorithm in _states)) { - throw new Error('Invalid SHA-512 algorithm: ' + algorithm); - } - - // SHA-512 state contains eight 64-bit integers (each as two 32-bit ints) - var _state = _states[algorithm]; - var _h = null; - - // input buffer - var _input = forge$7.util.createBuffer(); - - // used for 64-bit word storage - var _w = new Array(80); - for(var wi = 0; wi < 80; ++wi) { - _w[wi] = new Array(2); - } - - // determine digest length by algorithm name (default) - var digestLength = 64; - switch(algorithm) { - case 'SHA-384': - digestLength = 48; - break; - case 'SHA-512/256': - digestLength = 32; - break; - case 'SHA-512/224': - digestLength = 28; - break; - } - - // message digest object - var md = { - // SHA-512 => sha512 - algorithm: algorithm.replace('-', '').toLowerCase(), - blockLength: 128, - digestLength: digestLength, - // 56-bit length of message so far (does not including padding) - messageLength: 0, - // true message length - fullMessageLength: null, - // size of message length in bytes - messageLengthSize: 16 - }; - - /** - * Starts the digest. - * - * @return this digest object. - */ - md.start = function() { - // up to 56-bit message length for convenience - md.messageLength = 0; - - // full message length (set md.messageLength128 for backwards-compatibility) - md.fullMessageLength = md.messageLength128 = []; - var int32s = md.messageLengthSize / 4; - for(var i = 0; i < int32s; ++i) { - md.fullMessageLength.push(0); - } - _input = forge$7.util.createBuffer(); - _h = new Array(_state.length); - for(var i = 0; i < _state.length; ++i) { - _h[i] = _state[i].slice(0); - } - return md; - }; - // start digest automatically for first time - md.start(); - - /** - * Updates the digest with the given message input. The given input can - * treated as raw input (no encoding will be applied) or an encoding of - * 'utf8' maybe given to encode the input using UTF-8. - * - * @param msg the message input to update with. - * @param encoding the encoding to use (default: 'raw', other: 'utf8'). - * - * @return this digest object. - */ - md.update = function(msg, encoding) { - if(encoding === 'utf8') { - msg = forge$7.util.encodeUtf8(msg); - } - - // update message length - var len = msg.length; - md.messageLength += len; - len = [(len / 0x100000000) >>> 0, len >>> 0]; - for(var i = md.fullMessageLength.length - 1; i >= 0; --i) { - md.fullMessageLength[i] += len[1]; - len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0); - md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0; - len[0] = ((len[1] / 0x100000000) >>> 0); - } - - // add bytes to input buffer - _input.putBytes(msg); - - // process bytes - _update(_h, _w, _input); - - // compact input buffer every 2K or if empty - if(_input.read > 2048 || _input.length() === 0) { - _input.compact(); - } - - return md; - }; - - /** - * Produces the digest. - * - * @return a byte buffer containing the digest value. - */ - md.digest = function() { - /* Note: Here we copy the remaining bytes in the input buffer and - add the appropriate SHA-512 padding. Then we do the final update - on a copy of the state so that if the user wants to get - intermediate digests they can do so. */ - - /* Determine the number of bytes that must be added to the message - to ensure its length is congruent to 896 mod 1024. In other words, - the data to be digested must be a multiple of 1024 bits (or 128 bytes). - This data includes the message, some padding, and the length of the - message. Since the length of the message will be encoded as 16 bytes (128 - bits), that means that the last segment of the data must have 112 bytes - (896 bits) of message and padding. Therefore, the length of the message - plus the padding must be congruent to 896 mod 1024 because - 1024 - 128 = 896. - - In order to fill up the message length it must be filled with - padding that begins with 1 bit followed by all 0 bits. Padding - must *always* be present, so if the message length is already - congruent to 896 mod 1024, then 1024 padding bits must be added. */ - - var finalBlock = forge$7.util.createBuffer(); - finalBlock.putBytes(_input.bytes()); - - // compute remaining size to be digested (include message length size) - var remaining = ( - md.fullMessageLength[md.fullMessageLength.length - 1] + - md.messageLengthSize); - - // add padding for overflow blockSize - overflow - // _padding starts with 1 byte with first bit is set (byte value 128), then - // there may be up to (blockSize - 1) other pad bytes - var overflow = remaining & (md.blockLength - 1); - finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow)); - - // serialize message length in bits in big-endian order; since length - // is stored in bytes we multiply by 8 and add carry from next int - var next, carry; - var bits = md.fullMessageLength[0] * 8; - for(var i = 0; i < md.fullMessageLength.length - 1; ++i) { - next = md.fullMessageLength[i + 1] * 8; - carry = (next / 0x100000000) >>> 0; - bits += carry; - finalBlock.putInt32(bits >>> 0); - bits = next >>> 0; - } - finalBlock.putInt32(bits); - - var h = new Array(_h.length); - for(var i = 0; i < _h.length; ++i) { - h[i] = _h[i].slice(0); - } - _update(h, _w, finalBlock); - var rval = forge$7.util.createBuffer(); - var hlen; - if(algorithm === 'SHA-512') { - hlen = h.length; - } else if(algorithm === 'SHA-384') { - hlen = h.length - 2; - } else { - hlen = h.length - 4; - } - for(var i = 0; i < hlen; ++i) { - rval.putInt32(h[i][0]); - if(i !== hlen - 1 || algorithm !== 'SHA-512/224') { - rval.putInt32(h[i][1]); - } - } - return rval; - }; - - return md; -}; - -// sha-512 padding bytes not initialized yet -var _padding = null; -var _initialized = false; - -// table of constants -var _k = null; - -// initial hash states -var _states = null; - -/** - * Initializes the constant tables. - */ -function _init() { - // create padding - _padding = String.fromCharCode(128); - _padding += forge$7.util.fillString(String.fromCharCode(0x00), 128); - - // create K table for SHA-512 - _k = [ - [0x428a2f98, 0xd728ae22], [0x71374491, 0x23ef65cd], - [0xb5c0fbcf, 0xec4d3b2f], [0xe9b5dba5, 0x8189dbbc], - [0x3956c25b, 0xf348b538], [0x59f111f1, 0xb605d019], - [0x923f82a4, 0xaf194f9b], [0xab1c5ed5, 0xda6d8118], - [0xd807aa98, 0xa3030242], [0x12835b01, 0x45706fbe], - [0x243185be, 0x4ee4b28c], [0x550c7dc3, 0xd5ffb4e2], - [0x72be5d74, 0xf27b896f], [0x80deb1fe, 0x3b1696b1], - [0x9bdc06a7, 0x25c71235], [0xc19bf174, 0xcf692694], - [0xe49b69c1, 0x9ef14ad2], [0xefbe4786, 0x384f25e3], - [0x0fc19dc6, 0x8b8cd5b5], [0x240ca1cc, 0x77ac9c65], - [0x2de92c6f, 0x592b0275], [0x4a7484aa, 0x6ea6e483], - [0x5cb0a9dc, 0xbd41fbd4], [0x76f988da, 0x831153b5], - [0x983e5152, 0xee66dfab], [0xa831c66d, 0x2db43210], - [0xb00327c8, 0x98fb213f], [0xbf597fc7, 0xbeef0ee4], - [0xc6e00bf3, 0x3da88fc2], [0xd5a79147, 0x930aa725], - [0x06ca6351, 0xe003826f], [0x14292967, 0x0a0e6e70], - [0x27b70a85, 0x46d22ffc], [0x2e1b2138, 0x5c26c926], - [0x4d2c6dfc, 0x5ac42aed], [0x53380d13, 0x9d95b3df], - [0x650a7354, 0x8baf63de], [0x766a0abb, 0x3c77b2a8], - [0x81c2c92e, 0x47edaee6], [0x92722c85, 0x1482353b], - [0xa2bfe8a1, 0x4cf10364], [0xa81a664b, 0xbc423001], - [0xc24b8b70, 0xd0f89791], [0xc76c51a3, 0x0654be30], - [0xd192e819, 0xd6ef5218], [0xd6990624, 0x5565a910], - [0xf40e3585, 0x5771202a], [0x106aa070, 0x32bbd1b8], - [0x19a4c116, 0xb8d2d0c8], [0x1e376c08, 0x5141ab53], - [0x2748774c, 0xdf8eeb99], [0x34b0bcb5, 0xe19b48a8], - [0x391c0cb3, 0xc5c95a63], [0x4ed8aa4a, 0xe3418acb], - [0x5b9cca4f, 0x7763e373], [0x682e6ff3, 0xd6b2b8a3], - [0x748f82ee, 0x5defb2fc], [0x78a5636f, 0x43172f60], - [0x84c87814, 0xa1f0ab72], [0x8cc70208, 0x1a6439ec], - [0x90befffa, 0x23631e28], [0xa4506ceb, 0xde82bde9], - [0xbef9a3f7, 0xb2c67915], [0xc67178f2, 0xe372532b], - [0xca273ece, 0xea26619c], [0xd186b8c7, 0x21c0c207], - [0xeada7dd6, 0xcde0eb1e], [0xf57d4f7f, 0xee6ed178], - [0x06f067aa, 0x72176fba], [0x0a637dc5, 0xa2c898a6], - [0x113f9804, 0xbef90dae], [0x1b710b35, 0x131c471b], - [0x28db77f5, 0x23047d84], [0x32caab7b, 0x40c72493], - [0x3c9ebe0a, 0x15c9bebc], [0x431d67c4, 0x9c100d4c], - [0x4cc5d4be, 0xcb3e42b6], [0x597f299c, 0xfc657e2a], - [0x5fcb6fab, 0x3ad6faec], [0x6c44198c, 0x4a475817] - ]; - - // initial hash states - _states = {}; - _states['SHA-512'] = [ - [0x6a09e667, 0xf3bcc908], - [0xbb67ae85, 0x84caa73b], - [0x3c6ef372, 0xfe94f82b], - [0xa54ff53a, 0x5f1d36f1], - [0x510e527f, 0xade682d1], - [0x9b05688c, 0x2b3e6c1f], - [0x1f83d9ab, 0xfb41bd6b], - [0x5be0cd19, 0x137e2179] - ]; - _states['SHA-384'] = [ - [0xcbbb9d5d, 0xc1059ed8], - [0x629a292a, 0x367cd507], - [0x9159015a, 0x3070dd17], - [0x152fecd8, 0xf70e5939], - [0x67332667, 0xffc00b31], - [0x8eb44a87, 0x68581511], - [0xdb0c2e0d, 0x64f98fa7], - [0x47b5481d, 0xbefa4fa4] - ]; - _states['SHA-512/256'] = [ - [0x22312194, 0xFC2BF72C], - [0x9F555FA3, 0xC84C64C2], - [0x2393B86B, 0x6F53B151], - [0x96387719, 0x5940EABD], - [0x96283EE2, 0xA88EFFE3], - [0xBE5E1E25, 0x53863992], - [0x2B0199FC, 0x2C85B8AA], - [0x0EB72DDC, 0x81C52CA2] - ]; - _states['SHA-512/224'] = [ - [0x8C3D37C8, 0x19544DA2], - [0x73E19966, 0x89DCD4D6], - [0x1DFAB7AE, 0x32FF9C82], - [0x679DD514, 0x582F9FCF], - [0x0F6D2B69, 0x7BD44DA8], - [0x77E36F73, 0x04C48942], - [0x3F9D85A8, 0x6A1D36C8], - [0x1112E6AD, 0x91D692A1] - ]; - - // now initialized - _initialized = true; -} - -/** - * Updates a SHA-512 state with the given byte buffer. - * - * @param s the SHA-512 state to update. - * @param w the array to use to store words. - * @param bytes the byte buffer to update with. - */ -function _update(s, w, bytes) { - // consume 512 bit (128 byte) chunks - var t1_hi, t1_lo; - var t2_hi, t2_lo; - var s0_hi, s0_lo; - var s1_hi, s1_lo; - var ch_hi, ch_lo; - var maj_hi, maj_lo; - var a_hi, a_lo; - var b_hi, b_lo; - var c_hi, c_lo; - var d_hi, d_lo; - var e_hi, e_lo; - var f_hi, f_lo; - var g_hi, g_lo; - var h_hi, h_lo; - var i, hi, lo, w2, w7, w15, w16; - var len = bytes.length(); - while(len >= 128) { - // the w array will be populated with sixteen 64-bit big-endian words - // and then extended into 64 64-bit words according to SHA-512 - for(i = 0; i < 16; ++i) { - w[i][0] = bytes.getInt32() >>> 0; - w[i][1] = bytes.getInt32() >>> 0; - } - for(; i < 80; ++i) { - // for word 2 words ago: ROTR 19(x) ^ ROTR 61(x) ^ SHR 6(x) - w2 = w[i - 2]; - hi = w2[0]; - lo = w2[1]; - - // high bits - t1_hi = ( - ((hi >>> 19) | (lo << 13)) ^ // ROTR 19 - ((lo >>> 29) | (hi << 3)) ^ // ROTR 61/(swap + ROTR 29) - (hi >>> 6)) >>> 0; // SHR 6 - // low bits - t1_lo = ( - ((hi << 13) | (lo >>> 19)) ^ // ROTR 19 - ((lo << 3) | (hi >>> 29)) ^ // ROTR 61/(swap + ROTR 29) - ((hi << 26) | (lo >>> 6))) >>> 0; // SHR 6 - - // for word 15 words ago: ROTR 1(x) ^ ROTR 8(x) ^ SHR 7(x) - w15 = w[i - 15]; - hi = w15[0]; - lo = w15[1]; - - // high bits - t2_hi = ( - ((hi >>> 1) | (lo << 31)) ^ // ROTR 1 - ((hi >>> 8) | (lo << 24)) ^ // ROTR 8 - (hi >>> 7)) >>> 0; // SHR 7 - // low bits - t2_lo = ( - ((hi << 31) | (lo >>> 1)) ^ // ROTR 1 - ((hi << 24) | (lo >>> 8)) ^ // ROTR 8 - ((hi << 25) | (lo >>> 7))) >>> 0; // SHR 7 - - // sum(t1, word 7 ago, t2, word 16 ago) modulo 2^64 (carry lo overflow) - w7 = w[i - 7]; - w16 = w[i - 16]; - lo = (t1_lo + w7[1] + t2_lo + w16[1]); - w[i][0] = (t1_hi + w7[0] + t2_hi + w16[0] + - ((lo / 0x100000000) >>> 0)) >>> 0; - w[i][1] = lo >>> 0; - } - - // initialize hash value for this chunk - a_hi = s[0][0]; - a_lo = s[0][1]; - b_hi = s[1][0]; - b_lo = s[1][1]; - c_hi = s[2][0]; - c_lo = s[2][1]; - d_hi = s[3][0]; - d_lo = s[3][1]; - e_hi = s[4][0]; - e_lo = s[4][1]; - f_hi = s[5][0]; - f_lo = s[5][1]; - g_hi = s[6][0]; - g_lo = s[6][1]; - h_hi = s[7][0]; - h_lo = s[7][1]; - - // round function - for(i = 0; i < 80; ++i) { - // Sum1(e) = ROTR 14(e) ^ ROTR 18(e) ^ ROTR 41(e) - s1_hi = ( - ((e_hi >>> 14) | (e_lo << 18)) ^ // ROTR 14 - ((e_hi >>> 18) | (e_lo << 14)) ^ // ROTR 18 - ((e_lo >>> 9) | (e_hi << 23))) >>> 0; // ROTR 41/(swap + ROTR 9) - s1_lo = ( - ((e_hi << 18) | (e_lo >>> 14)) ^ // ROTR 14 - ((e_hi << 14) | (e_lo >>> 18)) ^ // ROTR 18 - ((e_lo << 23) | (e_hi >>> 9))) >>> 0; // ROTR 41/(swap + ROTR 9) - - // Ch(e, f, g) (optimized the same way as SHA-1) - ch_hi = (g_hi ^ (e_hi & (f_hi ^ g_hi))) >>> 0; - ch_lo = (g_lo ^ (e_lo & (f_lo ^ g_lo))) >>> 0; - - // Sum0(a) = ROTR 28(a) ^ ROTR 34(a) ^ ROTR 39(a) - s0_hi = ( - ((a_hi >>> 28) | (a_lo << 4)) ^ // ROTR 28 - ((a_lo >>> 2) | (a_hi << 30)) ^ // ROTR 34/(swap + ROTR 2) - ((a_lo >>> 7) | (a_hi << 25))) >>> 0; // ROTR 39/(swap + ROTR 7) - s0_lo = ( - ((a_hi << 4) | (a_lo >>> 28)) ^ // ROTR 28 - ((a_lo << 30) | (a_hi >>> 2)) ^ // ROTR 34/(swap + ROTR 2) - ((a_lo << 25) | (a_hi >>> 7))) >>> 0; // ROTR 39/(swap + ROTR 7) - - // Maj(a, b, c) (optimized the same way as SHA-1) - maj_hi = ((a_hi & b_hi) | (c_hi & (a_hi ^ b_hi))) >>> 0; - maj_lo = ((a_lo & b_lo) | (c_lo & (a_lo ^ b_lo))) >>> 0; - - // main algorithm - // t1 = (h + s1 + ch + _k[i] + _w[i]) modulo 2^64 (carry lo overflow) - lo = (h_lo + s1_lo + ch_lo + _k[i][1] + w[i][1]); - t1_hi = (h_hi + s1_hi + ch_hi + _k[i][0] + w[i][0] + - ((lo / 0x100000000) >>> 0)) >>> 0; - t1_lo = lo >>> 0; - - // t2 = s0 + maj modulo 2^64 (carry lo overflow) - lo = s0_lo + maj_lo; - t2_hi = (s0_hi + maj_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - t2_lo = lo >>> 0; - - h_hi = g_hi; - h_lo = g_lo; - - g_hi = f_hi; - g_lo = f_lo; - - f_hi = e_hi; - f_lo = e_lo; - - // e = (d + t1) modulo 2^64 (carry lo overflow) - lo = d_lo + t1_lo; - e_hi = (d_hi + t1_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - e_lo = lo >>> 0; - - d_hi = c_hi; - d_lo = c_lo; - - c_hi = b_hi; - c_lo = b_lo; - - b_hi = a_hi; - b_lo = a_lo; - - // a = (t1 + t2) modulo 2^64 (carry lo overflow) - lo = t1_lo + t2_lo; - a_hi = (t1_hi + t2_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - a_lo = lo >>> 0; - } - - // update hash state (additional modulo 2^64) - lo = s[0][1] + a_lo; - s[0][0] = (s[0][0] + a_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - s[0][1] = lo >>> 0; - - lo = s[1][1] + b_lo; - s[1][0] = (s[1][0] + b_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - s[1][1] = lo >>> 0; - - lo = s[2][1] + c_lo; - s[2][0] = (s[2][0] + c_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - s[2][1] = lo >>> 0; - - lo = s[3][1] + d_lo; - s[3][0] = (s[3][0] + d_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - s[3][1] = lo >>> 0; - - lo = s[4][1] + e_lo; - s[4][0] = (s[4][0] + e_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - s[4][1] = lo >>> 0; - - lo = s[5][1] + f_lo; - s[5][0] = (s[5][0] + f_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - s[5][1] = lo >>> 0; - - lo = s[6][1] + g_lo; - s[6][0] = (s[6][0] + g_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - s[6][1] = lo >>> 0; - - lo = s[7][1] + h_lo; - s[7][0] = (s[7][0] + h_hi + ((lo / 0x100000000) >>> 0)) >>> 0; - s[7][1] = lo >>> 0; - - len -= 128; - } -} - -var asn1Validator$1 = {}; - -/** - * Copyright (c) 2019 Digital Bazaar, Inc. - */ - -var forge$6 = forge$D; - -var asn1$1 = forge$6.asn1; - -asn1Validator$1.privateKeyValidator = { - // PrivateKeyInfo - name: 'PrivateKeyInfo', - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.SEQUENCE, - constructed: true, - value: [{ - // Version (INTEGER) - name: 'PrivateKeyInfo.version', - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.INTEGER, - constructed: false, - capture: 'privateKeyVersion' - }, { - // privateKeyAlgorithm - name: 'PrivateKeyInfo.privateKeyAlgorithm', - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'AlgorithmIdentifier.algorithm', - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.OID, - constructed: false, - capture: 'privateKeyOid' - }] - }, { - // PrivateKey - name: 'PrivateKeyInfo', - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.OCTETSTRING, - constructed: false, - capture: 'privateKey' - }] -}; - -asn1Validator$1.publicKeyValidator = { - name: 'SubjectPublicKeyInfo', - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.SEQUENCE, - constructed: true, - captureAsn1: 'subjectPublicKeyInfo', - value: [{ - name: 'SubjectPublicKeyInfo.AlgorithmIdentifier', - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.SEQUENCE, - constructed: true, - value: [{ - name: 'AlgorithmIdentifier.algorithm', - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.OID, - constructed: false, - capture: 'publicKeyOid' - }] - }, - // capture group for ed25519PublicKey - { - tagClass: asn1$1.Class.UNIVERSAL, - type: asn1$1.Type.BITSTRING, - constructed: false, - composed: true, - captureBitStringValue: 'ed25519PublicKey' - } - // FIXME: this is capture group for rsaPublicKey, use it in this API or - // discard? - /* { - // subjectPublicKey - name: 'SubjectPublicKeyInfo.subjectPublicKey', - tagClass: asn1.Class.UNIVERSAL, - type: asn1.Type.BITSTRING, - constructed: false, - value: [{ - // RSAPublicKey - name: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey', - tagClass: asn1.Class.UNIVERSAL, - type: asn1.Type.SEQUENCE, - constructed: true, - optional: true, - captureAsn1: 'rsaPublicKey' - }] - } */ - ] -}; - -/** - * JavaScript implementation of Ed25519. - * - * Copyright (c) 2017-2019 Digital Bazaar, Inc. - * - * This implementation is based on the most excellent TweetNaCl which is - * in the public domain. Many thanks to its contributors: - * - * https://github.com/dchest/tweetnacl-js - */ - -var forge$5 = forge$D; - - - - -var asn1Validator = asn1Validator$1; -var publicKeyValidator = asn1Validator.publicKeyValidator; -var privateKeyValidator = asn1Validator.privateKeyValidator; - -if(typeof BigInteger$1 === 'undefined') { - var BigInteger$1 = forge$5.jsbn.BigInteger; -} - -var ByteBuffer = forge$5.util.ByteBuffer; -var NativeBuffer = typeof Buffer === 'undefined' ? Uint8Array : Buffer; - -/* - * Ed25519 algorithms, see RFC 8032: - * https://tools.ietf.org/html/rfc8032 - */ -forge$5.pki = forge$5.pki || {}; -forge$5.pki.ed25519 = forge$5.ed25519 = forge$5.ed25519 || {}; -var ed25519 = forge$5.ed25519; - -ed25519.constants = {}; -ed25519.constants.PUBLIC_KEY_BYTE_LENGTH = 32; -ed25519.constants.PRIVATE_KEY_BYTE_LENGTH = 64; -ed25519.constants.SEED_BYTE_LENGTH = 32; -ed25519.constants.SIGN_BYTE_LENGTH = 64; -ed25519.constants.HASH_BYTE_LENGTH = 64; - -ed25519.generateKeyPair = function(options) { - options = options || {}; - var seed = options.seed; - if(seed === undefined) { - // generate seed - seed = forge$5.random.getBytesSync(ed25519.constants.SEED_BYTE_LENGTH); - } else if(typeof seed === 'string') { - if(seed.length !== ed25519.constants.SEED_BYTE_LENGTH) { - throw new TypeError( - '"seed" must be ' + ed25519.constants.SEED_BYTE_LENGTH + - ' bytes in length.'); - } - } else if(!(seed instanceof Uint8Array)) { - throw new TypeError( - '"seed" must be a node.js Buffer, Uint8Array, or a binary string.'); - } - - seed = messageToNativeBuffer({message: seed, encoding: 'binary'}); - - var pk = new NativeBuffer(ed25519.constants.PUBLIC_KEY_BYTE_LENGTH); - var sk = new NativeBuffer(ed25519.constants.PRIVATE_KEY_BYTE_LENGTH); - for(var i = 0; i < 32; ++i) { - sk[i] = seed[i]; - } - crypto_sign_keypair(pk, sk); - return {publicKey: pk, privateKey: sk}; -}; - -/** - * Converts a private key from a RFC8410 ASN.1 encoding. - * - * @param obj - The asn1 representation of a private key. - * - * @returns {Object} keyInfo - The key information. - * @returns {Buffer|Uint8Array} keyInfo.privateKeyBytes - 32 private key bytes. - */ -ed25519.privateKeyFromAsn1 = function(obj) { - var capture = {}; - var errors = []; - var valid = forge$5.asn1.validate(obj, privateKeyValidator, capture, errors); - if(!valid) { - var error = new Error('Invalid Key.'); - error.errors = errors; - throw error; - } - var oid = forge$5.asn1.derToOid(capture.privateKeyOid); - var ed25519Oid = forge$5.oids.EdDSA25519; - if(oid !== ed25519Oid) { - throw new Error('Invalid OID "' + oid + '"; OID must be "' + - ed25519Oid + '".'); - } - var privateKey = capture.privateKey; - // manually extract the private key bytes from nested octet string, see FIXME: - // https://github.com/digitalbazaar/forge/blob/master/lib/asn1.js#L542 - var privateKeyBytes = messageToNativeBuffer({ - message: forge$5.asn1.fromDer(privateKey).value, - encoding: 'binary' - }); - // TODO: RFC8410 specifies a format for encoding the public key bytes along - // with the private key bytes. `publicKeyBytes` can be returned in the - // future. https://tools.ietf.org/html/rfc8410#section-10.3 - return {privateKeyBytes: privateKeyBytes}; -}; - -/** - * Converts a public key from a RFC8410 ASN.1 encoding. - * - * @param obj - The asn1 representation of a public key. - * - * @return {Buffer|Uint8Array} - 32 public key bytes. - */ -ed25519.publicKeyFromAsn1 = function(obj) { - // get SubjectPublicKeyInfo - var capture = {}; - var errors = []; - var valid = forge$5.asn1.validate(obj, publicKeyValidator, capture, errors); - if(!valid) { - var error = new Error('Invalid Key.'); - error.errors = errors; - throw error; - } - var oid = forge$5.asn1.derToOid(capture.publicKeyOid); - var ed25519Oid = forge$5.oids.EdDSA25519; - if(oid !== ed25519Oid) { - throw new Error('Invalid OID "' + oid + '"; OID must be "' + - ed25519Oid + '".'); - } - var publicKeyBytes = capture.ed25519PublicKey; - if(publicKeyBytes.length !== ed25519.constants.PUBLIC_KEY_BYTE_LENGTH) { - throw new Error('Key length is invalid.'); - } - return messageToNativeBuffer({ - message: publicKeyBytes, - encoding: 'binary' - }); -}; - -ed25519.publicKeyFromPrivateKey = function(options) { - options = options || {}; - var privateKey = messageToNativeBuffer({ - message: options.privateKey, encoding: 'binary' - }); - if(privateKey.length !== ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) { - throw new TypeError( - '"options.privateKey" must have a byte length of ' + - ed25519.constants.PRIVATE_KEY_BYTE_LENGTH); - } - - var pk = new NativeBuffer(ed25519.constants.PUBLIC_KEY_BYTE_LENGTH); - for(var i = 0; i < pk.length; ++i) { - pk[i] = privateKey[32 + i]; - } - return pk; -}; - -ed25519.sign = function(options) { - options = options || {}; - var msg = messageToNativeBuffer(options); - var privateKey = messageToNativeBuffer({ - message: options.privateKey, - encoding: 'binary' - }); - if(privateKey.length === ed25519.constants.SEED_BYTE_LENGTH) { - var keyPair = ed25519.generateKeyPair({seed: privateKey}); - privateKey = keyPair.privateKey; - } else if(privateKey.length !== ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) { - throw new TypeError( - '"options.privateKey" must have a byte length of ' + - ed25519.constants.SEED_BYTE_LENGTH + ' or ' + - ed25519.constants.PRIVATE_KEY_BYTE_LENGTH); - } - - var signedMsg = new NativeBuffer( - ed25519.constants.SIGN_BYTE_LENGTH + msg.length); - crypto_sign(signedMsg, msg, msg.length, privateKey); - - var sig = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH); - for(var i = 0; i < sig.length; ++i) { - sig[i] = signedMsg[i]; - } - return sig; -}; - -ed25519.verify = function(options) { - options = options || {}; - var msg = messageToNativeBuffer(options); - if(options.signature === undefined) { - throw new TypeError( - '"options.signature" must be a node.js Buffer, a Uint8Array, a forge ' + - 'ByteBuffer, or a binary string.'); - } - var sig = messageToNativeBuffer({ - message: options.signature, - encoding: 'binary' - }); - if(sig.length !== ed25519.constants.SIGN_BYTE_LENGTH) { - throw new TypeError( - '"options.signature" must have a byte length of ' + - ed25519.constants.SIGN_BYTE_LENGTH); - } - var publicKey = messageToNativeBuffer({ - message: options.publicKey, - encoding: 'binary' - }); - if(publicKey.length !== ed25519.constants.PUBLIC_KEY_BYTE_LENGTH) { - throw new TypeError( - '"options.publicKey" must have a byte length of ' + - ed25519.constants.PUBLIC_KEY_BYTE_LENGTH); - } - - var sm = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH + msg.length); - var m = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH + msg.length); - var i; - for(i = 0; i < ed25519.constants.SIGN_BYTE_LENGTH; ++i) { - sm[i] = sig[i]; - } - for(i = 0; i < msg.length; ++i) { - sm[i + ed25519.constants.SIGN_BYTE_LENGTH] = msg[i]; - } - return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); -}; - -function messageToNativeBuffer(options) { - var message = options.message; - if(message instanceof Uint8Array || message instanceof NativeBuffer) { - return message; - } - - var encoding = options.encoding; - if(message === undefined) { - if(options.md) { - // TODO: more rigorous validation that `md` is a MessageDigest - message = options.md.digest().getBytes(); - encoding = 'binary'; - } else { - throw new TypeError('"options.message" or "options.md" not specified.'); - } - } - - if(typeof message === 'string' && !encoding) { - throw new TypeError('"options.encoding" must be "binary" or "utf8".'); - } - - if(typeof message === 'string') { - if(typeof Buffer !== 'undefined') { - return Buffer.from(message, encoding); - } - message = new ByteBuffer(message, encoding); - } else if(!(message instanceof ByteBuffer)) { - throw new TypeError( - '"options.message" must be a node.js Buffer, a Uint8Array, a forge ' + - 'ByteBuffer, or a string with "options.encoding" specifying its ' + - 'encoding.'); - } - - // convert to native buffer - var buffer = new NativeBuffer(message.length()); - for(var i = 0; i < buffer.length; ++i) { - buffer[i] = message.at(i); - } - return buffer; -} - -var gf0 = gf(); -var gf1 = gf([1]); -var D = gf([ - 0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, - 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]); -var D2 = gf([ - 0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, - 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]); -var X = gf([ - 0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, - 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]); -var Y = gf([ - 0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, - 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]); -var L = new Float64Array([ - 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, - 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); -var I = gf([ - 0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, - 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); - -// TODO: update forge buffer implementation to use `Buffer` or `Uint8Array`, -// whichever is available, to improve performance -function sha512(msg, msgLen) { - // Note: `out` and `msg` are NativeBuffer - var md = forge$5.md.sha512.create(); - var buffer = new ByteBuffer(msg); - md.update(buffer.getBytes(msgLen), 'binary'); - var hash = md.digest().getBytes(); - if(typeof Buffer !== 'undefined') { - return Buffer.from(hash, 'binary'); - } - var out = new NativeBuffer(ed25519.constants.HASH_BYTE_LENGTH); - for(var i = 0; i < 64; ++i) { - out[i] = hash.charCodeAt(i); - } - return out; -} - -function crypto_sign_keypair(pk, sk) { - var p = [gf(), gf(), gf(), gf()]; - var i; - - var d = sha512(sk, 32); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - scalarbase(p, d); - pack(pk, p); - - for(i = 0; i < 32; ++i) { - sk[i + 32] = pk[i]; - } - return 0; -} - -// Note: difference from C - smlen returned, not passed as argument. -function crypto_sign(sm, m, n, sk) { - var i, j, x = new Float64Array(64); - var p = [gf(), gf(), gf(), gf()]; - - var d = sha512(sk, 32); - d[0] &= 248; - d[31] &= 127; - d[31] |= 64; - - var smlen = n + 64; - for(i = 0; i < n; ++i) { - sm[64 + i] = m[i]; - } - for(i = 0; i < 32; ++i) { - sm[32 + i] = d[32 + i]; - } - - var r = sha512(sm.subarray(32), n + 32); - reduce(r); - scalarbase(p, r); - pack(sm, p); - - for(i = 32; i < 64; ++i) { - sm[i] = sk[i]; - } - var h = sha512(sm, n + 64); - reduce(h); - - for(i = 32; i < 64; ++i) { - x[i] = 0; - } - for(i = 0; i < 32; ++i) { - x[i] = r[i]; - } - for(i = 0; i < 32; ++i) { - for(j = 0; j < 32; j++) { - x[i + j] += h[i] * d[j]; - } - } - - modL(sm.subarray(32), x); - return smlen; -} - -function crypto_sign_open(m, sm, n, pk) { - var i, mlen; - var t = new NativeBuffer(32); - var p = [gf(), gf(), gf(), gf()], - q = [gf(), gf(), gf(), gf()]; - - mlen = -1; - if(n < 64) { - return -1; - } - - if(unpackneg(q, pk)) { - return -1; - } - - for(i = 0; i < n; ++i) { - m[i] = sm[i]; - } - for(i = 0; i < 32; ++i) { - m[i + 32] = pk[i]; - } - var h = sha512(m, n); - reduce(h); - scalarmult(p, q, h); - - scalarbase(q, sm.subarray(32)); - add(p, q); - pack(t, p); - - n -= 64; - if(crypto_verify_32(sm, 0, t, 0)) { - for(i = 0; i < n; ++i) { - m[i] = 0; - } - return -1; - } - - for(i = 0; i < n; ++i) { - m[i] = sm[i + 64]; - } - mlen = n; - return mlen; -} - -function modL(r, x) { - var carry, i, j, k; - for(i = 63; i >= 32; --i) { - carry = 0; - for(j = i - 32, k = i - 12; j < k; ++j) { - x[j] += carry - 16 * x[i] * L[j - (i - 32)]; - carry = (x[j] + 128) >> 8; - x[j] -= carry * 256; - } - x[j] += carry; - x[i] = 0; - } - carry = 0; - for(j = 0; j < 32; ++j) { - x[j] += carry - (x[31] >> 4) * L[j]; - carry = x[j] >> 8; - x[j] &= 255; - } - for(j = 0; j < 32; ++j) { - x[j] -= carry * L[j]; - } - for(i = 0; i < 32; ++i) { - x[i + 1] += x[i] >> 8; - r[i] = x[i] & 255; - } -} - -function reduce(r) { - var x = new Float64Array(64); - for(var i = 0; i < 64; ++i) { - x[i] = r[i]; - r[i] = 0; - } - modL(r, x); -} - -function add(p, q) { - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(), - g = gf(), h = gf(), t = gf(); - - Z(a, p[1], p[0]); - Z(t, q[1], q[0]); - M(a, a, t); - A(b, p[0], p[1]); - A(t, q[0], q[1]); - M(b, b, t); - M(c, p[3], q[3]); - M(c, c, D2); - M(d, p[2], q[2]); - A(d, d, d); - Z(e, b, a); - Z(f, d, c); - A(g, d, c); - A(h, b, a); - - M(p[0], e, f); - M(p[1], h, g); - M(p[2], g, f); - M(p[3], e, h); -} - -function cswap(p, q, b) { - for(var i = 0; i < 4; ++i) { - sel25519(p[i], q[i], b); - } -} - -function pack(r, p) { - var tx = gf(), ty = gf(), zi = gf(); - inv25519(zi, p[2]); - M(tx, p[0], zi); - M(ty, p[1], zi); - pack25519(r, ty); - r[31] ^= par25519(tx) << 7; -} - -function pack25519(o, n) { - var i, j, b; - var m = gf(), t = gf(); - for(i = 0; i < 16; ++i) { - t[i] = n[i]; - } - car25519(t); - car25519(t); - car25519(t); - for(j = 0; j < 2; ++j) { - m[0] = t[0] - 0xffed; - for(i = 1; i < 15; ++i) { - m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); - m[i-1] &= 0xffff; - } - m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); - b = (m[15] >> 16) & 1; - m[14] &= 0xffff; - sel25519(t, m, 1 - b); - } - for (i = 0; i < 16; i++) { - o[2 * i] = t[i] & 0xff; - o[2 * i + 1] = t[i] >> 8; - } -} - -function unpackneg(r, p) { - var t = gf(), chk = gf(), num = gf(), - den = gf(), den2 = gf(), den4 = gf(), - den6 = gf(); - - set25519(r[2], gf1); - unpack25519(r[1], p); - S(num, r[1]); - M(den, num, D); - Z(num, num, r[2]); - A(den, r[2], den); - - S(den2, den); - S(den4, den2); - M(den6, den4, den2); - M(t, den6, num); - M(t, t, den); - - pow2523(t, t); - M(t, t, num); - M(t, t, den); - M(t, t, den); - M(r[0], t, den); - - S(chk, r[0]); - M(chk, chk, den); - if(neq25519(chk, num)) { - M(r[0], r[0], I); - } - - S(chk, r[0]); - M(chk, chk, den); - if(neq25519(chk, num)) { - return -1; - } - - if(par25519(r[0]) === (p[31] >> 7)) { - Z(r[0], gf0, r[0]); - } - - M(r[3], r[0], r[1]); - return 0; -} - -function unpack25519(o, n) { - var i; - for(i = 0; i < 16; ++i) { - o[i] = n[2 * i] + (n[2 * i + 1] << 8); - } - o[15] &= 0x7fff; -} - -function pow2523(o, i) { - var c = gf(); - var a; - for(a = 0; a < 16; ++a) { - c[a] = i[a]; - } - for(a = 250; a >= 0; --a) { - S(c, c); - if(a !== 1) { - M(c, c, i); - } - } - for(a = 0; a < 16; ++a) { - o[a] = c[a]; - } -} - -function neq25519(a, b) { - var c = new NativeBuffer(32); - var d = new NativeBuffer(32); - pack25519(c, a); - pack25519(d, b); - return crypto_verify_32(c, 0, d, 0); -} - -function crypto_verify_32(x, xi, y, yi) { - return vn(x, xi, y, yi, 32); -} - -function vn(x, xi, y, yi, n) { - var i, d = 0; - for(i = 0; i < n; ++i) { - d |= x[xi + i] ^ y[yi + i]; - } - return (1 & ((d - 1) >>> 8)) - 1; -} - -function par25519(a) { - var d = new NativeBuffer(32); - pack25519(d, a); - return d[0] & 1; -} - -function scalarmult(p, q, s) { - var b, i; - set25519(p[0], gf0); - set25519(p[1], gf1); - set25519(p[2], gf1); - set25519(p[3], gf0); - for(i = 255; i >= 0; --i) { - b = (s[(i / 8)|0] >> (i & 7)) & 1; - cswap(p, q, b); - add(q, p); - add(p, p); - cswap(p, q, b); - } -} - -function scalarbase(p, s) { - var q = [gf(), gf(), gf(), gf()]; - set25519(q[0], X); - set25519(q[1], Y); - set25519(q[2], gf1); - M(q[3], X, Y); - scalarmult(p, q, s); -} - -function set25519(r, a) { - var i; - for(i = 0; i < 16; i++) { - r[i] = a[i] | 0; - } -} - -function inv25519(o, i) { - var c = gf(); - var a; - for(a = 0; a < 16; ++a) { - c[a] = i[a]; - } - for(a = 253; a >= 0; --a) { - S(c, c); - if(a !== 2 && a !== 4) { - M(c, c, i); - } - } - for(a = 0; a < 16; ++a) { - o[a] = c[a]; - } -} - -function car25519(o) { - var i, v, c = 1; - for(i = 0; i < 16; ++i) { - v = o[i] + c + 65535; - c = Math.floor(v / 65536); - o[i] = v - c * 65536; - } - o[0] += c - 1 + 37 * (c - 1); -} - -function sel25519(p, q, b) { - var t, c = ~(b - 1); - for(var i = 0; i < 16; ++i) { - t = c & (p[i] ^ q[i]); - p[i] ^= t; - q[i] ^= t; - } -} - -function gf(init) { - var i, r = new Float64Array(16); - if(init) { - for(i = 0; i < init.length; ++i) { - r[i] = init[i]; - } - } - return r; -} - -function A(o, a, b) { - for(var i = 0; i < 16; ++i) { - o[i] = a[i] + b[i]; - } -} - -function Z(o, a, b) { - for(var i = 0; i < 16; ++i) { - o[i] = a[i] - b[i]; - } -} - -function S(o, a) { - M(o, a, a); -} - -function M(o, a, b) { - var v, c, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, - t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, - t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, - b0 = b[0], - b1 = b[1], - b2 = b[2], - b3 = b[3], - b4 = b[4], - b5 = b[5], - b6 = b[6], - b7 = b[7], - b8 = b[8], - b9 = b[9], - b10 = b[10], - b11 = b[11], - b12 = b[12], - b13 = b[13], - b14 = b[14], - b15 = b[15]; - - v = a[0]; - t0 += v * b0; - t1 += v * b1; - t2 += v * b2; - t3 += v * b3; - t4 += v * b4; - t5 += v * b5; - t6 += v * b6; - t7 += v * b7; - t8 += v * b8; - t9 += v * b9; - t10 += v * b10; - t11 += v * b11; - t12 += v * b12; - t13 += v * b13; - t14 += v * b14; - t15 += v * b15; - v = a[1]; - t1 += v * b0; - t2 += v * b1; - t3 += v * b2; - t4 += v * b3; - t5 += v * b4; - t6 += v * b5; - t7 += v * b6; - t8 += v * b7; - t9 += v * b8; - t10 += v * b9; - t11 += v * b10; - t12 += v * b11; - t13 += v * b12; - t14 += v * b13; - t15 += v * b14; - t16 += v * b15; - v = a[2]; - t2 += v * b0; - t3 += v * b1; - t4 += v * b2; - t5 += v * b3; - t6 += v * b4; - t7 += v * b5; - t8 += v * b6; - t9 += v * b7; - t10 += v * b8; - t11 += v * b9; - t12 += v * b10; - t13 += v * b11; - t14 += v * b12; - t15 += v * b13; - t16 += v * b14; - t17 += v * b15; - v = a[3]; - t3 += v * b0; - t4 += v * b1; - t5 += v * b2; - t6 += v * b3; - t7 += v * b4; - t8 += v * b5; - t9 += v * b6; - t10 += v * b7; - t11 += v * b8; - t12 += v * b9; - t13 += v * b10; - t14 += v * b11; - t15 += v * b12; - t16 += v * b13; - t17 += v * b14; - t18 += v * b15; - v = a[4]; - t4 += v * b0; - t5 += v * b1; - t6 += v * b2; - t7 += v * b3; - t8 += v * b4; - t9 += v * b5; - t10 += v * b6; - t11 += v * b7; - t12 += v * b8; - t13 += v * b9; - t14 += v * b10; - t15 += v * b11; - t16 += v * b12; - t17 += v * b13; - t18 += v * b14; - t19 += v * b15; - v = a[5]; - t5 += v * b0; - t6 += v * b1; - t7 += v * b2; - t8 += v * b3; - t9 += v * b4; - t10 += v * b5; - t11 += v * b6; - t12 += v * b7; - t13 += v * b8; - t14 += v * b9; - t15 += v * b10; - t16 += v * b11; - t17 += v * b12; - t18 += v * b13; - t19 += v * b14; - t20 += v * b15; - v = a[6]; - t6 += v * b0; - t7 += v * b1; - t8 += v * b2; - t9 += v * b3; - t10 += v * b4; - t11 += v * b5; - t12 += v * b6; - t13 += v * b7; - t14 += v * b8; - t15 += v * b9; - t16 += v * b10; - t17 += v * b11; - t18 += v * b12; - t19 += v * b13; - t20 += v * b14; - t21 += v * b15; - v = a[7]; - t7 += v * b0; - t8 += v * b1; - t9 += v * b2; - t10 += v * b3; - t11 += v * b4; - t12 += v * b5; - t13 += v * b6; - t14 += v * b7; - t15 += v * b8; - t16 += v * b9; - t17 += v * b10; - t18 += v * b11; - t19 += v * b12; - t20 += v * b13; - t21 += v * b14; - t22 += v * b15; - v = a[8]; - t8 += v * b0; - t9 += v * b1; - t10 += v * b2; - t11 += v * b3; - t12 += v * b4; - t13 += v * b5; - t14 += v * b6; - t15 += v * b7; - t16 += v * b8; - t17 += v * b9; - t18 += v * b10; - t19 += v * b11; - t20 += v * b12; - t21 += v * b13; - t22 += v * b14; - t23 += v * b15; - v = a[9]; - t9 += v * b0; - t10 += v * b1; - t11 += v * b2; - t12 += v * b3; - t13 += v * b4; - t14 += v * b5; - t15 += v * b6; - t16 += v * b7; - t17 += v * b8; - t18 += v * b9; - t19 += v * b10; - t20 += v * b11; - t21 += v * b12; - t22 += v * b13; - t23 += v * b14; - t24 += v * b15; - v = a[10]; - t10 += v * b0; - t11 += v * b1; - t12 += v * b2; - t13 += v * b3; - t14 += v * b4; - t15 += v * b5; - t16 += v * b6; - t17 += v * b7; - t18 += v * b8; - t19 += v * b9; - t20 += v * b10; - t21 += v * b11; - t22 += v * b12; - t23 += v * b13; - t24 += v * b14; - t25 += v * b15; - v = a[11]; - t11 += v * b0; - t12 += v * b1; - t13 += v * b2; - t14 += v * b3; - t15 += v * b4; - t16 += v * b5; - t17 += v * b6; - t18 += v * b7; - t19 += v * b8; - t20 += v * b9; - t21 += v * b10; - t22 += v * b11; - t23 += v * b12; - t24 += v * b13; - t25 += v * b14; - t26 += v * b15; - v = a[12]; - t12 += v * b0; - t13 += v * b1; - t14 += v * b2; - t15 += v * b3; - t16 += v * b4; - t17 += v * b5; - t18 += v * b6; - t19 += v * b7; - t20 += v * b8; - t21 += v * b9; - t22 += v * b10; - t23 += v * b11; - t24 += v * b12; - t25 += v * b13; - t26 += v * b14; - t27 += v * b15; - v = a[13]; - t13 += v * b0; - t14 += v * b1; - t15 += v * b2; - t16 += v * b3; - t17 += v * b4; - t18 += v * b5; - t19 += v * b6; - t20 += v * b7; - t21 += v * b8; - t22 += v * b9; - t23 += v * b10; - t24 += v * b11; - t25 += v * b12; - t26 += v * b13; - t27 += v * b14; - t28 += v * b15; - v = a[14]; - t14 += v * b0; - t15 += v * b1; - t16 += v * b2; - t17 += v * b3; - t18 += v * b4; - t19 += v * b5; - t20 += v * b6; - t21 += v * b7; - t22 += v * b8; - t23 += v * b9; - t24 += v * b10; - t25 += v * b11; - t26 += v * b12; - t27 += v * b13; - t28 += v * b14; - t29 += v * b15; - v = a[15]; - t15 += v * b0; - t16 += v * b1; - t17 += v * b2; - t18 += v * b3; - t19 += v * b4; - t20 += v * b5; - t21 += v * b6; - t22 += v * b7; - t23 += v * b8; - t24 += v * b9; - t25 += v * b10; - t26 += v * b11; - t27 += v * b12; - t28 += v * b13; - t29 += v * b14; - t30 += v * b15; - - t0 += 38 * t16; - t1 += 38 * t17; - t2 += 38 * t18; - t3 += 38 * t19; - t4 += 38 * t20; - t5 += 38 * t21; - t6 += 38 * t22; - t7 += 38 * t23; - t8 += 38 * t24; - t9 += 38 * t25; - t10 += 38 * t26; - t11 += 38 * t27; - t12 += 38 * t28; - t13 += 38 * t29; - t14 += 38 * t30; - // t15 left as is - - // first car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - // second car - c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - o[ 0] = t0; - o[ 1] = t1; - o[ 2] = t2; - o[ 3] = t3; - o[ 4] = t4; - o[ 5] = t5; - o[ 6] = t6; - o[ 7] = t7; - o[ 8] = t8; - o[ 9] = t9; - o[10] = t10; - o[11] = t11; - o[12] = t12; - o[13] = t13; - o[14] = t14; - o[15] = t15; -} - -/** - * Javascript implementation of RSA-KEM. - * - * @author Lautaro Cozzani Rodriguez - * @author Dave Longley - * - * Copyright (c) 2014 Lautaro Cozzani - * Copyright (c) 2014 Digital Bazaar, Inc. - */ - -var forge$4 = forge$D; - - - - -forge$4.kem = forge$4.kem || {}; - -var BigInteger = forge$4.jsbn.BigInteger; - -/** - * The API for the RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2. - */ -forge$4.kem.rsa = {}; - -/** - * Creates an RSA KEM API object for generating a secret asymmetric key. - * - * The symmetric key may be generated via a call to 'encrypt', which will - * produce a ciphertext to be transmitted to the recipient and a key to be - * kept secret. The ciphertext is a parameter to be passed to 'decrypt' which - * will produce the same secret key for the recipient to use to decrypt a - * message that was encrypted with the secret key. - * - * @param kdf the KDF API to use (eg: new forge.kem.kdf1()). - * @param options the options to use. - * [prng] a custom crypto-secure pseudo-random number generator to use, - * that must define "getBytesSync". - */ -forge$4.kem.rsa.create = function(kdf, options) { - options = options || {}; - var prng = options.prng || forge$4.random; - - var kem = {}; - - /** - * Generates a secret key and its encapsulation. - * - * @param publicKey the RSA public key to encrypt with. - * @param keyLength the length, in bytes, of the secret key to generate. - * - * @return an object with: - * encapsulation: the ciphertext for generating the secret key, as a - * binary-encoded string of bytes. - * key: the secret key to use for encrypting a message. - */ - kem.encrypt = function(publicKey, keyLength) { - // generate a random r where 1 < r < n - var byteLength = Math.ceil(publicKey.n.bitLength() / 8); - var r; - do { - r = new BigInteger( - forge$4.util.bytesToHex(prng.getBytesSync(byteLength)), - 16).mod(publicKey.n); - } while(r.compareTo(BigInteger.ONE) <= 0); - - // prepend r with zeros - r = forge$4.util.hexToBytes(r.toString(16)); - var zeros = byteLength - r.length; - if(zeros > 0) { - r = forge$4.util.fillString(String.fromCharCode(0), zeros) + r; - } - - // encrypt the random - var encapsulation = publicKey.encrypt(r, 'NONE'); - - // generate the secret key - var key = kdf.generate(r, keyLength); - - return {encapsulation: encapsulation, key: key}; - }; - - /** - * Decrypts an encapsulated secret key. - * - * @param privateKey the RSA private key to decrypt with. - * @param encapsulation the ciphertext for generating the secret key, as - * a binary-encoded string of bytes. - * @param keyLength the length, in bytes, of the secret key to generate. - * - * @return the secret key as a binary-encoded string of bytes. - */ - kem.decrypt = function(privateKey, encapsulation, keyLength) { - // decrypt the encapsulation and generate the secret key - var r = privateKey.decrypt(encapsulation, 'NONE'); - return kdf.generate(r, keyLength); - }; - - return kem; -}; - -// TODO: add forge.kem.kdf.create('KDF1', {md: ..., ...}) API? - -/** - * Creates a key derivation API object that implements KDF1 per ISO 18033-2. - * - * @param md the hash API to use. - * @param [digestLength] an optional digest length that must be positive and - * less than or equal to md.digestLength. - * - * @return a KDF1 API object. - */ -forge$4.kem.kdf1 = function(md, digestLength) { - _createKDF(this, md, 0, digestLength || md.digestLength); -}; - -/** - * Creates a key derivation API object that implements KDF2 per ISO 18033-2. - * - * @param md the hash API to use. - * @param [digestLength] an optional digest length that must be positive and - * less than or equal to md.digestLength. - * - * @return a KDF2 API object. - */ -forge$4.kem.kdf2 = function(md, digestLength) { - _createKDF(this, md, 1, digestLength || md.digestLength); -}; - -/** - * Creates a KDF1 or KDF2 API object. - * - * @param md the hash API to use. - * @param counterStart the starting index for the counter. - * @param digestLength the digest length to use. - * - * @return the KDF API object. - */ -function _createKDF(kdf, md, counterStart, digestLength) { - /** - * Generate a key of the specified length. - * - * @param x the binary-encoded byte string to generate a key from. - * @param length the number of bytes to generate (the size of the key). - * - * @return the key as a binary-encoded string. - */ - kdf.generate = function(x, length) { - var key = new forge$4.util.ByteBuffer(); - - // run counter from counterStart to ceil(length / Hash.len) - var k = Math.ceil(length / digestLength) + counterStart; - - var c = new forge$4.util.ByteBuffer(); - for(var i = counterStart; i < k; ++i) { - // I2OSP(i, 4): convert counter to an octet string of 4 octets - c.putInt32(i); - - // digest 'x' and the counter and add the result to the key - md.start(); - md.update(x + c.getBytes()); - var hash = md.digest(); - key.putBytes(hash.getBytes(digestLength)); - } - - // truncate to the correct key length - key.truncate(key.length() - length); - return key.getBytes(); - }; -} - -/** - * Cross-browser support for logging in a web application. - * - * @author David I. Lehn - * - * Copyright (c) 2008-2013 Digital Bazaar, Inc. - */ - -var forge$3 = forge$D; - - -/* LOG API */ -forge$3.log = forge$3.log || {}; - -/** - * Application logging system. - * - * Each logger level available as it's own function of the form: - * forge.log.level(category, args...) - * The category is an arbitrary string, and the args are the same as - * Firebug's console.log API. By default the call will be output as: - * 'LEVEL [category] , args[1], ...' - * This enables proper % formatting via the first argument. - * Each category is enabled by default but can be enabled or disabled with - * the setCategoryEnabled() function. - */ -// list of known levels -forge$3.log.levels = [ - 'none', 'error', 'warning', 'info', 'debug', 'verbose', 'max']; -// info on the levels indexed by name: -// index: level index -// name: uppercased display name -var sLevelInfo = {}; -// list of loggers -var sLoggers = []; -/** - * Standard console logger. If no console support is enabled this will - * remain null. Check before using. - */ -var sConsoleLogger = null; - -// logger flags -/** - * Lock the level at the current value. Used in cases where user config may - * set the level such that only critical messages are seen but more verbose - * messages are needed for debugging or other purposes. - */ -forge$3.log.LEVEL_LOCKED = (1 << 1); -/** - * Always call log function. By default, the logging system will check the - * message level against logger.level before calling the log function. This - * flag allows the function to do its own check. - */ -forge$3.log.NO_LEVEL_CHECK = (1 << 2); -/** - * Perform message interpolation with the passed arguments. "%" style - * fields in log messages will be replaced by arguments as needed. Some - * loggers, such as Firebug, may do this automatically. The original log - * message will be available as 'message' and the interpolated version will - * be available as 'fullMessage'. - */ -forge$3.log.INTERPOLATE = (1 << 3); - -// setup each log level -for(var i = 0; i < forge$3.log.levels.length; ++i) { - var level = forge$3.log.levels[i]; - sLevelInfo[level] = { - index: i, - name: level.toUpperCase() - }; -} - -/** - * Message logger. Will dispatch a message to registered loggers as needed. - * - * @param message message object - */ -forge$3.log.logMessage = function(message) { - var messageLevelIndex = sLevelInfo[message.level].index; - for(var i = 0; i < sLoggers.length; ++i) { - var logger = sLoggers[i]; - if(logger.flags & forge$3.log.NO_LEVEL_CHECK) { - logger.f(message); - } else { - // get logger level - var loggerLevelIndex = sLevelInfo[logger.level].index; - // check level - if(messageLevelIndex <= loggerLevelIndex) { - // message critical enough, call logger - logger.f(logger, message); - } - } - } -}; - -/** - * Sets the 'standard' key on a message object to: - * "LEVEL [category] " + message - * - * @param message a message log object - */ -forge$3.log.prepareStandard = function(message) { - if(!('standard' in message)) { - message.standard = - sLevelInfo[message.level].name + - //' ' + +message.timestamp + - ' [' + message.category + '] ' + - message.message; - } -}; - -/** - * Sets the 'full' key on a message object to the original message - * interpolated via % formatting with the message arguments. - * - * @param message a message log object. - */ -forge$3.log.prepareFull = function(message) { - if(!('full' in message)) { - // copy args and insert message at the front - var args = [message.message]; - args = args.concat([] || message['arguments']); - // format the message - message.full = forge$3.util.format.apply(this, args); - } -}; - -/** - * Applies both preparseStandard() and prepareFull() to a message object and - * store result in 'standardFull'. - * - * @param message a message log object. - */ -forge$3.log.prepareStandardFull = function(message) { - if(!('standardFull' in message)) { - // FIXME implement 'standardFull' logging - forge$3.log.prepareStandard(message); - message.standardFull = message.standard; - } -}; - -// create log level functions -{ - // levels for which we want functions - var levels = ['error', 'warning', 'info', 'debug', 'verbose']; - for(var i = 0; i < levels.length; ++i) { - // wrap in a function to ensure proper level var is passed - (function(level) { - // create function for this level - forge$3.log[level] = function(category, message/*, args...*/) { - // convert arguments to real array, remove category and message - var args = Array.prototype.slice.call(arguments).slice(2); - // create message object - // Note: interpolation and standard formatting is done lazily - var msg = { - timestamp: new Date(), - level: level, - category: category, - message: message, - 'arguments': args - /*standard*/ - /*full*/ - /*fullMessage*/ - }; - // process this message - forge$3.log.logMessage(msg); - }; - })(levels[i]); - } -} - -/** - * Creates a new logger with specified custom logging function. - * - * The logging function has a signature of: - * function(logger, message) - * logger: current logger - * message: object: - * level: level id - * category: category - * message: string message - * arguments: Array of extra arguments - * fullMessage: interpolated message and arguments if INTERPOLATE flag set - * - * @param logFunction a logging function which takes a log message object - * as a parameter. - * - * @return a logger object. - */ -forge$3.log.makeLogger = function(logFunction) { - var logger = { - flags: 0, - f: logFunction - }; - forge$3.log.setLevel(logger, 'none'); - return logger; -}; - -/** - * Sets the current log level on a logger. - * - * @param logger the target logger. - * @param level the new maximum log level as a string. - * - * @return true if set, false if not. - */ -forge$3.log.setLevel = function(logger, level) { - var rval = false; - if(logger && !(logger.flags & forge$3.log.LEVEL_LOCKED)) { - for(var i = 0; i < forge$3.log.levels.length; ++i) { - var aValidLevel = forge$3.log.levels[i]; - if(level == aValidLevel) { - // set level - logger.level = level; - rval = true; - break; - } - } - } - - return rval; -}; - -/** - * Locks the log level at its current value. - * - * @param logger the target logger. - * @param lock boolean lock value, default to true. - */ -forge$3.log.lock = function(logger, lock) { - if(typeof lock === 'undefined' || lock) { - logger.flags |= forge$3.log.LEVEL_LOCKED; - } else { - logger.flags &= ~forge$3.log.LEVEL_LOCKED; - } -}; - -/** - * Adds a logger. - * - * @param logger the logger object. - */ -forge$3.log.addLogger = function(logger) { - sLoggers.push(logger); -}; - -// setup the console logger if possible, else create fake console.log -if(typeof(console) !== 'undefined' && 'log' in console) { - var logger; - if(console.error && console.warn && console.info && console.debug) { - // looks like Firebug-style logging is available - // level handlers map - var levelHandlers = { - error: console.error, - warning: console.warn, - info: console.info, - debug: console.debug, - verbose: console.debug - }; - var f = function(logger, message) { - forge$3.log.prepareStandard(message); - var handler = levelHandlers[message.level]; - // prepend standard message and concat args - var args = [message.standard]; - args = args.concat(message['arguments'].slice()); - // apply to low-level console function - handler.apply(console, args); - }; - logger = forge$3.log.makeLogger(f); - } else { - // only appear to have basic console.log - var f = function(logger, message) { - forge$3.log.prepareStandardFull(message); - console.log(message.standardFull); - }; - logger = forge$3.log.makeLogger(f); - } - forge$3.log.setLevel(logger, 'debug'); - forge$3.log.addLogger(logger); - sConsoleLogger = logger; -} else { - // define fake console.log to avoid potential script errors on - // browsers that do not have console logging - console = { - log: function() {} - }; -} - -/* - * Check for logging control query vars in current URL. - * - * console.level= - * Set's the console log level by name. Useful to override defaults and - * allow more verbose logging before a user config is loaded. - * - * console.lock= - * Lock the console log level at whatever level it is set at. This is run - * after console.level is processed. Useful to force a level of verbosity - * that could otherwise be limited by a user config. - */ -if(sConsoleLogger !== null && - typeof window !== 'undefined' && window.location -) { - var query = new URL(window.location.href).searchParams; - if(query.has('console.level')) { - // set with last value - forge$3.log.setLevel( - sConsoleLogger, query.get('console.level').slice(-1)[0]); - } - if(query.has('console.lock')) { - // set with last value - var lock = query.get('console.lock').slice(-1)[0]; - if(lock == 'true') { - forge$3.log.lock(sConsoleLogger); - } - } -} - -// provide public access to console logger -forge$3.log.consoleLogger = sConsoleLogger; - -/** - * Javascript implementation of PKCS#7 v1.5. - * - * @author Stefan Siegl - * @author Dave Longley - * - * Copyright (c) 2012 Stefan Siegl - * Copyright (c) 2012-2015 Digital Bazaar, Inc. - * - * Currently this implementation only supports ContentType of EnvelopedData, - * EncryptedData, or SignedData at the root level. The top level elements may - * contain only a ContentInfo of ContentType Data, i.e. plain data. Further - * nesting is not (yet) supported. - * - * The Forge validators for PKCS #7's ASN.1 structures are available from - * a separate file pkcs7asn1.js, since those are referenced from other - * PKCS standards like PKCS #12. - */ - -var forge$2 = forge$D; - - - - - - - - - - -// shortcut for ASN.1 API -var asn1 = forge$2.asn1; - -// shortcut for PKCS#7 API -var p7 = forge$2.pkcs7 = forge$2.pkcs7 || {}; - -/** - * Converts a PKCS#7 message from PEM format. - * - * @param pem the PEM-formatted PKCS#7 message. - * - * @return the PKCS#7 message. - */ -p7.messageFromPem = function(pem) { - var msg = forge$2.pem.decode(pem)[0]; - - if(msg.type !== 'PKCS7') { - var error = new Error('Could not convert PKCS#7 message from PEM; PEM ' + - 'header type is not "PKCS#7".'); - error.headerType = msg.type; - throw error; - } - if(msg.procType && msg.procType.type === 'ENCRYPTED') { - throw new Error('Could not convert PKCS#7 message from PEM; PEM is encrypted.'); - } - - // convert DER to ASN.1 object - var obj = asn1.fromDer(msg.body); - - return p7.messageFromAsn1(obj); -}; - -/** - * Converts a PKCS#7 message to PEM format. - * - * @param msg The PKCS#7 message object - * @param maxline The maximum characters per line, defaults to 64. - * - * @return The PEM-formatted PKCS#7 message. - */ -p7.messageToPem = function(msg, maxline) { - // convert to ASN.1, then DER, then PEM-encode - var pemObj = { - type: 'PKCS7', - body: asn1.toDer(msg.toAsn1()).getBytes() - }; - return forge$2.pem.encode(pemObj, {maxline: maxline}); -}; - -/** - * Converts a PKCS#7 message from an ASN.1 object. - * - * @param obj the ASN.1 representation of a ContentInfo. - * - * @return the PKCS#7 message. - */ -p7.messageFromAsn1 = function(obj) { - // validate root level ContentInfo and capture data - var capture = {}; - var errors = []; - if(!asn1.validate(obj, p7.asn1.contentInfoValidator, capture, errors)) { - var error = new Error('Cannot read PKCS#7 message. ' + - 'ASN.1 object is not an PKCS#7 ContentInfo.'); - error.errors = errors; - throw error; - } - - var contentType = asn1.derToOid(capture.contentType); - var msg; - - switch(contentType) { - case forge$2.pki.oids.envelopedData: - msg = p7.createEnvelopedData(); - break; - - case forge$2.pki.oids.encryptedData: - msg = p7.createEncryptedData(); - break; - - case forge$2.pki.oids.signedData: - msg = p7.createSignedData(); - break; - - default: - throw new Error('Cannot read PKCS#7 message. ContentType with OID ' + - contentType + ' is not (yet) supported.'); - } - - msg.fromAsn1(capture.content.value[0]); - return msg; -}; - -p7.createSignedData = function() { - var msg = null; - msg = { - type: forge$2.pki.oids.signedData, - version: 1, - certificates: [], - crls: [], - // TODO: add json-formatted signer stuff here? - signers: [], - // populated during sign() - digestAlgorithmIdentifiers: [], - contentInfo: null, - signerInfos: [], - - fromAsn1: function(obj) { - // validate SignedData content block and capture data. - _fromAsn1(msg, obj, p7.asn1.signedDataValidator); - msg.certificates = []; - msg.crls = []; - msg.digestAlgorithmIdentifiers = []; - msg.contentInfo = null; - msg.signerInfos = []; - - if(msg.rawCapture.certificates) { - var certs = msg.rawCapture.certificates.value; - for(var i = 0; i < certs.length; ++i) { - msg.certificates.push(forge$2.pki.certificateFromAsn1(certs[i])); - } - } - - // TODO: parse crls - }, - - toAsn1: function() { - // degenerate case with no content - if(!msg.contentInfo) { - msg.sign(); - } - - var certs = []; - for(var i = 0; i < msg.certificates.length; ++i) { - certs.push(forge$2.pki.certificateToAsn1(msg.certificates[i])); - } - - var crls = []; - // TODO: implement CRLs - - // [0] SignedData - var signedData = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // Version - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, - asn1.integerToDer(msg.version).getBytes()), - // DigestAlgorithmIdentifiers - asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.SET, true, - msg.digestAlgorithmIdentifiers), - // ContentInfo - msg.contentInfo - ]) - ]); - if(certs.length > 0) { - // [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL - signedData.value[0].value.push( - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, certs)); - } - if(crls.length > 0) { - // [1] IMPLICIT CertificateRevocationLists OPTIONAL - signedData.value[0].value.push( - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, crls)); - } - // SignerInfos - signedData.value[0].value.push( - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, - msg.signerInfos)); - - // ContentInfo - return asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // ContentType - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(msg.type).getBytes()), - // [0] SignedData - signedData - ]); - }, - - /** - * Add (another) entity to list of signers. - * - * Note: If authenticatedAttributes are provided, then, per RFC 2315, - * they must include at least two attributes: content type and - * message digest. The message digest attribute value will be - * auto-calculated during signing and will be ignored if provided. - * - * Here's an example of providing these two attributes: - * - * forge.pkcs7.createSignedData(); - * p7.addSigner({ - * issuer: cert.issuer.attributes, - * serialNumber: cert.serialNumber, - * key: privateKey, - * digestAlgorithm: forge.pki.oids.sha1, - * authenticatedAttributes: [{ - * type: forge.pki.oids.contentType, - * value: forge.pki.oids.data - * }, { - * type: forge.pki.oids.messageDigest - * }] - * }); - * - * TODO: Support [subjectKeyIdentifier] as signer's ID. - * - * @param signer the signer information: - * key the signer's private key. - * [certificate] a certificate containing the public key - * associated with the signer's private key; use this option as - * an alternative to specifying signer.issuer and - * signer.serialNumber. - * [issuer] the issuer attributes (eg: cert.issuer.attributes). - * [serialNumber] the signer's certificate's serial number in - * hexadecimal (eg: cert.serialNumber). - * [digestAlgorithm] the message digest OID, as a string, to use - * (eg: forge.pki.oids.sha1). - * [authenticatedAttributes] an optional array of attributes - * to also sign along with the content. - */ - addSigner: function(signer) { - var issuer = signer.issuer; - var serialNumber = signer.serialNumber; - if(signer.certificate) { - var cert = signer.certificate; - if(typeof cert === 'string') { - cert = forge$2.pki.certificateFromPem(cert); - } - issuer = cert.issuer.attributes; - serialNumber = cert.serialNumber; - } - var key = signer.key; - if(!key) { - throw new Error( - 'Could not add PKCS#7 signer; no private key specified.'); - } - if(typeof key === 'string') { - key = forge$2.pki.privateKeyFromPem(key); - } - - // ensure OID known for digest algorithm - var digestAlgorithm = signer.digestAlgorithm || forge$2.pki.oids.sha1; - switch(digestAlgorithm) { - case forge$2.pki.oids.sha1: - case forge$2.pki.oids.sha256: - case forge$2.pki.oids.sha384: - case forge$2.pki.oids.sha512: - case forge$2.pki.oids.md5: - break; - default: - throw new Error( - 'Could not add PKCS#7 signer; unknown message digest algorithm: ' + - digestAlgorithm); - } - - // if authenticatedAttributes is present, then the attributes - // must contain at least PKCS #9 content-type and message-digest - var authenticatedAttributes = signer.authenticatedAttributes || []; - if(authenticatedAttributes.length > 0) { - var contentType = false; - var messageDigest = false; - for(var i = 0; i < authenticatedAttributes.length; ++i) { - var attr = authenticatedAttributes[i]; - if(!contentType && attr.type === forge$2.pki.oids.contentType) { - contentType = true; - if(messageDigest) { - break; - } - continue; - } - if(!messageDigest && attr.type === forge$2.pki.oids.messageDigest) { - messageDigest = true; - if(contentType) { - break; - } - continue; - } - } - - if(!contentType || !messageDigest) { - throw new Error('Invalid signer.authenticatedAttributes. If ' + - 'signer.authenticatedAttributes is specified, then it must ' + - 'contain at least two attributes, PKCS #9 content-type and ' + - 'PKCS #9 message-digest.'); - } - } - - msg.signers.push({ - key: key, - version: 1, - issuer: issuer, - serialNumber: serialNumber, - digestAlgorithm: digestAlgorithm, - signatureAlgorithm: forge$2.pki.oids.rsaEncryption, - signature: null, - authenticatedAttributes: authenticatedAttributes, - unauthenticatedAttributes: [] - }); - }, - - /** - * Signs the content. - * @param options Options to apply when signing: - * [detached] boolean. If signing should be done in detached mode. Defaults to false. - */ - sign: function(options) { - options = options || {}; - // auto-generate content info - if(typeof msg.content !== 'object' || msg.contentInfo === null) { - // use Data ContentInfo - msg.contentInfo = asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // ContentType - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(forge$2.pki.oids.data).getBytes()) - ]); - - // add actual content, if present - if('content' in msg) { - var content; - if(msg.content instanceof forge$2.util.ByteBuffer) { - content = msg.content.bytes(); - } else if(typeof msg.content === 'string') { - content = forge$2.util.encodeUtf8(msg.content); - } - - if (options.detached) { - msg.detachedContent = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, content); - } else { - msg.contentInfo.value.push( - // [0] EXPLICIT content - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, - content) - ])); - } - } - } - - // no signers, return early (degenerate case for certificate container) - if(msg.signers.length === 0) { - return; - } - - // generate digest algorithm identifiers - var mds = addDigestAlgorithmIds(); - - // generate signerInfos - addSignerInfos(mds); - }, - - verify: function() { - throw new Error('PKCS#7 signature verification not yet implemented.'); - }, - - /** - * Add a certificate. - * - * @param cert the certificate to add. - */ - addCertificate: function(cert) { - // convert from PEM - if(typeof cert === 'string') { - cert = forge$2.pki.certificateFromPem(cert); - } - msg.certificates.push(cert); - }, - - /** - * Add a certificate revokation list. - * - * @param crl the certificate revokation list to add. - */ - addCertificateRevokationList: function(crl) { - throw new Error('PKCS#7 CRL support not yet implemented.'); - } - }; - return msg; - - function addDigestAlgorithmIds() { - var mds = {}; - - for(var i = 0; i < msg.signers.length; ++i) { - var signer = msg.signers[i]; - var oid = signer.digestAlgorithm; - if(!(oid in mds)) { - // content digest - mds[oid] = forge$2.md[forge$2.pki.oids[oid]].create(); - } - if(signer.authenticatedAttributes.length === 0) { - // no custom attributes to digest; use content message digest - signer.md = mds[oid]; - } else { - // custom attributes to be digested; use own message digest - // TODO: optimize to just copy message digest state if that - // feature is ever supported with message digests - signer.md = forge$2.md[forge$2.pki.oids[oid]].create(); - } - } - - // add unique digest algorithm identifiers - msg.digestAlgorithmIdentifiers = []; - for(var oid in mds) { - msg.digestAlgorithmIdentifiers.push( - // AlgorithmIdentifier - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // algorithm - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(oid).getBytes()), - // parameters (null) - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') - ])); - } - - return mds; - } - - function addSignerInfos(mds) { - var content; - - if (msg.detachedContent) { - // Signature has been made in detached mode. - content = msg.detachedContent; - } else { - // Note: ContentInfo is a SEQUENCE with 2 values, second value is - // the content field and is optional for a ContentInfo but required here - // since signers are present - // get ContentInfo content - content = msg.contentInfo.value[1]; - // skip [0] EXPLICIT content wrapper - content = content.value[0]; - } - - if(!content) { - throw new Error( - 'Could not sign PKCS#7 message; there is no content to sign.'); - } - - // get ContentInfo content type - var contentType = asn1.derToOid(msg.contentInfo.value[0].value); - - // serialize content - var bytes = asn1.toDer(content); - - // skip identifier and length per RFC 2315 9.3 - // skip identifier (1 byte) - bytes.getByte(); - // read and discard length bytes - asn1.getBerValueLength(bytes); - bytes = bytes.getBytes(); - - // digest content DER value bytes - for(var oid in mds) { - mds[oid].start().update(bytes); - } - - // sign content - var signingTime = new Date(); - for(var i = 0; i < msg.signers.length; ++i) { - var signer = msg.signers[i]; - - if(signer.authenticatedAttributes.length === 0) { - // if ContentInfo content type is not "Data", then - // authenticatedAttributes must be present per RFC 2315 - if(contentType !== forge$2.pki.oids.data) { - throw new Error( - 'Invalid signer; authenticatedAttributes must be present ' + - 'when the ContentInfo content type is not PKCS#7 Data.'); - } - } else { - // process authenticated attributes - // [0] IMPLICIT - signer.authenticatedAttributesAsn1 = asn1.create( - asn1.Class.CONTEXT_SPECIFIC, 0, true, []); - - // per RFC 2315, attributes are to be digested using a SET container - // not the above [0] IMPLICIT container - var attrsAsn1 = asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.SET, true, []); - - for(var ai = 0; ai < signer.authenticatedAttributes.length; ++ai) { - var attr = signer.authenticatedAttributes[ai]; - if(attr.type === forge$2.pki.oids.messageDigest) { - // use content message digest as value - attr.value = mds[signer.digestAlgorithm].digest(); - } else if(attr.type === forge$2.pki.oids.signingTime) { - // auto-populate signing time if not already set - if(!attr.value) { - attr.value = signingTime; - } - } - - // convert to ASN.1 and push onto Attributes SET (for signing) and - // onto authenticatedAttributesAsn1 to complete SignedData ASN.1 - // TODO: optimize away duplication - attrsAsn1.value.push(_attributeToAsn1(attr)); - signer.authenticatedAttributesAsn1.value.push(_attributeToAsn1(attr)); - } - - // DER-serialize and digest SET OF attributes only - bytes = asn1.toDer(attrsAsn1).getBytes(); - signer.md.start().update(bytes); - } - - // sign digest - signer.signature = signer.key.sign(signer.md, 'RSASSA-PKCS1-V1_5'); - } - - // add signer info - msg.signerInfos = _signersToAsn1(msg.signers); - } -}; - -/** - * Creates an empty PKCS#7 message of type EncryptedData. - * - * @return the message. - */ -p7.createEncryptedData = function() { - var msg = null; - msg = { - type: forge$2.pki.oids.encryptedData, - version: 0, - encryptedContent: { - algorithm: forge$2.pki.oids['aes256-CBC'] - }, - - /** - * Reads an EncryptedData content block (in ASN.1 format) - * - * @param obj The ASN.1 representation of the EncryptedData content block - */ - fromAsn1: function(obj) { - // Validate EncryptedData content block and capture data. - _fromAsn1(msg, obj, p7.asn1.encryptedDataValidator); - }, - - /** - * Decrypt encrypted content - * - * @param key The (symmetric) key as a byte buffer - */ - decrypt: function(key) { - if(key !== undefined) { - msg.encryptedContent.key = key; - } - _decryptContent(msg); - } - }; - return msg; -}; - -/** - * Creates an empty PKCS#7 message of type EnvelopedData. - * - * @return the message. - */ -p7.createEnvelopedData = function() { - var msg = null; - msg = { - type: forge$2.pki.oids.envelopedData, - version: 0, - recipients: [], - encryptedContent: { - algorithm: forge$2.pki.oids['aes256-CBC'] - }, - - /** - * Reads an EnvelopedData content block (in ASN.1 format) - * - * @param obj the ASN.1 representation of the EnvelopedData content block. - */ - fromAsn1: function(obj) { - // validate EnvelopedData content block and capture data - var capture = _fromAsn1(msg, obj, p7.asn1.envelopedDataValidator); - msg.recipients = _recipientsFromAsn1(capture.recipientInfos.value); - }, - - toAsn1: function() { - // ContentInfo - return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // ContentType - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(msg.type).getBytes()), - // [0] EnvelopedData - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // Version - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, - asn1.integerToDer(msg.version).getBytes()), - // RecipientInfos - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, - _recipientsToAsn1(msg.recipients)), - // EncryptedContentInfo - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, - _encryptedContentToAsn1(msg.encryptedContent)) - ]) - ]) - ]); - }, - - /** - * Find recipient by X.509 certificate's issuer. - * - * @param cert the certificate with the issuer to look for. - * - * @return the recipient object. - */ - findRecipient: function(cert) { - var sAttr = cert.issuer.attributes; - - for(var i = 0; i < msg.recipients.length; ++i) { - var r = msg.recipients[i]; - var rAttr = r.issuer; - - if(r.serialNumber !== cert.serialNumber) { - continue; - } - - if(rAttr.length !== sAttr.length) { - continue; - } - - var match = true; - for(var j = 0; j < sAttr.length; ++j) { - if(rAttr[j].type !== sAttr[j].type || - rAttr[j].value !== sAttr[j].value) { - match = false; - break; - } - } - - if(match) { - return r; - } - } - - return null; - }, - - /** - * Decrypt enveloped content - * - * @param recipient The recipient object related to the private key - * @param privKey The (RSA) private key object - */ - decrypt: function(recipient, privKey) { - if(msg.encryptedContent.key === undefined && recipient !== undefined && - privKey !== undefined) { - switch(recipient.encryptedContent.algorithm) { - case forge$2.pki.oids.rsaEncryption: - case forge$2.pki.oids.desCBC: - var key = privKey.decrypt(recipient.encryptedContent.content); - msg.encryptedContent.key = forge$2.util.createBuffer(key); - break; - - default: - throw new Error('Unsupported asymmetric cipher, ' + - 'OID ' + recipient.encryptedContent.algorithm); - } - } - - _decryptContent(msg); - }, - - /** - * Add (another) entity to list of recipients. - * - * @param cert The certificate of the entity to add. - */ - addRecipient: function(cert) { - msg.recipients.push({ - version: 0, - issuer: cert.issuer.attributes, - serialNumber: cert.serialNumber, - encryptedContent: { - // We simply assume rsaEncryption here, since forge.pki only - // supports RSA so far. If the PKI module supports other - // ciphers one day, we need to modify this one as well. - algorithm: forge$2.pki.oids.rsaEncryption, - key: cert.publicKey - } - }); - }, - - /** - * Encrypt enveloped content. - * - * This function supports two optional arguments, cipher and key, which - * can be used to influence symmetric encryption. Unless cipher is - * provided, the cipher specified in encryptedContent.algorithm is used - * (defaults to AES-256-CBC). If no key is provided, encryptedContent.key - * is (re-)used. If that one's not set, a random key will be generated - * automatically. - * - * @param [key] The key to be used for symmetric encryption. - * @param [cipher] The OID of the symmetric cipher to use. - */ - encrypt: function(key, cipher) { - // Part 1: Symmetric encryption - if(msg.encryptedContent.content === undefined) { - cipher = cipher || msg.encryptedContent.algorithm; - key = key || msg.encryptedContent.key; - - var keyLen, ivLen, ciphFn; - switch(cipher) { - case forge$2.pki.oids['aes128-CBC']: - keyLen = 16; - ivLen = 16; - ciphFn = forge$2.aes.createEncryptionCipher; - break; - - case forge$2.pki.oids['aes192-CBC']: - keyLen = 24; - ivLen = 16; - ciphFn = forge$2.aes.createEncryptionCipher; - break; - - case forge$2.pki.oids['aes256-CBC']: - keyLen = 32; - ivLen = 16; - ciphFn = forge$2.aes.createEncryptionCipher; - break; - - case forge$2.pki.oids['des-EDE3-CBC']: - keyLen = 24; - ivLen = 8; - ciphFn = forge$2.des.createEncryptionCipher; - break; - - default: - throw new Error('Unsupported symmetric cipher, OID ' + cipher); - } - - if(key === undefined) { - key = forge$2.util.createBuffer(forge$2.random.getBytes(keyLen)); - } else if(key.length() != keyLen) { - throw new Error('Symmetric key has wrong length; ' + - 'got ' + key.length() + ' bytes, expected ' + keyLen + '.'); - } - - // Keep a copy of the key & IV in the object, so the caller can - // use it for whatever reason. - msg.encryptedContent.algorithm = cipher; - msg.encryptedContent.key = key; - msg.encryptedContent.parameter = forge$2.util.createBuffer( - forge$2.random.getBytes(ivLen)); - - var ciph = ciphFn(key); - ciph.start(msg.encryptedContent.parameter.copy()); - ciph.update(msg.content); - - // The finish function does PKCS#7 padding by default, therefore - // no action required by us. - if(!ciph.finish()) { - throw new Error('Symmetric encryption failed.'); - } - - msg.encryptedContent.content = ciph.output; - } - - // Part 2: asymmetric encryption for each recipient - for(var i = 0; i < msg.recipients.length; ++i) { - var recipient = msg.recipients[i]; - - // Nothing to do, encryption already done. - if(recipient.encryptedContent.content !== undefined) { - continue; - } - - switch(recipient.encryptedContent.algorithm) { - case forge$2.pki.oids.rsaEncryption: - recipient.encryptedContent.content = - recipient.encryptedContent.key.encrypt( - msg.encryptedContent.key.data); - break; - - default: - throw new Error('Unsupported asymmetric cipher, OID ' + - recipient.encryptedContent.algorithm); - } - } - } - }; - return msg; -}; - -/** - * Converts a single recipient from an ASN.1 object. - * - * @param obj the ASN.1 RecipientInfo. - * - * @return the recipient object. - */ -function _recipientFromAsn1(obj) { - // validate EnvelopedData content block and capture data - var capture = {}; - var errors = []; - if(!asn1.validate(obj, p7.asn1.recipientInfoValidator, capture, errors)) { - var error = new Error('Cannot read PKCS#7 RecipientInfo. ' + - 'ASN.1 object is not an PKCS#7 RecipientInfo.'); - error.errors = errors; - throw error; - } - - return { - version: capture.version.charCodeAt(0), - issuer: forge$2.pki.RDNAttributesAsArray(capture.issuer), - serialNumber: forge$2.util.createBuffer(capture.serial).toHex(), - encryptedContent: { - algorithm: asn1.derToOid(capture.encAlgorithm), - parameter: capture.encParameter ? capture.encParameter.value : undefined, - content: capture.encKey - } - }; -} - -/** - * Converts a single recipient object to an ASN.1 object. - * - * @param obj the recipient object. - * - * @return the ASN.1 RecipientInfo. - */ -function _recipientToAsn1(obj) { - return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // Version - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, - asn1.integerToDer(obj.version).getBytes()), - // IssuerAndSerialNumber - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // Name - forge$2.pki.distinguishedNameToAsn1({attributes: obj.issuer}), - // Serial - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, - forge$2.util.hexToBytes(obj.serialNumber)) - ]), - // KeyEncryptionAlgorithmIdentifier - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // Algorithm - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(obj.encryptedContent.algorithm).getBytes()), - // Parameter, force NULL, only RSA supported for now. - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') - ]), - // EncryptedKey - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, - obj.encryptedContent.content) - ]); -} - -/** - * Map a set of RecipientInfo ASN.1 objects to recipient objects. - * - * @param infos an array of ASN.1 representations RecipientInfo (i.e. SET OF). - * - * @return an array of recipient objects. - */ -function _recipientsFromAsn1(infos) { - var ret = []; - for(var i = 0; i < infos.length; ++i) { - ret.push(_recipientFromAsn1(infos[i])); - } - return ret; -} - -/** - * Map an array of recipient objects to ASN.1 RecipientInfo objects. - * - * @param recipients an array of recipientInfo objects. - * - * @return an array of ASN.1 RecipientInfos. - */ -function _recipientsToAsn1(recipients) { - var ret = []; - for(var i = 0; i < recipients.length; ++i) { - ret.push(_recipientToAsn1(recipients[i])); - } - return ret; -} - -/** - * Converts a single signerInfo object to an ASN.1 object. - * - * @param obj the signerInfo object. - * - * @return the ASN.1 representation of a SignerInfo. - */ -function _signerToAsn1(obj) { - // SignerInfo - var rval = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // version - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, - asn1.integerToDer(obj.version).getBytes()), - // issuerAndSerialNumber - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // name - forge$2.pki.distinguishedNameToAsn1({attributes: obj.issuer}), - // serial - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, - forge$2.util.hexToBytes(obj.serialNumber)) - ]), - // digestAlgorithm - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // algorithm - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(obj.digestAlgorithm).getBytes()), - // parameters (null) - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') - ]) - ]); - - // authenticatedAttributes (OPTIONAL) - if(obj.authenticatedAttributesAsn1) { - // add ASN.1 previously generated during signing - rval.value.push(obj.authenticatedAttributesAsn1); - } - - // digestEncryptionAlgorithm - rval.value.push(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // algorithm - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(obj.signatureAlgorithm).getBytes()), - // parameters (null) - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, '') - ])); - - // encryptedDigest - rval.value.push(asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, obj.signature)); - - // unauthenticatedAttributes (OPTIONAL) - if(obj.unauthenticatedAttributes.length > 0) { - // [1] IMPLICIT - var attrsAsn1 = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 1, true, []); - for(var i = 0; i < obj.unauthenticatedAttributes.length; ++i) { - var attr = obj.unauthenticatedAttributes[i]; - attrsAsn1.values.push(_attributeToAsn1(attr)); - } - rval.value.push(attrsAsn1); - } - - return rval; -} - -/** - * Map an array of signer objects to ASN.1 objects. - * - * @param signers an array of signer objects. - * - * @return an array of ASN.1 SignerInfos. - */ -function _signersToAsn1(signers) { - var ret = []; - for(var i = 0; i < signers.length; ++i) { - ret.push(_signerToAsn1(signers[i])); - } - return ret; -} - -/** - * Convert an attribute object to an ASN.1 Attribute. - * - * @param attr the attribute object. - * - * @return the ASN.1 Attribute. - */ -function _attributeToAsn1(attr) { - var value; - - // TODO: generalize to support more attributes - if(attr.type === forge$2.pki.oids.contentType) { - value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(attr.value).getBytes()); - } else if(attr.type === forge$2.pki.oids.messageDigest) { - value = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, - attr.value.bytes()); - } else if(attr.type === forge$2.pki.oids.signingTime) { - /* Note per RFC 2985: Dates between 1 January 1950 and 31 December 2049 - (inclusive) MUST be encoded as UTCTime. Any dates with year values - before 1950 or after 2049 MUST be encoded as GeneralizedTime. [Further,] - UTCTime values MUST be expressed in Greenwich Mean Time (Zulu) and MUST - include seconds (i.e., times are YYMMDDHHMMSSZ), even where the - number of seconds is zero. Midnight (GMT) must be represented as - "YYMMDD000000Z". */ - // TODO: make these module-level constants - var jan_1_1950 = new Date('1950-01-01T00:00:00Z'); - var jan_1_2050 = new Date('2050-01-01T00:00:00Z'); - var date = attr.value; - if(typeof date === 'string') { - // try to parse date - var timestamp = Date.parse(date); - if(!isNaN(timestamp)) { - date = new Date(timestamp); - } else if(date.length === 13) { - // YYMMDDHHMMSSZ (13 chars for UTCTime) - date = asn1.utcTimeToDate(date); - } else { - // assume generalized time - date = asn1.generalizedTimeToDate(date); - } - } - - if(date >= jan_1_1950 && date < jan_1_2050) { - value = asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.UTCTIME, false, - asn1.dateToUtcTime(date)); - } else { - value = asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.GENERALIZEDTIME, false, - asn1.dateToGeneralizedTime(date)); - } - } - - // TODO: expose as common API call - // create a RelativeDistinguishedName set - // each value in the set is an AttributeTypeAndValue first - // containing the type (an OID) and second the value - return asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // AttributeType - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(attr.type).getBytes()), - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SET, true, [ - // AttributeValue - value - ]) - ]); -} - -/** - * Map messages encrypted content to ASN.1 objects. - * - * @param ec The encryptedContent object of the message. - * - * @return ASN.1 representation of the encryptedContent object (SEQUENCE). - */ -function _encryptedContentToAsn1(ec) { - return [ - // ContentType, always Data for the moment - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(forge$2.pki.oids.data).getBytes()), - // ContentEncryptionAlgorithmIdentifier - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [ - // Algorithm - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, - asn1.oidToDer(ec.algorithm).getBytes()), - // Parameters (IV) - !ec.parameter ? - undefined : - asn1.create( - asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, - ec.parameter.getBytes()) - ]), - // [0] EncryptedContent - asn1.create(asn1.Class.CONTEXT_SPECIFIC, 0, true, [ - asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, - ec.content.getBytes()) - ]) - ]; -} - -/** - * Reads the "common part" of an PKCS#7 content block (in ASN.1 format) - * - * This function reads the "common part" of the PKCS#7 content blocks - * EncryptedData and EnvelopedData, i.e. version number and symmetrically - * encrypted content block. - * - * The result of the ASN.1 validate and capture process is returned - * to allow the caller to extract further data, e.g. the list of recipients - * in case of a EnvelopedData object. - * - * @param msg the PKCS#7 object to read the data to. - * @param obj the ASN.1 representation of the content block. - * @param validator the ASN.1 structure validator object to use. - * - * @return the value map captured by validator object. - */ -function _fromAsn1(msg, obj, validator) { - var capture = {}; - var errors = []; - if(!asn1.validate(obj, validator, capture, errors)) { - var error = new Error('Cannot read PKCS#7 message. ' + - 'ASN.1 object is not a supported PKCS#7 message.'); - error.errors = error; - throw error; - } - - // Check contentType, so far we only support (raw) Data. - var contentType = asn1.derToOid(capture.contentType); - if(contentType !== forge$2.pki.oids.data) { - throw new Error('Unsupported PKCS#7 message. ' + - 'Only wrapped ContentType Data supported.'); - } - - if(capture.encryptedContent) { - var content = ''; - if(forge$2.util.isArray(capture.encryptedContent)) { - for(var i = 0; i < capture.encryptedContent.length; ++i) { - if(capture.encryptedContent[i].type !== asn1.Type.OCTETSTRING) { - throw new Error('Malformed PKCS#7 message, expecting encrypted ' + - 'content constructed of only OCTET STRING objects.'); - } - content += capture.encryptedContent[i].value; - } - } else { - content = capture.encryptedContent; - } - msg.encryptedContent = { - algorithm: asn1.derToOid(capture.encAlgorithm), - parameter: forge$2.util.createBuffer(capture.encParameter.value), - content: forge$2.util.createBuffer(content) - }; - } - - if(capture.content) { - var content = ''; - if(forge$2.util.isArray(capture.content)) { - for(var i = 0; i < capture.content.length; ++i) { - if(capture.content[i].type !== asn1.Type.OCTETSTRING) { - throw new Error('Malformed PKCS#7 message, expecting ' + - 'content constructed of only OCTET STRING objects.'); - } - content += capture.content[i].value; - } - } else { - content = capture.content; - } - msg.content = forge$2.util.createBuffer(content); - } - - msg.version = capture.version.charCodeAt(0); - msg.rawCapture = capture; - - return capture; -} - -/** - * Decrypt the symmetrically encrypted content block of the PKCS#7 message. - * - * Decryption is skipped in case the PKCS#7 message object already has a - * (decrypted) content attribute. The algorithm, key and cipher parameters - * (probably the iv) are taken from the encryptedContent attribute of the - * message object. - * - * @param The PKCS#7 message object. - */ -function _decryptContent(msg) { - if(msg.encryptedContent.key === undefined) { - throw new Error('Symmetric key not available.'); - } - - if(msg.content === undefined) { - var ciph; - - switch(msg.encryptedContent.algorithm) { - case forge$2.pki.oids['aes128-CBC']: - case forge$2.pki.oids['aes192-CBC']: - case forge$2.pki.oids['aes256-CBC']: - ciph = forge$2.aes.createDecryptionCipher(msg.encryptedContent.key); - break; - - case forge$2.pki.oids['desCBC']: - case forge$2.pki.oids['des-EDE3-CBC']: - ciph = forge$2.des.createDecryptionCipher(msg.encryptedContent.key); - break; - - default: - throw new Error('Unsupported symmetric cipher, OID ' + - msg.encryptedContent.algorithm); - } - ciph.start(msg.encryptedContent.parameter); - ciph.update(msg.encryptedContent.content); - - if(!ciph.finish()) { - throw new Error('Symmetric decryption failed.'); - } - - msg.content = ciph.output; - } -} - -/** - * Functions to output keys in SSH-friendly formats. - * - * This is part of the Forge project which may be used under the terms of - * either the BSD License or the GNU General Public License (GPL) Version 2. - * - * See: https://github.com/digitalbazaar/forge/blob/cbebca3780658703d925b61b2caffb1d263a6c1d/LICENSE - * - * @author https://github.com/shellac - */ - -var forge$1 = forge$D; - - - - - - -var ssh = forge$1.ssh = forge$1.ssh || {}; - -/** - * Encodes (and optionally encrypts) a private RSA key as a Putty PPK file. - * - * @param privateKey the key. - * @param passphrase a passphrase to protect the key (falsy for no encryption). - * @param comment a comment to include in the key file. - * - * @return the PPK file as a string. - */ -ssh.privateKeyToPutty = function(privateKey, passphrase, comment) { - comment = comment || ''; - passphrase = passphrase || ''; - var algorithm = 'ssh-rsa'; - var encryptionAlgorithm = (passphrase === '') ? 'none' : 'aes256-cbc'; - - var ppk = 'PuTTY-User-Key-File-2: ' + algorithm + '\r\n'; - ppk += 'Encryption: ' + encryptionAlgorithm + '\r\n'; - ppk += 'Comment: ' + comment + '\r\n'; - - // public key into buffer for ppk - var pubbuffer = forge$1.util.createBuffer(); - _addStringToBuffer(pubbuffer, algorithm); - _addBigIntegerToBuffer(pubbuffer, privateKey.e); - _addBigIntegerToBuffer(pubbuffer, privateKey.n); - - // write public key - var pub = forge$1.util.encode64(pubbuffer.bytes(), 64); - var length = Math.floor(pub.length / 66) + 1; // 66 = 64 + \r\n - ppk += 'Public-Lines: ' + length + '\r\n'; - ppk += pub; - - // private key into a buffer - var privbuffer = forge$1.util.createBuffer(); - _addBigIntegerToBuffer(privbuffer, privateKey.d); - _addBigIntegerToBuffer(privbuffer, privateKey.p); - _addBigIntegerToBuffer(privbuffer, privateKey.q); - _addBigIntegerToBuffer(privbuffer, privateKey.qInv); - - // optionally encrypt the private key - var priv; - if(!passphrase) { - // use the unencrypted buffer - priv = forge$1.util.encode64(privbuffer.bytes(), 64); - } else { - // encrypt RSA key using passphrase - var encLen = privbuffer.length() + 16 - 1; - encLen -= encLen % 16; - - // pad private key with sha1-d data -- needs to be a multiple of 16 - var padding = _sha1(privbuffer.bytes()); - - padding.truncate(padding.length() - encLen + privbuffer.length()); - privbuffer.putBuffer(padding); - - var aeskey = forge$1.util.createBuffer(); - aeskey.putBuffer(_sha1('\x00\x00\x00\x00', passphrase)); - aeskey.putBuffer(_sha1('\x00\x00\x00\x01', passphrase)); - - // encrypt some bytes using CBC mode - // key is 40 bytes, so truncate *by* 8 bytes - var cipher = forge$1.aes.createEncryptionCipher(aeskey.truncate(8), 'CBC'); - cipher.start(forge$1.util.createBuffer().fillWithByte(0, 16)); - cipher.update(privbuffer.copy()); - cipher.finish(); - var encrypted = cipher.output; - - // Note: this appears to differ from Putty -- is forge wrong, or putty? - // due to padding we finish as an exact multiple of 16 - encrypted.truncate(16); // all padding - - priv = forge$1.util.encode64(encrypted.bytes(), 64); - } - - // output private key - length = Math.floor(priv.length / 66) + 1; // 64 + \r\n - ppk += '\r\nPrivate-Lines: ' + length + '\r\n'; - ppk += priv; - - // MAC - var mackey = _sha1('putty-private-key-file-mac-key', passphrase); - - var macbuffer = forge$1.util.createBuffer(); - _addStringToBuffer(macbuffer, algorithm); - _addStringToBuffer(macbuffer, encryptionAlgorithm); - _addStringToBuffer(macbuffer, comment); - macbuffer.putInt32(pubbuffer.length()); - macbuffer.putBuffer(pubbuffer); - macbuffer.putInt32(privbuffer.length()); - macbuffer.putBuffer(privbuffer); - - var hmac = forge$1.hmac.create(); - hmac.start('sha1', mackey); - hmac.update(macbuffer.bytes()); - - ppk += '\r\nPrivate-MAC: ' + hmac.digest().toHex() + '\r\n'; - - return ppk; -}; - -/** - * Encodes a public RSA key as an OpenSSH file. - * - * @param key the key. - * @param comment a comment. - * - * @return the public key in OpenSSH format. - */ -ssh.publicKeyToOpenSSH = function(key, comment) { - var type = 'ssh-rsa'; - comment = comment || ''; - - var buffer = forge$1.util.createBuffer(); - _addStringToBuffer(buffer, type); - _addBigIntegerToBuffer(buffer, key.e); - _addBigIntegerToBuffer(buffer, key.n); - - return type + ' ' + forge$1.util.encode64(buffer.bytes()) + ' ' + comment; -}; - -/** - * Encodes a private RSA key as an OpenSSH file. - * - * @param key the key. - * @param passphrase a passphrase to protect the key (falsy for no encryption). - * - * @return the public key in OpenSSH format. - */ -ssh.privateKeyToOpenSSH = function(privateKey, passphrase) { - if(!passphrase) { - return forge$1.pki.privateKeyToPem(privateKey); - } - // OpenSSH private key is just a legacy format, it seems - return forge$1.pki.encryptRsaPrivateKey(privateKey, passphrase, - {legacy: true, algorithm: 'aes128'}); -}; - -/** - * Gets the SSH fingerprint for the given public key. - * - * @param options the options to use. - * [md] the message digest object to use (defaults to forge.md.md5). - * [encoding] an alternative output encoding, such as 'hex' - * (defaults to none, outputs a byte buffer). - * [delimiter] the delimiter to use between bytes for 'hex' encoded - * output, eg: ':' (defaults to none). - * - * @return the fingerprint as a byte buffer or other encoding based on options. - */ -ssh.getPublicKeyFingerprint = function(key, options) { - options = options || {}; - var md = options.md || forge$1.md.md5.create(); - - var type = 'ssh-rsa'; - var buffer = forge$1.util.createBuffer(); - _addStringToBuffer(buffer, type); - _addBigIntegerToBuffer(buffer, key.e); - _addBigIntegerToBuffer(buffer, key.n); - - // hash public key bytes - md.start(); - md.update(buffer.getBytes()); - var digest = md.digest(); - if(options.encoding === 'hex') { - var hex = digest.toHex(); - if(options.delimiter) { - return hex.match(/.{2}/g).join(options.delimiter); - } - return hex; - } else if(options.encoding === 'binary') { - return digest.getBytes(); - } else if(options.encoding) { - throw new Error('Unknown encoding "' + options.encoding + '".'); - } - return digest; -}; - -/** - * Adds len(val) then val to a buffer. - * - * @param buffer the buffer to add to. - * @param val a big integer. - */ -function _addBigIntegerToBuffer(buffer, val) { - var hexVal = val.toString(16); - // ensure 2s complement +ve - if(hexVal[0] >= '8') { - hexVal = '00' + hexVal; - } - var bytes = forge$1.util.hexToBytes(hexVal); - buffer.putInt32(bytes.length); - buffer.putBytes(bytes); -} - -/** - * Adds len(val) then val to a buffer. - * - * @param buffer the buffer to add to. - * @param val a string. - */ -function _addStringToBuffer(buffer, val) { - buffer.putInt32(val.length); - buffer.putString(val); -} - -/** - * Hashes the arguments into one value using SHA-1. - * - * @return the sha1 hash of the provided arguments. - */ -function _sha1() { - var sha = forge$1.md.sha1.create(); - var num = arguments.length; - for (var i = 0; i < num; ++i) { - sha.update(arguments[i]); - } - return sha.digest(); -} - -/** - * Node.js module for Forge. - * - * @author Dave Longley - * - * Copyright 2011-2016 Digital Bazaar, Inc. - */ - -var lib = forge$D; - -const forge = /*@__PURE__*/getDefaultExportFromCjs(lib); - -let isDockerCached; -function isDocker() { - if (isDockerCached === void 0) { - isDockerCached = _hasDockerEnvironment() || _hasDockerCGroup(); - } - return isDockerCached; -} -function _hasDockerEnvironment() { - try { - statSync("/.dockerenv"); - return true; - } catch { - return false; - } -} -function _hasDockerCGroup() { - try { - return readFileSync("/proc/self/cgroup", "utf8").includes("docker"); - } catch { - return false; - } -} - -let isWSLCached; -function isWsl() { - if (isWSLCached === void 0) { - isWSLCached = _isWsl(); - } - return isWSLCached; -} -function _isWsl() { - if (process.platform !== "linux") { - return false; - } - if (os.release().toLowerCase().includes("microsoft")) { - if (isDocker()) { - return false; - } - return true; - } - try { - return readFileSync("/proc/version", "utf8").toLowerCase().includes("microsoft") ? !isDocker() : false; - } catch { - return false; - } -} -const defaultMountPoint = "/mnt/"; -let _wslMountpoint; -function getWslDrivesMountPoint() { - if (_wslMountpoint) { - return _wslMountpoint; - } - const configFilePath = "/etc/wsl.conf"; - let isConfigFileExists = false; - try { - accessSync(configFilePath, constants.F_OK); - isConfigFileExists = true; - } catch { - } - if (!isConfigFileExists) { - return defaultMountPoint; - } - const configContent = readFileSync(configFilePath, { encoding: "utf8" }); - const configMountPoint = /(?.*)/g.exec( - configContent - ); - if (!configMountPoint || !configMountPoint.groups) { - return defaultMountPoint; - } - _wslMountpoint = configMountPoint.groups.mountPoint.trim(); - _wslMountpoint = _wslMountpoint.endsWith("/") ? _wslMountpoint : `${_wslMountpoint}/`; - return _wslMountpoint; -} - -async function open(target, options = {}) { - let command; - const cliArguments = []; - const childProcessOptions = {}; - if (process.platform === "darwin") { - command = "open"; - if (options.wait) { - cliArguments.push("--wait-apps"); - } - if (options.background) { - cliArguments.push("--background"); - } - if (options.newInstance) { - cliArguments.push("--new"); - } - } else if (process.platform === "win32" || isWsl() && !isDocker()) { - command = isWsl() ? `${getWslDrivesMountPoint()}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe` : `${process.env.SYSTEMROOT}\\System32\\WindowsPowerShell\\v1.0\\powershell`; - cliArguments.push( - "-NoProfile", - "-NonInteractive", - "\u2013ExecutionPolicy", - "Bypass", - "-EncodedCommand" - ); - if (!isWsl()) { - childProcessOptions.windowsVerbatimArguments = true; - } - const encodedArguments = ["Start"]; - if (options.wait) { - encodedArguments.push("-Wait"); - } - encodedArguments.push(target); - target = Buffer.from(encodedArguments.join(" "), "utf16le").toString( - "base64" - ); - } else { - command = "xdg-open"; - const useSystemXdgOpen = process.versions.electron || process.platform === "android"; - if (!useSystemXdgOpen) { - command = join(os.tmpdir(), "xdg-open"); - if (!fs.existsSync(command)) { - try { - fs.writeFileSync( - join(os.tmpdir(), "xdg-open"), - await import('./xdg-open.mjs').then((r) => r.xdgOpenScript()), - "utf8" - ); - fs.chmodSync( - command, - 493 - /* rwx r-x r-x */ - ); - } catch { - command = "xdg-open"; - } - } - } - if (!options.wait) { - childProcessOptions.stdio = "ignore"; - childProcessOptions.detached = true; - } - } - cliArguments.push(target); - const subprocess = childProcess.spawn( - command, - cliArguments, - childProcessOptions - ); - if (options.wait) { - return new Promise((resolve, reject) => { - subprocess.once("error", reject); - subprocess.once("close", (exitCode) => { - if (options.allowNonzeroExitCode && exitCode > 0) { - reject(new Error(`Exited with code ${exitCode}`)); - return; - } - resolve(subprocess); - }); - }); - } - subprocess.unref(); - return subprocess; -} - -function getNetworkInterfaces(includeIPV6) { - const addrs = /* @__PURE__ */ new Set(); - for (const details of Object.values(networkInterfaces())) { - if (details) { - for (const d of details) { - if (!d.internal && !(d.mac === "00:00:00:00:00:00") && !d.address.startsWith("fe80::") && !(!includeIPV6 && (d.family === "IPv6" || +d.family === 6))) { - addrs.add(formatAddress(d)); - } - } - } - } - return [...addrs].sort(); -} -function formatAddress(addr) { - return addr.family === "IPv6" || addr.family === 6 ? `[${addr.address}]` : addr.address; -} -function formatURL(url) { - return colors.cyan( - colors.underline( - decodeURI(url).replace(/:(\d+)\//g, `:${colors.bold("$1")}/`) - ) - ); -} -const _localHosts = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "::1"]); -function isLocalhost(hostname) { - return hostname === void 0 ? false : _localHosts.has(hostname); -} -const _anyHosts = /* @__PURE__ */ new Set(["", "0.0.0.0", "::"]); -function isAnyhost(hostname) { - return hostname === void 0 ? false : _anyHosts.has(hostname); -} -function generateURL(hostname, listhenOptions, baseURL) { - const proto = listhenOptions.https ? "https://" : "http://"; - let port = listhenOptions.port || ""; - if (port === 80 && proto === "http://" || port === 443 && proto === "https://") { - port = ""; - } - if (hostname[0] !== "[" && hostname.includes(":")) { - hostname = `[${hostname}]`; - } - return proto + (hostname || "localhost") + ":" + port + (baseURL || listhenOptions.baseURL || ""); -} -function getDefaultHost(preferPublic) { - if (isDocker() || isWsl()) { - return ""; - } - return preferPublic ? "" : "localhost"; -} -function getPublicURL(listhenOptions, baseURL) { - if (listhenOptions.publicURL) { - return listhenOptions.publicURL; - } - if (d === "stackblitz") { - const stackblitzURL = detectStackblitzURL(listhenOptions._entry); - if (stackblitzURL) { - return stackblitzURL; - } - } - if (listhenOptions.hostname && !isLocalhost(listhenOptions.hostname) && !isAnyhost(listhenOptions.hostname)) { - return generateURL(listhenOptions.hostname, listhenOptions, baseURL); - } -} -function detectStackblitzURL(entry) { - try { - const cwd = process.env.PWD || ""; - if (cwd.startsWith("/home/projects")) { - const projectId = cwd.split("/")[3]; - const relativeEntry = entry && relative(process.cwd(), entry).replace(/^\.\//, ""); - const query = relativeEntry ? `?file=${relativeEntry}` : ""; - return `https://stackblitz.com/edit/${projectId}${query}`; - } - if (cwd.startsWith("/home")) { - const githubRepo = cwd.split("/").slice(2).join("/"); - return `https://stackblitz.com/edit/~/github.com/${githubRepo}`; - } - } catch (error) { - console.error(error); - } -} -const HOSTNAME_RE = /^(?!-)[\d.:A-Za-z-]{1,63}(? options && options.includeBoundaries - ? `(?:(?<=\\s|^)(?=${word})|(?<=${word})(?=\\s|$))` - : ''; - -const v4 = '(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}'; - -const v6segment = '[a-fA-F\\d]{1,4}'; - -const v6 = ` -(?: -(?:${v6segment}:){7}(?:${v6segment}|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8 -(?:${v6segment}:){6}(?:${v4}|:${v6segment}|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4 -(?:${v6segment}:){5}(?::${v4}|(?::${v6segment}){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4 -(?:${v6segment}:){4}(?:(?::${v6segment}){0,1}:${v4}|(?::${v6segment}){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4 -(?:${v6segment}:){3}(?:(?::${v6segment}){0,2}:${v4}|(?::${v6segment}){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4 -(?:${v6segment}:){2}(?:(?::${v6segment}){0,3}:${v4}|(?::${v6segment}){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4 -(?:${v6segment}:){1}(?:(?::${v6segment}){0,4}:${v4}|(?::${v6segment}){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4 -(?::(?:(?::${v6segment}){0,5}:${v4}|(?::${v6segment}){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4 -)(?:%[0-9a-zA-Z]{1,})? // %eth0 %1 -`.replace(/\s*\/\/.*$/gm, '').replace(/\n/g, '').trim(); - -// Pre-compile only the exact regexes because adding a global flag make regexes stateful -const v46Exact = new RegExp(`(?:^${v4}$)|(?:^${v6}$)`); -const v4exact = new RegExp(`^${v4}$`); -const v6exact = new RegExp(`^${v6}$`); - -const ipRegex = options => options && options.exact - ? v46Exact - : new RegExp(`(?:${boundry(options)}${v4}${boundry(options)})|(?:${boundry(options)}${v6}${boundry(options)})`, 'g'); - -ipRegex.v4 = options => options && options.exact ? v4exact : new RegExp(`${boundry(options)}${v4}${boundry(options)}`, 'g'); -ipRegex.v6 = options => options && options.exact ? v6exact : new RegExp(`${boundry(options)}${v6}${boundry(options)}`, 'g'); - -async function resolveCertificate(options) { - let https; - if (typeof options === "object" && options.key && options.cert) { - https = await resolveCert(options); - if (options.passphrase) { - https.passphrase = options.passphrase; - } - } else if (typeof options === "object" && options.pfx) { - const pfx = await resolvePfx(options); - if (!pfx.safeContents || pfx.safeContents.length < 2 || pfx.safeContents[0].safeBags.length === 0 || pfx.safeContents[1].safeBags.length === 0) { - throw new Error("keystore not containing a cert AND a key"); - } - const _cert = pfx.safeContents[0].safeBags[0].cert; - const _key = pfx.safeContents[1].safeBags[0].key; - https = { - key: forge.pki.privateKeyToPem(_key), - cert: forge.pki.certificateToPem(_cert) - }; - } else { - const { cert } = await generateCertificates(options); - https = cert; - } - return https; -} -async function generateCertificates(options) { - const defaults = { - commonName: "localhost", - countryCode: "US", - state: "Michigan", - locality: "Berkley", - organization: "Testing Corp", - organizationalUnit: "IT department", - domains: ["localhost", "127.0.0.1", "::1"], - validityDays: 1, - bits: 2048 - }; - const caOptions = defu(options, defaults); - caOptions.passphrase = options.signingKeyPassphrase; - const ca = await generateCACert(caOptions); - const domains = Array.isArray(options.domains) ? options.domains : ["localhost", "127.0.0.1", "::1"]; - const certOptions = defu(options, defaults); - const cert = await generateTLSCert({ - ...certOptions, - signingKeyCert: ca.cert, - signingKey: ca.key, - domains - }); - return { ca, cert }; -} -async function resolveCert(options) { - if (options && options.key && options.cert) { - const isInline = (s = "") => s.startsWith("--"); - const r = (s) => isInline(s) ? s : promises.readFile(s, "utf8"); - return { - key: await r(options.key), - cert: await r(options.cert) - }; - } - throw new Error("Certificate or Private Key not present"); -} -async function resolvePfx(options) { - if (options && options.pfx) { - const pfx = await promises.readFile(options.pfx, "binary"); - const p12Asn1 = forge.asn1.fromDer(pfx); - if (options.passphrase) { - return forge.pkcs12.pkcs12FromAsn1(p12Asn1, options.passphrase); - } - return forge.pkcs12.pkcs12FromAsn1(p12Asn1, ""); - } - throw new Error("Error resolving the pfx store"); -} -function createAttributes(options) { - return [ - options.commonName && { name: "commonName", value: options.commonName }, - options.countryCode && { name: "countryName", value: options.countryCode }, - options.state && { name: "stateOrProvinceName", value: options.state }, - options.locality && { name: "localityName", value: options.locality }, - options.organization && { - name: "organizationName", - value: options.organization - }, - options.organizationalUnit && { - name: "organizationalUnitName", - value: options.organizationalUnit - }, - options.emailAddress && { - name: "emailAddress", - value: options.emailAddress - } - ].filter(Boolean); -} -function createCertificateInfo(options) { - if (!options.domains || options.domains && options.domains.length === 0) { - options.domains = ["localhost.local"]; - } - options.commonName = options.commonName || options.domains[0]; - const attributes = createAttributes(options); - const extensions = [ - { name: "basicConstraints", cA: false, critical: true }, - { - name: "keyUsage", - digitalSignature: true, - keyEncipherment: true, - critical: true - }, - { name: "extKeyUsage", serverAuth: true, clientAuth: true }, - { - name: "subjectAltName", - altNames: options.domains.map((domain) => { - const types = { domain: 2, ip: 7 }; - const isIp = ipRegex({ exact: true }).test(domain); - if (isIp) { - return { type: types.ip, ip: domain }; - } - return { type: types.domain, value: domain }; - }) - } - ]; - return { attributes, extensions }; -} -function createCaInfo(options) { - const attributes = createAttributes(options); - const extensions = [ - { name: "basicConstraints", cA: true, critical: true }, - { name: "keyUsage", keyCertSign: true, critical: true } - ]; - return { attributes, extensions }; -} -async function generateTLSCert(options) { - const { attributes, extensions } = createCertificateInfo(options); - const ca = forge.pki.certificateFromPem(options.signingKeyCert); - return await generateCert({ - bits: options.bits, - subject: attributes, - issuer: ca.subject.attributes, - extensions, - validityDays: options.validityDays || 1, - signingKey: options.signingKey, - signingKeyPassphrase: options.signingKeyPassphrase, - passphrase: options.passphrase - }); -} -async function generateCACert(options = {}) { - const { attributes, extensions } = createCaInfo(options); - return await generateCert({ - ...options, - bits: options.bits || 2048, - subject: attributes, - issuer: attributes, - extensions, - validityDays: options.validityDays || 1 - }); -} -function signCertificate(options, cert) { - if (options.signingKey) { - if (isValidPassphrase(options.signingKeyPassphrase)) { - const encryptedPrivateKey = forge.pki.encryptedPrivateKeyFromPem( - options.signingKey - ); - const decryptedPrivateKey = forge.pki.decryptPrivateKeyInfo( - encryptedPrivateKey, - options.signingKeyPassphrase - ); - cert.sign( - forge.pki.privateKeyFromAsn1(decryptedPrivateKey), - forge.md.sha256.create() - ); - } else { - cert.sign( - forge.pki.privateKeyFromPem(options.signingKey), - forge.md.sha256.create() - ); - } - } else { - cert.sign(cert.privateKey, forge.md.sha256.create()); - } -} -function createCertificateFromKeyPair(keyPair, options) { - const serial = Math.floor(Math.random() * 95e3 + 5e4).toString(); - const cert = forge.pki.createCertificate(); - cert.publicKey = keyPair.publicKey; - cert.privateKey = keyPair.privateKey; - cert.serialNumber = Buffer.from(serial).toString("hex"); - cert.validity.notBefore = /* @__PURE__ */ new Date(); - cert.validity.notAfter = /* @__PURE__ */ new Date(); - cert.validity.notAfter.setDate( - cert.validity.notAfter.getDate() + options.validityDays - ); - cert.setSubject(options.subject); - cert.setIssuer(options.issuer); - cert.setExtensions(options.extensions); - return cert; -} -async function generateKeyPair(bits = 2048) { - const _generateKeyPair = promisify( - forge.pki.rsa.generateKeyPair.bind(forge.pki.rsa) - ); - return await _generateKeyPair({ - bits, - workers: os.availableParallelism ? os.availableParallelism() : os.cpus().length - }); -} -function isValidPassphrase(passphrase) { - return typeof passphrase === "string" && passphrase.length < 2e3; -} -async function generateCert(options) { - const keyPair = await generateKeyPair(options.bits); - const cert = createCertificateFromKeyPair(keyPair, options); - if (isValidPassphrase(options.passphrase)) { - const asn1PrivateKey = forge.pki.privateKeyToAsn1(keyPair.privateKey); - const privateKeyInfo = forge.pki.wrapRsaPrivateKey(asn1PrivateKey); - const encryptedPrivateKeyInfo = forge.pki.encryptPrivateKeyInfo( - privateKeyInfo, - options.passphrase, - { - algorithm: "aes256" - } - ); - signCertificate( - { - signingKey: options.signingKey, - signingKeyPassphrase: options.signingKeyPassphrase - }, - cert - ); - return { - key: forge.pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo), - cert: forge.pki.certificateToPem(cert), - passphrase: options.passphrase - }; - } else { - signCertificate( - { - signingKey: options.signingKey, - signingKeyPassphrase: options.signingKeyPassphrase - }, - cert - ); - return { - key: forge.pki.privateKeyToPem(keyPair.privateKey), - cert: forge.pki.certificateToPem(cert) - }; - } -} - -async function listen(handle, _options = {}) { - const _isProd = _options.isProd ?? process.env.NODE_ENV === "production"; - const _isTest = _options.isTest ?? process.env.NODE_ENV === "test"; - const _hostname = _options.hostname ?? process.env.HOST; - const _public = _options.public ?? (isLocalhost(_hostname) ? false : void 0) ?? (isAnyhost(_hostname) ? true : void 0) ?? (process.argv.includes("--host") ? true : void 0) ?? _isProd; - const listhenOptions = defu(_options, { - name: "", - https: false, - port: process.env.PORT || 3e3, - hostname: _hostname ?? getDefaultHost(_public), - showURL: true, - baseURL: "/", - open: false, - clipboard: false, - isTest: _isTest, - isProd: _isProd, - public: _public, - autoClose: true - }); - listhenOptions.hostname = validateHostname( - listhenOptions.hostname, - listhenOptions.public - ); - const _localhost = isLocalhost(listhenOptions.hostname); - const _anyhost = isAnyhost(listhenOptions.hostname); - if (listhenOptions.public && _localhost) { - consola.warn( - `[listhen] Trying to listhen on private host ${JSON.stringify( - listhenOptions.hostname - )} with public option enabled.` - ); - listhenOptions.public = false; - } else if (!listhenOptions.public && _anyhost && !(isWsl() || isDocker())) { - consola.warn( - `[listhen] Trying to listhen on public host ${JSON.stringify( - listhenOptions.hostname - )} with public option disabled. Using "localhost".` - ); - listhenOptions.public = false; - listhenOptions.hostname = "localhost"; - } - if (listhenOptions.isTest) { - listhenOptions.showURL = false; - } - if (listhenOptions.isProd || listhenOptions.isTest) { - listhenOptions.open = false; - listhenOptions.clipboard = false; - } - const port = listhenOptions.port = await getPort({ - port: Number(listhenOptions.port), - verbose: !listhenOptions.isTest, - host: listhenOptions.hostname, - alternativePortRange: [3e3, 3100], - public: listhenOptions.public, - ...typeof listhenOptions.port === "object" && listhenOptions.port - }); - let server; - let https = false; - const httpsOptions = listhenOptions.https; - let _addr; - if (httpsOptions) { - https = await resolveCertificate(httpsOptions); - server = createServer$1(https, handle); - addShutdown(server); - await promisify(server.listen.bind(server))(port, listhenOptions.hostname); - _addr = server.address(); - listhenOptions.port = _addr.port; - } else { - server = createServer$2(handle); - addShutdown(server); - await promisify(server.listen.bind(server))(port, listhenOptions.hostname); - _addr = server.address(); - listhenOptions.port = _addr.port; - } - if (listhenOptions.ws) { - if (typeof listhenOptions.ws === "function") { - server.on("upgrade", listhenOptions.ws); - } else { - consola.warn( - "[listhen] Using experimental websocket API. Learn more: `https://crossws.unjs.io`" - ); - const nodeWSAdapter = await import('./node.mjs').then( - (r) => r.default || r - ); - const { handleUpgrade } = nodeWSAdapter({ - ...listhenOptions.ws - }); - server.on("upgrade", handleUpgrade); - } - } - const getURL = (host = listhenOptions.hostname, baseURL) => generateURL(host, listhenOptions, baseURL); - let tunnel; - if (listhenOptions.tunnel) { - const { startTunnel } = await import('./index5.mjs'); - tunnel = await startTunnel({ - url: getURL() - }); - } - let _closed = false; - const close = async () => { - if (_closed) { - return; - } - _closed = true; - await promisify(server.shutdown)().catch(() => { - }); - await tunnel?.close().catch(() => { - }); - }; - if (listhenOptions.clipboard) { - const clipboardy = await import('./index6.mjs').then((r) => r.default || r); - await clipboardy.write(getURL()).catch(() => { - listhenOptions.clipboard = false; - }); - } - const getURLs = async (getURLOptions = {}) => { - const urls = []; - const _addURL = (type, url) => { - if (!urls.some((u) => u.url === url)) { - urls.push({ - url, - type - }); - } - }; - const publicURL = getURLOptions.publicURL || getPublicURL(listhenOptions, getURLOptions.baseURL); - if (publicURL) { - _addURL("network", publicURL); - } - if (_localhost || _anyhost) { - _addURL("local", getURL(listhenOptions.hostname, getURLOptions.baseURL)); - } - if (tunnel) { - _addURL("tunnel", await tunnel.getURL()); - } - if (listhenOptions.public) { - const _ipv6Host = listhenOptions.hostname.includes(":"); - for (const addr of getNetworkInterfaces(_ipv6Host)) { - if (addr === publicURL) { - continue; - } - _addURL("network", getURL(addr, getURLOptions.baseURL)); - } - } - return urls; - }; - const showURL = async (showURLOptions = {}) => { - const lines = []; - const nameSuffix = showURLOptions.name || listhenOptions.name ? ` (${showURLOptions.name || listhenOptions.name})` : ""; - const urls = await getURLs(showURLOptions); - const firstLocalUrl = urls.find((u) => u.type === "local"); - const firstPublicUrl = urls.find((u) => u.type !== "local"); - const showQR = (showURLOptions.qr ?? listhenOptions.qr) !== false; - if (firstPublicUrl && showQR) { - const space = " ".repeat(14); - lines.push(" "); - lines.push( - ...renderUnicodeCompact(firstPublicUrl.url).split("\n").map((line) => space + line) - ); - lines.push(" "); - } - const typeMap = { - local: ["Local", "green"], - tunnel: ["Tunnel", "yellow"], - network: ["Network", "magenta"] - }; - for (const url of urls) { - const type = typeMap[url.type]; - const label = getColor(type[1])( - ` \u279C ${(type[0] + ":").padEnd(8, " ")}${nameSuffix} ` - ); - let suffix = ""; - if (url === firstLocalUrl && listhenOptions.clipboard) { - suffix += colors.gray(" [copied to clipboard]"); - } - if (url === firstPublicUrl && showQR) { - suffix += colors.gray(" [QR code]"); - } - lines.push(`${label} ${formatURL(url.url)}${suffix}`); - } - if (!firstPublicUrl) { - lines.push( - colors.gray(` \u279C Network: use ${colors.white("--host")} to expose`) - ); - } - console.log("\n" + lines.join("\n") + "\n"); - }; - if (listhenOptions.showURL) { - showURL(); - } - const _open = async () => { - await open(getURL()).catch(() => { - }); - }; - if (listhenOptions.open) { - await _open(); - } - if (listhenOptions.autoClose) { - process.setMaxListeners(0); - process.once("exit", () => close()); - process.once("SIGINT", () => process.exit(0)); - process.once("SIGTERM", () => process.exit(0)); - process.once("SIGHUP", () => process.exit(0)); - } - return { - url: getURL(), - https, - server, - address: _addr, - open: _open, - showURL, - getURLs, - close - }; -} - -export { listen }; diff --git a/.pnpm-store/v3/files/3d/b7fbd7d9a51d6dea86e1da79da7f14ee22c5af122c6b23d9929d8d6e9ddaf9211d225640de86ab8e83c960d07b9ba8127a1de24810c01bb65efbabbfc014c6 b/.pnpm-store/v3/files/3d/b7fbd7d9a51d6dea86e1da79da7f14ee22c5af122c6b23d9929d8d6e9ddaf9211d225640de86ab8e83c960d07b9ba8127a1de24810c01bb65efbabbfc014c6 deleted file mode 100644 index 12e3954314d9d6ec074cabb40e4b6ccb9e8dd788..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/3d/b7fbd7d9a51d6dea86e1da79da7f14ee22c5af122c6b23d9929d8d6e9ddaf9211d225640de86ab8e83c960d07b9ba8127a1de24810c01bb65efbabbfc014c6 +++ /dev/null @@ -1,111 +0,0 @@ -import { d as defineCommand, c as consola } from '../shared/nuxi.9edf0930.mjs'; -import 'node:util'; -import 'node:path'; -import 'node:process'; -import 'node:tty'; -import { l as loadKit } from '../shared/nuxi.dc1b30dc.mjs'; -import { a as clearBuildDir } from '../shared/nuxi.1ff5d6e2.mjs'; -import { o as overrideEnv } from '../shared/nuxi.2509f57e.mjs'; -import { s as showVersions } from '../shared/nuxi.c8477004.mjs'; -import { s as sharedArgs, l as legacyRootDirArgs, r as resolve, a as relative } from '../shared/nuxi.610c92ff.mjs'; -import 'node:url'; -import '../shared/nuxi.1902c37d.mjs'; -import 'node:module'; -import 'node:fs'; -import '../shared/nuxi.53f5921c.mjs'; -import 'node:assert'; -import 'node:v8'; -import 'node:perf_hooks'; -import '../shared/nuxi.eaa29140.mjs'; -import './satisfies.mjs'; -import '../shared/nuxi.2155838d.mjs'; -import '../shared/nuxi.cc8dd4a9.mjs'; -import '../shared/nuxi.73800aa7.mjs'; -import 'crypto'; -import 'fs'; -import 'module'; -import 'path'; -import 'perf_hooks'; -import 'os'; -import 'vm'; -import 'url'; -import 'assert'; -import 'process'; -import 'v8'; -import 'util'; -import 'tty'; -import '../shared/nuxi.d3241ca4.mjs'; -import '../shared/nuxi.5aaa4630.mjs'; - -const buildCommand = defineCommand({ - meta: { - name: "build", - description: "Build Nuxt for production deployment" - }, - args: { - ...sharedArgs, - prerender: { - type: "boolean", - description: "Build Nuxt and prerender static routes" - }, - preset: { - type: "string", - description: "Nitro server preset" - }, - dotenv: { - type: "string", - description: "Path to .env file" - }, - ...legacyRootDirArgs - }, - async run(ctx) { - overrideEnv("production"); - const cwd = resolve(ctx.args.cwd || ctx.args.rootDir || "."); - showVersions(cwd); - const kit = await loadKit(cwd); - const nitroPreset = ctx.args.prerender ? "static" : ctx.args.preset; - if (nitroPreset) { - consola.info(`Using Nitro server preset: \`${nitroPreset}\``); - } - const nuxt = await kit.loadNuxt({ - cwd, - dotenv: { - cwd, - fileName: ctx.args.dotenv - }, - overrides: { - logLevel: ctx.args.logLevel, - // TODO: remove in 3.8 - _generate: ctx.args.prerender, - ...ctx.args.prerender ? { nitro: { static: true } } : { nitro: { preset: nitroPreset } }, - ...ctx.data?.overrides - } - }); - let nitro; - try { - nitro = kit.useNitro?.(); - } catch { - } - await clearBuildDir(nuxt.options.buildDir); - await kit.writeTypes(nuxt); - nuxt.hook("build:error", (err) => { - consola.error("Nuxt Build Error:", err); - process.exit(1); - }); - await kit.buildNuxt(nuxt); - if (ctx.args.prerender) { - if (!nuxt.options.ssr) { - consola.warn( - "HTML content not prerendered because `ssr: false` was set. You can read more in `https://nuxt.com/docs/getting-started/deployment#static-hosting`." - ); - } - const dir = nitro?.options.output.publicDir; - const publicDir = dir ? relative(process.cwd(), dir) : ".output/public"; - consola.success( - `You can now deploy \`${publicDir}\` to any static hosting!` - ); - } - } -}); - -export { buildCommand as default }; diff --git a/.pnpm-store/v3/files/4b/b0a55a58f0ff2ae7dc7ba0e9bfa03a5995b979d1ac38389e0dca4e17bc5efa9be144c5c9808385bbe90e001177e3d5272086e6f09c8ea7808851179fff4dcf b/.pnpm-store/v3/files/4b/b0a55a58f0ff2ae7dc7ba0e9bfa03a5995b979d1ac38389e0dca4e17bc5efa9be144c5c9808385bbe90e001177e3d5272086e6f09c8ea7808851179fff4dcf deleted file mode 100644 index bb0a1d8954cf8185e913e19eeaf9d2dc9c4500be..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/4b/b0a55a58f0ff2ae7dc7ba0e9bfa03a5995b979d1ac38389e0dca4e17bc5efa9be144c5c9808385bbe90e001177e3d5272086e6f09c8ea7808851179fff4dcf +++ /dev/null @@ -1,11 +0,0 @@ -const overrideEnv = (targetEnv) => { - const currentEnv = process.env.NODE_ENV; - if (currentEnv && currentEnv !== targetEnv) { - console.warn( - `Changing \`NODE_ENV\` from \`${currentEnv}\` to \`${targetEnv}\`, to avoid unintended behavior.` - ); - } - process.env.NODE_ENV = targetEnv; -}; - -export { overrideEnv as o }; diff --git a/.pnpm-store/v3/files/51/5444e545d62ea7d0ba8944d63b3a530262133943fb51aacd3f9df2e2d38891dd73d6ee7ae0ecf400c495623110e494e9e4a9d60dee72e145e447e4ce40e1c8 b/.pnpm-store/v3/files/51/5444e545d62ea7d0ba8944d63b3a530262133943fb51aacd3f9df2e2d38891dd73d6ee7ae0ecf400c495623110e494e9e4a9d60dee72e145e447e4ce40e1c8 deleted file mode 100644 index 05e1f6183d618170c19b8810ab5757cbc8470ffa..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/51/5444e545d62ea7d0ba8944d63b3a530262133943fb51aacd3f9df2e2d38891dd73d6ee7ae0ecf400c495623110e494e9e4a9d60dee72e145e447e4ce40e1c8 +++ /dev/null @@ -1,74 +0,0 @@ -import { execa } from './index3.mjs'; -import { d as defineCommand, c as consola } from '../shared/nuxi.9edf0930.mjs'; -import 'node:util'; -import 'node:path'; -import 'node:process'; -import 'node:tty'; -import { t as tryResolveModule } from '../shared/nuxi.1902c37d.mjs'; -import { s as sharedArgs, l as legacyRootDirArgs, r as resolve } from '../shared/nuxi.610c92ff.mjs'; -import 'node:buffer'; -import 'node:child_process'; -import '../shared/nuxi.2155838d.mjs'; -import 'child_process'; -import 'path'; -import 'fs'; -import 'node:url'; -import 'node:os'; -import 'node:fs'; -import 'node:timers/promises'; -import 'stream'; -import 'node:module'; -import '../shared/nuxi.53f5921c.mjs'; -import 'node:assert'; -import 'node:v8'; - -const MODULE_BUILDER_PKG = "@nuxt/module-builder"; -const buildModule = defineCommand({ - meta: { - name: "build-module", - description: `Helper command for using ${MODULE_BUILDER_PKG}` - }, - args: { - ...sharedArgs, - ...legacyRootDirArgs, - stub: { - type: "boolean", - description: "Stub dist instead of actually building it for development" - }, - sourcemap: { - type: "boolean", - description: "Generate sourcemaps" - }, - prepare: { - type: "boolean", - description: "Prepare module for local development" - } - }, - async run(ctx) { - const cwd = resolve(ctx.args.cwd || ctx.args.rootDir || "."); - const hasLocal = await tryResolveModule( - `${MODULE_BUILDER_PKG}/package.json`, - cwd - ); - const execArgs = Object.entries({ - "--stub": ctx.args.stub, - "--sourcemap": ctx.args.sourcemap, - "--prepare": ctx.args.prepare - }).filter(([, value]) => value).map(([key]) => key); - let cmd = "nuxt-module-build"; - if (!hasLocal) { - consola.warn( - `Cannot find locally installed version of \`${MODULE_BUILDER_PKG}\` (>=0.2.0). Falling back to \`npx ${MODULE_BUILDER_PKG}\`` - ); - cmd = "npx"; - execArgs.unshift(MODULE_BUILDER_PKG); - } - await execa(cmd, execArgs, { - cwd, - preferLocal: true, - stdio: "inherit" - }); - } -}); - -export { buildModule as default }; diff --git a/.pnpm-store/v3/files/5f/18bb5fb155a80f7e4a82b0538a894e8586b6a0e0cdb5a5630a4c0b51701578a13b9ec1e715c02d76afcac30c87c138bb0aa41902630a291af525cc192ce3ca b/.pnpm-store/v3/files/5f/18bb5fb155a80f7e4a82b0538a894e8586b6a0e0cdb5a5630a4c0b51701578a13b9ec1e715c02d76afcac30c87c138bb0aa41902630a291af525cc192ce3ca deleted file mode 100644 index 5cba810ec73a79c29706de846746655fd3f0879c..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/5f/18bb5fb155a80f7e4a82b0538a894e8586b6a0e0cdb5a5630a4c0b51701578a13b9ec1e715c02d76afcac30c87c138bb0aa41902630a291af525cc192ce3ca +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) Nuxt Team - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/.pnpm-store/v3/files/6c/a67d19868ce8638ae0aaa9e4c9cfb6d89bae6f92cdf40f64ad03612309e401c10b6bf645e0c96e86224733d3bc6e05f6c77e1d36179eb5553bce5440176176 b/.pnpm-store/v3/files/6c/a67d19868ce8638ae0aaa9e4c9cfb6d89bae6f92cdf40f64ad03612309e401c10b6bf645e0c96e86224733d3bc6e05f6c77e1d36179eb5553bce5440176176 deleted file mode 100644 index 666679ce05a3d32ff3d8da069b2bf2386ec1fc40..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/6c/a67d19868ce8638ae0aaa9e4c9cfb6d89bae6f92cdf40f64ad03612309e401c10b6bf645e0c96e86224733d3bc6e05f6c77e1d36179eb5553bce5440176176 +++ /dev/null @@ -1,10 +0,0 @@ -declare const main: any; - -declare const runMain: () => Promise; -declare function runCommand(name: string, argv?: string[], data?: { - overrides?: Record; -}): Promise<{ - result: unknown; -}>; - -export { main, runCommand, runMain }; diff --git a/.pnpm-store/v3/files/73/2d794726dfb64b23b283a438d1a7003c65b70cfdc5d7e582c38e4f6bdb7f22fd27d8507308516db0ecec751ef57b5c5fb44898463960b8346bb91f21af56de b/.pnpm-store/v3/files/73/2d794726dfb64b23b283a438d1a7003c65b70cfdc5d7e582c38e4f6bdb7f22fd27d8507308516db0ecec751ef57b5c5fb44898463960b8346bb91f21af56de deleted file mode 100644 index 107f12570d697d1a4273f48509bc846d443a291a..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/73/2d794726dfb64b23b283a438d1a7003c65b70cfdc5d7e582c38e4f6bdb7f22fd27d8507308516db0ecec751ef57b5c5fb44898463960b8346bb91f21af56de +++ /dev/null @@ -1,319 +0,0 @@ -import process from 'node:process'; -import os from 'node:os'; -import fs from 'node:fs'; -import { execa, execaSync } from './index3.mjs'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { promisify } from 'node:util'; -import childProcess from 'node:child_process'; -import 'node:buffer'; -import '../shared/nuxi.2155838d.mjs'; -import 'child_process'; -import 'path'; -import 'fs'; -import 'node:timers/promises'; -import 'stream'; - -let isDockerCached; - -function hasDockerEnv() { - try { - fs.statSync('/.dockerenv'); - return true; - } catch { - return false; - } -} - -function hasDockerCGroup() { - try { - return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker'); - } catch { - return false; - } -} - -function isDocker() { - // TODO: Use `??=` when targeting Node.js 16. - if (isDockerCached === undefined) { - isDockerCached = hasDockerEnv() || hasDockerCGroup(); - } - - return isDockerCached; -} - -let cachedResult; - -// Podman detection -const hasContainerEnv = () => { - try { - fs.statSync('/run/.containerenv'); - return true; - } catch { - return false; - } -}; - -function isInsideContainer() { - // TODO: Use `??=` when targeting Node.js 16. - if (cachedResult === undefined) { - cachedResult = hasContainerEnv() || isDocker(); - } - - return cachedResult; -} - -const isWsl = () => { - if (process.platform !== 'linux') { - return false; - } - - if (os.release().toLowerCase().includes('microsoft')) { - if (isInsideContainer()) { - return false; - } - - return true; - } - - try { - return fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft') - ? !isInsideContainer() : false; - } catch { - return false; - } -}; - -const isWSL = process.env.__IS_WSL_TEST__ ? isWsl : isWsl(); - -const handler = error => { - if (error.code === 'ENOENT') { - throw new Error('Couldn\'t find the termux-api scripts. You can install them with: apt install termux-api'); - } - - throw error; -}; - -const clipboard$4 = { - async copy(options) { - try { - await execa('termux-clipboard-set', options); - } catch (error) { - handler(error); - } - }, - async paste(options) { - try { - const {stdout} = await execa('termux-clipboard-get', options); - return stdout; - } catch (error) { - handler(error); - } - }, - copySync(options) { - try { - execaSync('termux-clipboard-set', options); - } catch (error) { - handler(error); - } - }, - pasteSync(options) { - try { - return execaSync('termux-clipboard-get', options).stdout; - } catch (error) { - handler(error); - } - }, -}; - -const termux = clipboard$4; - -const __dirname$1 = path.dirname(fileURLToPath(import.meta.url)); - -const xsel = 'xsel'; -const xselFallback = path.join(__dirname$1, '../fallbacks/linux/xsel'); - -const copyArguments = ['--clipboard', '--input']; -const pasteArguments = ['--clipboard', '--output']; - -const makeError = (xselError, fallbackError) => { - let error; - if (xselError.code === 'ENOENT') { - error = new Error('Couldn\'t find the `xsel` binary and fallback didn\'t work. On Debian/Ubuntu you can install xsel with: sudo apt install xsel'); - } else { - error = new Error('Both xsel and fallback failed'); - error.xselError = xselError; - } - - error.fallbackError = fallbackError; - return error; -}; - -const xselWithFallback = async (argumentList, options) => { - try { - const {stdout} = await execa(xsel, argumentList, options); - return stdout; - } catch (xselError) { - try { - const {stdout} = await execa(xselFallback, argumentList, options); - return stdout; - } catch (fallbackError) { - throw makeError(xselError, fallbackError); - } - } -}; - -const xselWithFallbackSync = (argumentList, options) => { - try { - return execaSync(xsel, argumentList, options).stdout; - } catch (xselError) { - try { - return execaSync(xselFallback, argumentList, options).stdout; - } catch (fallbackError) { - throw makeError(xselError, fallbackError); - } - } -}; - -const clipboard$3 = { - async copy(options) { - await xselWithFallback(copyArguments, options); - }, - copySync(options) { - xselWithFallbackSync(copyArguments, options); - }, - paste: options => xselWithFallback(pasteArguments, options), - pasteSync: options => xselWithFallbackSync(pasteArguments, options), -}; - -const linux = clipboard$3; - -const env = { - LC_CTYPE: 'UTF-8', // eslint-disable-line unicorn/text-encoding-identifier-case -}; - -const clipboard$2 = { - copy: async options => execa('pbcopy', {...options, env}), - async paste(options) { - const {stdout} = await execa('pbpaste', {...options, env}); - return stdout; - }, - copySync: options => execaSync('pbcopy', {...options, env}), - pasteSync: options => execaSync('pbpaste', {...options, env}).stdout, -}; - -const macos = clipboard$2; - -promisify(childProcess.execFile); - -function systemArchitectureSync() { - const {arch, platform, env} = process; - - // Detect Node.js x64 binary running under Rosetta 2 on a ARM64 Mac. - if (platform === 'darwin' && arch === 'x64') { - const stdout = childProcess.execFileSync('sysctl', ['-inq', 'sysctl.proc_translated'], {encoding: 'utf8'}); - return stdout.trim() === '1' ? 'arm64' : 'x64'; - } - - if (arch === 'arm64' || arch === 'x64') { - return arch; - } - - if (platform === 'win32' && Object.hasOwn(env, 'PROCESSOR_ARCHITEW6432')) { - return 'x64'; - } - - if (platform === 'linux') { - const stdout = childProcess.execFileSync('getconf', ['LONG_BIT'], {encoding: 'utf8'}); - if (stdout.trim() === '64') { - return 'x64'; - } - } - - return arch; -} - -const archtectures64bit = new Set([ - 'arm64', - 'x64', - 'ppc64', - 'riscv64', -]); - -function is64bitSync() { - return archtectures64bit.has(systemArchitectureSync()); -} - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); - -const binarySuffix = is64bitSync() ? 'x86_64' : 'i686'; - -// Binaries from: https://github.com/sindresorhus/win-clipboard -const windowBinaryPath = path.join(__dirname, `../fallbacks/windows/clipboard_${binarySuffix}.exe`); - -const clipboard$1 = { - copy: async options => execa(windowBinaryPath, ['--copy'], options), - async paste(options) { - const {stdout} = await execa(windowBinaryPath, ['--paste'], options); - return stdout; - }, - copySync: options => execaSync(windowBinaryPath, ['--copy'], options), - pasteSync: options => execaSync(windowBinaryPath, ['--paste'], options).stdout, -}; - -const windows = clipboard$1; - -const platformLib = (() => { - switch (process.platform) { - case 'darwin': { - return macos; - } - - case 'win32': { - return windows; - } - - case 'android': { - if (process.env.PREFIX !== '/data/data/com.termux/files/usr') { - throw new Error('You need to install Termux for this module to work on Android: https://termux.com'); - } - - return termux; - } - - default: { - // `process.platform === 'linux'` for WSL. - if (isWSL) { - return windows; - } - - return linux; - } - } -})(); - -const clipboard = {}; - -clipboard.write = async text => { - if (typeof text !== 'string') { - throw new TypeError(`Expected a string, got ${typeof text}`); - } - - await platformLib.copy({input: text}); -}; - -clipboard.read = async () => platformLib.paste({stripFinalNewline: false}); - -clipboard.writeSync = text => { - if (typeof text !== 'string') { - throw new TypeError(`Expected a string, got ${typeof text}`); - } - - platformLib.copySync({input: text}); -}; - -clipboard.readSync = () => platformLib.pasteSync({stripFinalNewline: false}); - -const clipboardy = clipboard; - -export { clipboardy as default }; diff --git a/.pnpm-store/v3/files/74/5579d31f220241999ae22d3b5672bdfd193e23f1f49c75b64bbd7746b1b2f10f4b3390839b0199c1a205be44fc15d9400755b2defbba4feec3640bbfaed3d0 b/.pnpm-store/v3/files/74/5579d31f220241999ae22d3b5672bdfd193e23f1f49c75b64bbd7746b1b2f10f4b3390839b0199c1a205be44fc15d9400755b2defbba4feec3640bbfaed3d0 deleted file mode 100644 index 6a9282e3ece056699ef0707d233d67a48b308ca4..0000000000000000000000000000000000000000 --- a/.pnpm-store/v3/files/74/5579d31f220241999ae22d3b5672bdfd193e23f1f49c75b64bbd7746b1b2f10f4b3390839b0199c1a205be44fc15d9400755b2defbba4feec3640bbfaed3d0 +++ /dev/null @@ -1,210 +0,0 @@ -import { existsSync, promises } from 'node:fs'; -import { d as defineCommand, c as consola } from '../shared/nuxi.9edf0930.mjs'; -import 'node:util'; -import 'node:path'; -import 'node:process'; -import 'node:tty'; -import { l as loadKit } from '../shared/nuxi.dc1b30dc.mjs'; -import { u as upperFirst } from '../shared/nuxi.349af404.mjs'; -import { s as sharedArgs, r as resolve, e as extname, d as dirname } from '../shared/nuxi.610c92ff.mjs'; -import 'node:url'; -import '../shared/nuxi.1902c37d.mjs'; -import 'node:module'; -import '../shared/nuxi.53f5921c.mjs'; -import 'node:assert'; -import 'node:v8'; -import 'node:perf_hooks'; -import '../shared/nuxi.eaa29140.mjs'; -import './satisfies.mjs'; -import '../shared/nuxi.2155838d.mjs'; -import '../shared/nuxi.cc8dd4a9.mjs'; -import '../shared/nuxi.73800aa7.mjs'; -import 'crypto'; -import 'fs'; -import 'module'; -import 'path'; -import 'perf_hooks'; -import 'os'; -import 'vm'; -import 'url'; -import 'assert'; -import 'process'; -import 'v8'; -import 'util'; -import 'tty'; - -const httpMethods = [ - "connect", - "delete", - "get", - "head", - "options", - "post", - "put", - "trace", - "patch" -]; -const api = ({ name, args }) => ({ - path: `server/api/${name}${applySuffix(args, httpMethods, "method")}.ts`, - contents: ` -export default defineEventHandler((event) => { - return 'Hello ${name}' -}) -` -}); -const plugin = ({ name, args }) => ({ - path: `plugins/${name}${applySuffix(args, ["client", "server"], "mode")}.ts`, - contents: ` -export default defineNuxtPlugin((nuxtApp) => {}) - ` -}); -const component = ({ name, args }) => ({ - path: `components/${name}${applySuffix( - args, - ["client", "server"], - "mode" - )}.vue`, - contents: ` -